diff --git a/Inpsyde/Sniffs/CodeQuality/DisableMagicSerializeSniff.php b/Inpsyde/Sniffs/CodeQuality/DisableMagicSerializeSniff.php index 4273777..e7cac85 100644 --- a/Inpsyde/Sniffs/CodeQuality/DisableMagicSerializeSniff.php +++ b/Inpsyde/Sniffs/CodeQuality/DisableMagicSerializeSniff.php @@ -11,12 +11,10 @@ class DisableMagicSerializeSniff implements Sniff { - /** @var list */ + /** @var array */ public array $disabledFunctions = [ - '__serialize', - '__sleep', - '__unserialize', - '__wakeup', + '__sleep' => '__serialize', + '__wakeup' => '__unserialize', ]; /** @@ -42,12 +40,10 @@ public function process(File $phpcsFile, $stackPtr): void } $name = FunctionDeclarations::getName($phpcsFile, $stackPtr); - if (in_array($name, $this->disabledFunctions, true)) { + $alternative = $this->disabledFunctions[$name] ?? null; + if ($alternative !== null) { $phpcsFile->addError( - sprintf( - 'The method "%s" is forbidden, please use Serializable interface.', - $name - ), + "The method '{$name}' is deprecated, please use '{$alternative}' instead.", $stackPtr, 'Found' ); diff --git a/Inpsyde/Sniffs/CodeQuality/DisableSerializeInterfaceSniff.php b/Inpsyde/Sniffs/CodeQuality/DisableSerializeInterfaceSniff.php new file mode 100644 index 0000000..5dad6ed --- /dev/null +++ b/Inpsyde/Sniffs/CodeQuality/DisableSerializeInterfaceSniff.php @@ -0,0 +1,52 @@ + + */ + public function register(): array + { + return [ + \T_CLASS, + \T_ANON_CLASS, + \T_ENUM, + \T_INTERFACE, + ]; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * @return void + * + * phpcs:disable Inpsyde.CodeQuality.ArgumentTypeDeclaration + */ + public function process(File $phpcsFile, $stackPtr): void + { + // phpcs:enable Inpsyde.CodeQuality.ArgumentTypeDeclaration + $tokenCode = $phpcsFile->getTokens()[$stackPtr]['code'] ?? null; + $find = ($tokenCode === \T_INTERFACE) + ? ObjectDeclarations::findExtendedInterfaceNames($phpcsFile, $stackPtr) + : ObjectDeclarations::findImplementedInterfaceNames($phpcsFile, $stackPtr); + + if (($find === false) || !in_array('Serializable', $find, true)) { + return; + } + + $phpcsFile->addError( + 'The Serializable interface is deprecated, ' + . 'please use __serialize and __unserialize instead.', + $stackPtr, + 'Found' + ); + } +} diff --git a/README.md b/README.md index 646d8c6..9b5ffcf 100644 --- a/README.md +++ b/README.md @@ -117,30 +117,31 @@ Some rules are also included from PHP_CodeSniffer itself, as well as [PHPCSExtra The following custom rules are in use: -| Sniff Name | Description | Has Config | Auto-Fixable | -|:---------------------------|:-----------------------------------------------------------------------------------------------|:----------:|:------------:| -| `ArgumentTypeDeclaration` | Enforce argument type declaration. | | | -| `DisableCallUserFunc` | Disable usage of `call_user_func`. | | | -| `DisableMagicSerialize` | Disable usage of `__serialize`, `__sleep`, `__unserialize`, `__wakeup`. | | | -| `DisallowShortOpenTag` | Disallow short open PHP tag (short echo tag allowed). | | | -| `ElementNameMinimalLength` | Use minimum 3 chars for names (with a few exclusions) | ✓ | | -| `EncodingComment` | Detect usage of opening `-*- coding: utf-8 -*-` | ✓ | ✓ | -| `ForbiddenPublicProperty` | No public class properties | | | -| `FunctionBodyStart` | Handle blank line at start of function body. | | ✓ | -| `FunctionLength` | Max 50 lines per function/method, excluding blank lines and comments-only lines. | ✓ | | -| `HookClosureReturn` | Ensure that actions callbacks do not return anything, while filter callbacks return something. | | | -| `HookPriority` | Report usage of `PHP_INT_MAX` and `PHP_INT_MIN` as hook priority. | | | -| `LineLength` | Max 100 chars per line | ✓ | | -| `NestingLevel` | Max indent level of 3 inside functions | ✓ | | -| `NoAccessors` | Discourage usage of getters and setters. | | | -| `NoElse` | Discourage usage of `else`. | | | -| `NoRootNamespaceFunctions` | Report usage of global functions in the root namespace. | | | -| `NoTopLevelDefine` | Discourage usage of `define` where `const` is preferable. | | | -| `PropertyPerClassLimit` | Discourage usage of more than 10 properties per class. | ✓ | | -| `Psr4` | Check PSR-4 compliance | ✓ | | -| `ReturnTypeDeclaration` | Enforce return type declaration | | | -| `StaticClosure` | Points closures that can be `static`. | | ✓ | -| `VariablesName` | Check variable (and properties) names | ✓ | | +| Sniff Name | Description | Has Config | Auto-Fixable | +|:----------------------------|:-----------------------------------------------------------------------------------------------|:----------:|:------------:| +| `ArgumentTypeDeclaration` | Enforce argument type declaration. | | | +| `DisableCallUserFunc` | Disable usage of `call_user_func`. | | | +| `DisableMagicSerialize` | Disable usage of `__sleep`, `__wakeup`. | | | +| `DisableSerializeInterface` | Disable usage of `Serializable` interface. | | | +| `DisallowShortOpenTag` | Disallow short open PHP tag (short echo tag allowed). | | | +| `ElementNameMinimalLength` | Use minimum 3 chars for names (with a few exclusions) | ✓ | | +| `EncodingComment` | Detect usage of opening `-*- coding: utf-8 -*-` | ✓ | ✓ | +| `ForbiddenPublicProperty` | No public class properties | | | +| `FunctionBodyStart` | Handle blank line at start of function body. | | ✓ | +| `FunctionLength` | Max 50 lines per function/method, excluding blank lines and comments-only lines. | ✓ | | +| `HookClosureReturn` | Ensure that actions callbacks do not return anything, while filter callbacks return something. | | | +| `HookPriority` | Report usage of `PHP_INT_MAX` and `PHP_INT_MIN` as hook priority. | | | +| `LineLength` | Max 100 chars per line | ✓ | | +| `NestingLevel` | Max indent level of 3 inside functions | ✓ | | +| `NoAccessors` | Discourage usage of getters and setters. | | | +| `NoElse` | Discourage usage of `else`. | | | +| `NoRootNamespaceFunctions` | Report usage of global functions in the root namespace. | | | +| `NoTopLevelDefine` | Discourage usage of `define` where `const` is preferable. | | | +| `PropertyPerClassLimit` | Discourage usage of more than 10 properties per class. | ✓ | | +| `Psr4` | Check PSR-4 compliance | ✓ | | +| `ReturnTypeDeclaration` | Enforce return type declaration | | | +| `StaticClosure` | Points closures that can be `static`. | | ✓ | +| `VariablesName` | Check variable (and properties) names | ✓ | | For **notes and configuration**, refer to the [`inpsyde-custom-sniffs.md`](/inpsyde-custom-sniffs.md) file in this repository. diff --git a/tests/unit/fixtures/disallow-magic-serialize.php b/tests/unit/fixtures/disallow-magic-serialize.php index c66710e..0ed833c 100644 --- a/tests/unit/fixtures/disallow-magic-serialize.php +++ b/tests/unit/fixtures/disallow-magic-serialize.php @@ -4,7 +4,6 @@ class Foo { - // @phpcsErrorOnNextLine public function __serialize(): array { return []; @@ -37,7 +36,6 @@ public function wakeup(): array return []; } - // @phpcsErrorOnNextLine public function __unserialize(): array { return []; diff --git a/tests/unit/fixtures/disallow-serialize-interface.php b/tests/unit/fixtures/disallow-serialize-interface.php new file mode 100644 index 0000000..1b7ab1f --- /dev/null +++ b/tests/unit/fixtures/disallow-serialize-interface.php @@ -0,0 +1,58 @@ +