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:
1 | <?php |
||
23 | class NewExtensionsSniff extends AbstractNewFeatureSniff |
||
24 | { |
||
25 | /** |
||
26 | * A list of functions to whitelist, if any. |
||
27 | * |
||
28 | * This is intended for projects using functions which start with the same |
||
29 | * prefix as one of the removed extensions. |
||
30 | * |
||
31 | * This property can be set from the ruleset, like so: |
||
32 | * <rule ref="PHPCompatibility.PHP.RemovedExtensions"> |
||
33 | * <properties> |
||
34 | * <property name="functionWhitelist" type="array" value="mysql_to_rfc3339,mysql_another_function" /> |
||
35 | * </properties> |
||
36 | * </rule> |
||
37 | * |
||
38 | * @var array |
||
39 | */ |
||
40 | public $functionWhitelist; |
||
41 | |||
42 | /** |
||
43 | * A list of new PHP extensions. |
||
44 | * |
||
45 | * The array lists : version number with false (available in PECL) and true (shipped with PHP). |
||
46 | * If's sufficient to list the first version where the extension was introduced. |
||
47 | * |
||
48 | * @var array(string|null) |
||
49 | */ |
||
50 | protected $newExtensions = array( |
||
51 | 'csprng' => array( |
||
52 | '7.0' => true, |
||
53 | 'prefixes' => array( |
||
54 | // Function prefix all functions: verified. |
||
55 | 'random_', // In practice: only random_bytes, random_int |
||
56 | // NO ini settings |
||
57 | // NO constants |
||
58 | ), |
||
59 | ), |
||
60 | 'fileinfo' => array( |
||
61 | '5.3' => true, |
||
62 | 'prefixes' => array( |
||
63 | // Function prefix all functions: verified. |
||
64 | 'finfo_' |
||
65 | // Also function: mime_content_type() |
||
66 | // Class: finfo |
||
67 | // NO ini settings |
||
68 | // Constants prefix: FILEINFO_ |
||
69 | ), |
||
70 | ), |
||
71 | 'hash' => array( |
||
72 | '5.1.2' => true, |
||
73 | 'prefixes' => array( |
||
74 | // Function prefix: verified. |
||
75 | 'hash_' |
||
76 | // Function `hash()` also exists!!!! |
||
|
|||
77 | // NO ini settings |
||
78 | // 1 constant: HASH_HMAC |
||
79 | ), |
||
80 | ), |
||
81 | 'opcache' => array( |
||
82 | '5.2' => false, |
||
83 | '5.5' => true, |
||
84 | 'prefixes' => array( |
||
85 | // Function prefix all functions: verified. |
||
86 | 'opcache_' |
||
87 | // ini prefix: `opcache.` |
||
88 | // NO constants |
||
89 | ), |
||
90 | ), |
||
91 | 'password' => array( |
||
92 | '5.5' => true, |
||
93 | 'prefixes' => array( |
||
94 | // Function prefix all functions: verified. |
||
95 | 'password_' |
||
96 | // NO ini settings |
||
97 | // 2 constants: PASSWORD_BCRYPT, PASSWORD_DEFAULT |
||
98 | ), |
||
99 | ), |
||
100 | 'phar' => array( |
||
101 | '5.3' => true, |
||
102 | 'prefixes' => array( |
||
103 | // NO functions, only classes. |
||
104 | // ini prefix: `phar.` |
||
105 | // constants - all class constants: `Phar::` |
||
106 | // Classes: Phar, PharData, PharFileInfo, PharException |
||
107 | ), |
||
108 | ), |
||
109 | |||
110 | /* |
||
111 | 'activescript' => array( |
||
112 | '5.1' => true, |
||
113 | 'alternative' => 'pecl/activescript', |
||
114 | ), |
||
115 | 'cpdf' => array( |
||
116 | '5.1' => true, |
||
117 | 'alternative' => 'pecl/pdflib', |
||
118 | ), |
||
119 | 'dbase' => array( |
||
120 | '5.3' => true, |
||
121 | 'alternative' => null, |
||
122 | 'separator' => '_', // Verified: all functions use separator. |
||
123 | ), |
||
124 | 'dbx' => array( |
||
125 | '5.1' => true, |
||
126 | 'alternative' => 'pecl/dbx', |
||
127 | 'separator' => '_', // Verified: all functions use separator. |
||
128 | ), |
||
129 | 'dio' => array( |
||
130 | '5.1' => true, |
||
131 | 'alternative' => 'pecl/dio', |
||
132 | 'separator' => '_', // Verified: all functions use separator. |
||
133 | ), |
||
134 | 'ereg' => array( |
||
135 | '5.3' => false, |
||
136 | '7.0' => true, |
||
137 | 'alternative' => 'pcre', |
||
138 | ), |
||
139 | 'fam' => array( |
||
140 | '5.1' => true, |
||
141 | 'alternative' => null, |
||
142 | 'separator' => '_', // Verified: all functions use separator. |
||
143 | ), |
||
144 | 'fbsql' => array( |
||
145 | '5.3' => true, |
||
146 | 'alternative' => null, |
||
147 | 'separator' => '_', // Verified: all functions use separator. |
||
148 | ), |
||
149 | 'fdf' => array( |
||
150 | '5.3' => true, |
||
151 | 'alternative' => 'pecl/fdf', |
||
152 | 'separator' => '_', // Verified: all functions use separator. |
||
153 | ), |
||
154 | 'filepro' => array( |
||
155 | '5.2' => true, |
||
156 | 'alternative' => null, |
||
157 | 'separator' => '_', // Verified: function 'filepro' exists - all other functions use separator. |
||
158 | ), |
||
159 | 'hw_api' => array( |
||
160 | '5.2' => true, |
||
161 | 'alternative' => null, |
||
162 | ), |
||
163 | 'ingres' => array( |
||
164 | '5.1' => true, |
||
165 | 'alternative' => 'pecl/ingres', |
||
166 | 'separator' => '_', // Verified: all functions use separator. |
||
167 | ), |
||
168 | 'ircg' => array( |
||
169 | '5.1' => true, |
||
170 | 'alternative' => null, |
||
171 | ), |
||
172 | 'mcrypt' => array( |
||
173 | '7.1' => false, |
||
174 | 'alternative' => 'openssl (preferred) or pecl/mcrypt once available', |
||
175 | 'separator' => '_', // Verified: all functions use separator, though there is also the mdecrypt_generic function. |
||
176 | ), |
||
177 | 'mcve' => array( |
||
178 | '5.1' => true, |
||
179 | 'alternative' => 'pecl/mvce', |
||
180 | ), |
||
181 | 'ming' => array( |
||
182 | '5.3' => true, |
||
183 | 'alternative' => 'pecl/ming', |
||
184 | ), |
||
185 | 'mnogosearch' => array( |
||
186 | '5.1' => true, |
||
187 | 'alternative' => null, |
||
188 | 'prefix' => 'udm', |
||
189 | 'separator' => '_', // Verified: all functions use separator. |
||
190 | ), |
||
191 | 'msql' => array( |
||
192 | '5.3' => true, |
||
193 | 'alternative' => null, |
||
194 | 'separator' => '_', // Verified: function 'msql' exists - all other functions use separator. |
||
195 | ), |
||
196 | 'mssql' => array( |
||
197 | '7.0' => true, |
||
198 | 'alternative' => null, |
||
199 | 'separator' => '_', // Verified: all functions use separator. |
||
200 | ), |
||
201 | 'mysql_' => array( |
||
202 | '5.5' => false, |
||
203 | '7.0' => true, |
||
204 | 'alternative' => 'mysqli', |
||
205 | 'separator' => '_', // Verified: all functions use separator. |
||
206 | ), |
||
207 | 'ncurses' => array( |
||
208 | '5.3' => true, |
||
209 | 'alternative' => 'pecl/ncurses', |
||
210 | 'separator' => '_', // Verified: all functions use separator. |
||
211 | ), |
||
212 | 'oracle' => array( |
||
213 | '5.1' => true, |
||
214 | 'alternative' => 'oci8 or pdo_oci', |
||
215 | ), |
||
216 | 'ovrimos' => array( |
||
217 | '5.1' => true, |
||
218 | 'alternative' => null, |
||
219 | 'separator' => '_', // Verified: all functions use separator. |
||
220 | ), |
||
221 | 'pfpro' => array( |
||
222 | '5.3' => true, |
||
223 | 'alternative' => null, |
||
224 | ), |
||
225 | 'sqlite' => array( |
||
226 | '5.4' => true, |
||
227 | 'alternative' => null, |
||
228 | 'separator' => '_', // Verified: all functions use separator. |
||
229 | ), |
||
230 | // Has to be before `sybase` as otherwise it will never match. |
||
231 | 'sybase_ct' => array( |
||
232 | '7.0' => true, |
||
233 | 'alternative' => null, |
||
234 | ), |
||
235 | 'sybase' => array( |
||
236 | '5.3' => true, |
||
237 | 'alternative' => 'sybase_ct', |
||
238 | 'separator' => '_', // Verified: all functions use separator. |
||
239 | ), |
||
240 | 'w32api' => array( |
||
241 | '5.1' => true, |
||
242 | 'alternative' => 'pecl/ffi', |
||
243 | 'separator' => '_', // Verified: all functions use separator. |
||
244 | ), |
||
245 | 'yp' => array( |
||
246 | '5.1' => true, |
||
247 | 'alternative' => null, |
||
248 | 'separator' => '_', // Verified: all functions use separator. |
||
249 | ), |
||
250 | */ |
||
251 | ); |
||
252 | |||
253 | /** |
||
254 | * Returns an array of tokens this test wants to listen for. |
||
255 | * |
||
256 | * @return array |
||
257 | */ |
||
258 | public function register() |
||
266 | |||
267 | /** |
||
268 | * Processes this test, when one of its tokens is encountered. |
||
269 | * |
||
270 | * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
||
271 | * @param int $stackPtr The position of the current token in the |
||
272 | * stack passed in $tokens. |
||
273 | * |
||
274 | * @return void |
||
275 | */ |
||
276 | View Code Duplication | public function process(\PHP_CodeSniffer_File $phpcsFile, $stackPtr) |
|
331 | |||
332 | |||
333 | /** |
||
334 | * Is the current function being checked whitelisted ? |
||
335 | * |
||
336 | * Parsing the list late as it may be provided as a property, but also inline. |
||
337 | * |
||
338 | * @param string $content Content of the current token. |
||
339 | * |
||
340 | * @return bool |
||
341 | */ |
||
342 | View Code Duplication | protected function isWhiteListed($content) |
|
364 | |||
365 | |||
366 | /** |
||
367 | * Get the relevant sub-array for a specific item from a multi-dimensional array. |
||
368 | * |
||
369 | * @param array $itemInfo Base information about the item. |
||
370 | * |
||
371 | * @return array Version and other information about the item. |
||
372 | */ |
||
373 | public function getItemArray(array $itemInfo) |
||
377 | |||
378 | |||
379 | /** |
||
380 | * Get the error message template for this sniff. |
||
381 | * |
||
382 | * @return string |
||
383 | */ |
||
384 | protected function getErrorMsgTemplate() |
||
388 | |||
389 | |||
390 | }//end class |
||
391 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.