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 Utility 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 Utility, and based on these observations, apply Extract Interface, too.
1 | <?php namespace XoopsModules\Marquee; |
||
9 | class Utility |
||
10 | { |
||
11 | use Common\VersionChecks; //checkVerXoops, checkVerPhp Traits |
||
12 | |||
13 | use Common\ServerStats; // getServerStats Trait |
||
14 | |||
15 | use Common\FilesManagement; // Files Management Trait |
||
16 | |||
17 | //--------------- Custom module methods ----------------------------- |
||
18 | const MODULE_NAME = 'marquee'; |
||
19 | |||
20 | /** |
||
21 | * truncateHtml can truncate a string up to a number of characters while preserving whole words and HTML tags |
||
22 | * www.gsdesign.ro/blog/cut-html-string-without-breaking-the-tags |
||
23 | * www.cakephp.org |
||
24 | * |
||
25 | * @param string $text String to truncate. |
||
26 | * @param integer $length Length of returned string, including ellipsis. |
||
27 | * @param string $ending Ending to be appended to the trimmed string. |
||
28 | * @param boolean $exact If false, $text will not be cut mid-word |
||
29 | * @param boolean $considerHtml If true, HTML tags would be handled correctly |
||
30 | * |
||
31 | * @return string Trimmed string. |
||
32 | */ |
||
33 | public static function truncateHtml($text, $length = 100, $ending = '...', $exact = false, $considerHtml = true) |
||
124 | |||
125 | /** |
||
126 | * Access the only instance of this class |
||
127 | * |
||
128 | * @return \XoopsModules\Marquee\Utility |
||
129 | * |
||
130 | * @static |
||
131 | * @staticvar object |
||
132 | */ |
||
133 | public static function getInstance() |
||
142 | |||
143 | /** |
||
144 | * Returns a module's option (with cache) |
||
145 | * |
||
146 | * @param string $option module option's name |
||
147 | * @param boolean $withCache Do we have to use some cache ? |
||
148 | * |
||
149 | * @return mixed option's value |
||
150 | */ |
||
151 | // public static function getModuleOption($option, $withCache = true) |
||
152 | // { |
||
153 | // global $xoopsModuleConfig, $xoopsModule; |
||
154 | // $repmodule = self::MODULE_NAME; |
||
155 | // static $options = []; |
||
156 | // if (is_array($options) && array_key_exists($option, $options) && $withCache) { |
||
157 | // return $options[$option]; |
||
158 | // } |
||
159 | // |
||
160 | // $retval = false; |
||
161 | // if (null !== $xoopsModuleConfig && (is_object($xoopsModule) && ($xoopsModule->getVar('dirname') == $repmodule) && $xoopsModule->getVar('isactive'))) { |
||
162 | // if (isset($xoopsModuleConfig[$option])) { |
||
163 | // $retval = $xoopsModuleConfig[$option]; |
||
164 | // } |
||
165 | // } else { |
||
166 | // /** @var \XoopsModuleHandler $moduleHandler */ |
||
167 | // $moduleHandler = xoops_getHandler('module'); |
||
168 | // $module = $moduleHandler->getByDirname($repmodule); |
||
169 | // $configHandler = xoops_getHandler('config'); |
||
170 | // if ($module) { |
||
171 | // $moduleConfig = $configHandler->getConfigsByCat(0, $module->getVar('mid')); |
||
172 | // if (isset($moduleConfig[$option])) { |
||
173 | // $retval = $moduleConfig[$option]; |
||
174 | // } |
||
175 | // } |
||
176 | // } |
||
177 | // $options[$option] = $retval; |
||
178 | // |
||
179 | // return $retval; |
||
180 | // } |
||
181 | |||
182 | /** |
||
183 | * Is Xoops 2.3.x ? |
||
184 | * |
||
185 | * @return boolean need to say it ? |
||
186 | */ |
||
187 | // function isX23() |
||
188 | // { |
||
189 | // $x23 = false; |
||
190 | // $xv = str_replace('XOOPS ', '', XOOPS_VERSION); |
||
191 | // if ((int)(substr($xv, 2, 1)) >= 3) { |
||
192 | // $x23 = true; |
||
193 | // } |
||
194 | // |
||
195 | // return $x23; |
||
196 | // } |
||
197 | |||
198 | /** |
||
199 | * Retreive an editor according to the module's option "form_options" |
||
200 | * |
||
201 | * @param string $caption Caption to give to the editor |
||
202 | * @param string $name Editor's name |
||
203 | * @param string $value Editor's value |
||
204 | * @param string $width Editor's width |
||
205 | * @param string $height Editor's height |
||
206 | * @param string $supplemental |
||
207 | * |
||
208 | * @return \XoopsFormDhtmlTextArea|\XoopsFormEditor The editor to use |
||
209 | */ |
||
210 | public static function getWysiwygForm( |
||
233 | |||
234 | /** |
||
235 | * Create (in a link) a javascript confirmation's box |
||
236 | * |
||
237 | * @param string $message Message to display |
||
238 | * @param boolean $form Is this a confirmation for a form ? |
||
239 | * |
||
240 | * @return string the javascript code to insert in the link (or in the form) |
||
241 | */ |
||
242 | public static function javascriptLinkConfirm($message, $form = false) |
||
250 | |||
251 | /** |
||
252 | * Redirect user with a message |
||
253 | * |
||
254 | * @param string $message message to display |
||
255 | * @param string $url The place where to go |
||
256 | * @param integer timeout Time to wait before to redirect |
||
257 | */ |
||
258 | public static function redirect($message = '', $url = 'index.php', $time = 2) |
||
262 | |||
263 | /** |
||
264 | * Internal function used to get the handler of the current module |
||
265 | * |
||
266 | * @return \XoopsModule The module |
||
267 | */ |
||
268 | protected static function getModule() |
||
283 | |||
284 | /** |
||
285 | * Returns the module's name (as defined by the user in the module manager) with cache |
||
286 | * |
||
287 | * @return string Module's name |
||
288 | */ |
||
289 | public static function getModuleName() |
||
299 | |||
300 | /** |
||
301 | * This function indicates if the current Xoops version needs to add asterisks to required fields in forms |
||
302 | * |
||
303 | * @return boolean Yes = we need to add them, false = no |
||
304 | */ |
||
305 | public static function needsAsterisk() |
||
322 | |||
323 | /** |
||
324 | * Mark the mandatory fields of a form with a star |
||
325 | * |
||
326 | * @param \XoopsThemeForm $sform The form to modify |
||
327 | * |
||
328 | * @internal param string $caracter The character to use to mark fields |
||
329 | * @return \XoopsThemeForm The modified form |
||
330 | */ |
||
331 | public static function formMarkRequiredFields(&$sform) |
||
349 | |||
350 | View Code Duplication | public static function getModuleOption($option, $repmodule = 'marquee') |
|
381 | |||
382 | /** |
||
383 | * Verify if the current "user" is a bot or not |
||
384 | * |
||
385 | * If you have a problem with this function, insert the folowing code just before the line if (isset($_SESSION['news_cache_bot'])) { : |
||
386 | * return false; |
||
387 | * |
||
388 | * @package Marquee |
||
389 | * @author Hervé Thouzard (http://www.herve-thouzard.com) |
||
390 | * @copyright (c) Hervé Thouzard |
||
391 | */ |
||
392 | View Code Duplication | public static function isBot() |
|
415 | |||
416 | /** |
||
417 | * Escape a string so that it can be included in a javascript string |
||
418 | * |
||
419 | * @param $string |
||
420 | * |
||
421 | * @return mixed |
||
422 | */ |
||
423 | public static function javascriptEscape($string) |
||
427 | } |
||
428 |
There are different options of fixing this problem.
If you want to be on the safe side, you can add an additional type-check:
If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:
Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.