Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like PHPCSHelper often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use PHPCSHelper, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
29 | class PHPCSHelper |
||
30 | { |
||
31 | |||
32 | /** |
||
33 | * Get the PHPCS version number. |
||
34 | * |
||
35 | * @return string |
||
36 | */ |
||
37 | public static function getVersion() |
||
47 | |||
48 | |||
49 | /** |
||
50 | * Pass config data to PHPCS. |
||
51 | * |
||
52 | * PHPCS cross-version compatibility helper. |
||
53 | * |
||
54 | * @param string $key The name of the config value. |
||
55 | * @param string|null $value The value to set. If null, the config entry |
||
56 | * is deleted, reverting it to the default value. |
||
57 | * @param boolean $temp Set this config data temporarily for this script run. |
||
58 | * This will not write the config data to the config file. |
||
59 | * |
||
60 | * @return void |
||
61 | */ |
||
62 | public static function setConfigData($key, $value, $temp = false) |
||
72 | |||
73 | |||
74 | /** |
||
75 | * Get the value of a single PHPCS config key. |
||
76 | * |
||
77 | * @param string $key The name of the config value. |
||
78 | * |
||
79 | * @return string|null |
||
80 | */ |
||
81 | public static function getConfigData($key) |
||
91 | |||
92 | |||
93 | /** |
||
94 | * Get the value of a single PHPCS config key. |
||
95 | * |
||
96 | * This config key can be set in the `CodeSniffer.conf` file, on the |
||
97 | * command-line or in a ruleset. |
||
98 | * |
||
99 | * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
||
100 | * @param string $key The name of the config value. |
||
101 | * |
||
102 | * @return string|null |
||
103 | */ |
||
104 | public static function getCommandLineData($phpcsFile, $key) |
||
122 | |||
123 | |||
124 | /** |
||
125 | * Returns the position of the first non-whitespace token in a statement. |
||
126 | * |
||
127 | * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` |
||
128 | * class and introduced in PHPCS 2.1.0 and improved in PHPCS 2.7.1. |
||
129 | * |
||
130 | * Once the minimum supported PHPCS version for this standard goes beyond |
||
131 | * that, this method can be removed and calls to it replaced with |
||
132 | * `$phpcsFile->findStartOfStatement($start, $ignore)` calls. |
||
133 | * |
||
134 | * Last synced with PHPCS version: PHPCS 3.3.2 at commit 6ad28354c04b364c3c71a34e4a18b629cc3b231e}} |
||
135 | * |
||
136 | * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. |
||
137 | * @param int $start The position to start searching from in the token stack. |
||
138 | * @param int|array $ignore Token types that should not be considered stop points. |
||
139 | * |
||
140 | * @return int |
||
141 | */ |
||
142 | public static function findStartOfStatement(File $phpcsFile, $start, $ignore = null) |
||
201 | |||
202 | |||
203 | /** |
||
204 | * Returns the position of the last non-whitespace token in a statement. |
||
205 | * |
||
206 | * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` |
||
207 | * class and introduced in PHPCS 2.1.0 and improved in PHPCS 2.7.1 and 3.3.0. |
||
208 | * |
||
209 | * Once the minimum supported PHPCS version for this standard goes beyond |
||
210 | * that, this method can be removed and calls to it replaced with |
||
211 | * `$phpcsFile->findEndOfStatement($start, $ignore)` calls. |
||
212 | * |
||
213 | * Last synced with PHPCS version: PHPCS 3.3.0-alpha at commit f5d899dcb5c534a1c3cca34668624517856ba823}} |
||
214 | * |
||
215 | * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. |
||
216 | * @param int $start The position to start searching from in the token stack. |
||
217 | * @param int|array $ignore Token types that should not be considered stop points. |
||
218 | * |
||
219 | * @return int |
||
220 | */ |
||
221 | public static function findEndOfStatement(\PHP_CodeSniffer_File $phpcsFile, $start, $ignore = null) |
||
295 | |||
296 | |||
297 | /** |
||
298 | * Returns the name of the class that the specified class extends |
||
299 | * (works for classes, anonymous classes and interfaces). |
||
300 | * |
||
301 | * Returns FALSE on error or if there is no extended class name. |
||
302 | * |
||
303 | * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` |
||
304 | * class, but with some improvements which have been introduced in |
||
305 | * PHPCS 2.8.0. |
||
306 | * {@link https://github.com/squizlabs/PHP_CodeSniffer/commit/0011d448119d4c568e3ac1f825ae78815bf2cc34}. |
||
307 | * |
||
308 | * Once the minimum supported PHPCS version for this standard goes beyond |
||
309 | * that, this method can be removed and calls to it replaced with |
||
310 | * `$phpcsFile->findExtendedClassName($stackPtr)` calls. |
||
311 | * |
||
312 | * Last synced with PHPCS version: PHPCS 3.1.0-alpha at commit a9efcc9b0703f3f9f4a900623d4e97128a6aafc6}} |
||
313 | * |
||
314 | * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. |
||
315 | * @param int $stackPtr The position of the class token in the stack. |
||
316 | * |
||
317 | * @return string|false |
||
318 | */ |
||
319 | public static function findExtendedClassName(\PHP_CodeSniffer_File $phpcsFile, $stackPtr) |
||
365 | |||
366 | |||
367 | /** |
||
368 | * Returns the name(s) of the interface(s) that the specified class implements. |
||
369 | * |
||
370 | * Returns FALSE on error or if there are no implemented interface names. |
||
371 | * |
||
372 | * {@internal Duplicate of same method as introduced in PHPCS 2.7. |
||
373 | * This method also includes an improvement we use which was only introduced |
||
374 | * in PHPCS 2.8.0, so only defer to upstream for higher versions. |
||
375 | * Once the minimum supported PHPCS version for this sniff library goes beyond |
||
376 | * that, this method can be removed and calls to it replaced with |
||
377 | * `$phpcsFile->findImplementedInterfaceNames($stackPtr)` calls.}} |
||
378 | * |
||
379 | * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
||
380 | * @param int $stackPtr The position of the class token. |
||
381 | * |
||
382 | * @return array|false |
||
383 | */ |
||
384 | public static function findImplementedInterfaceNames(\PHP_CodeSniffer_File $phpcsFile, $stackPtr) |
||
432 | |||
433 | |||
434 | /** |
||
435 | * Returns the method parameters for the specified function token. |
||
436 | * |
||
437 | * Each parameter is in the following format: |
||
438 | * |
||
439 | * <code> |
||
440 | * 0 => array( |
||
441 | * 'name' => '$var', // The variable name. |
||
442 | * 'token' => integer, // The stack pointer to the variable name. |
||
443 | * 'content' => string, // The full content of the variable definition. |
||
444 | * 'pass_by_reference' => boolean, // Is the variable passed by reference? |
||
445 | * 'variable_length' => boolean, // Is the param of variable length through use of `...` ? |
||
446 | * 'type_hint' => string, // The type hint for the variable. |
||
447 | * 'type_hint_token' => integer, // The stack pointer to the type hint |
||
448 | * // or false if there is no type hint. |
||
449 | * 'nullable_type' => boolean, // Is the variable using a nullable type? |
||
450 | * ) |
||
451 | * </code> |
||
452 | * |
||
453 | * Parameters with default values have an additional array index of |
||
454 | * 'default' with the value of the default as a string. |
||
455 | * |
||
456 | * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` |
||
457 | * class. |
||
458 | * |
||
459 | * Last synced with PHPCS version: PHPCS 3.3.0-alpha at commit 53a28408d345044c0360c2c1b4a2aaebf4a3b8c9}} |
||
460 | * |
||
461 | * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. |
||
462 | * @param int $stackPtr The position in the stack of the |
||
463 | * function token to acquire the |
||
464 | * parameters for. |
||
465 | * |
||
466 | * @return array|false |
||
467 | * @throws \PHP_CodeSniffer_Exception If the specified $stackPtr is not of |
||
468 | * type T_FUNCTION or T_CLOSURE. |
||
469 | */ |
||
470 | public static function getMethodParameters(\PHP_CodeSniffer_File $phpcsFile, $stackPtr) |
||
651 | } |
||
652 |
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.