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 CoreExtension 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 CoreExtension, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 21 | class CoreExtension extends \Twig_Extension |
||
| 22 | { |
||
| 23 | /** |
||
| 24 | * @var ContainerInterface |
||
| 25 | */ |
||
| 26 | private $container; |
||
| 27 | |||
| 28 | /** |
||
| 29 | * @var TranslatorInterface |
||
| 30 | */ |
||
| 31 | private $translator; |
||
| 32 | |||
| 33 | public function __construct(ContainerInterface $container = null) |
||
| 38 | |||
| 39 | /** |
||
| 40 | * @return ContainerInterface |
||
| 41 | */ |
||
| 42 | public function getContainer() |
||
| 46 | |||
| 47 | public function getTokenParsers() |
||
| 53 | |||
| 54 | /** |
||
| 55 | * Returns a list of functions to add to the existing list. |
||
| 56 | * |
||
| 57 | * @return array An array of functions |
||
| 58 | */ |
||
| 59 | public function getFunctions() |
||
| 86 | |||
| 87 | public function getFilters() |
||
| 98 | |||
| 99 | public function getAssetPath($path) |
||
| 103 | |||
| 104 | /** |
||
| 105 | * Function to get the language direction |
||
| 106 | * |
||
| 107 | * @return string the language direction |
||
| 108 | */ |
||
| 109 | public function langDirection() |
||
| 113 | |||
| 114 | public function button() |
||
| 117 | |||
| 118 | public function img() |
||
| 121 | |||
| 122 | public function icon() |
||
| 125 | |||
| 126 | /** |
||
| 127 | * Display flash messages in twig template. Defaults to bootstrap alert classes. |
||
| 128 | * |
||
| 129 | * <pre> |
||
| 130 | * {{ showflashes() }} |
||
| 131 | * {{ showflashes({'class': 'custom-class', 'tag': 'span'}) }} |
||
| 132 | * </pre> |
||
| 133 | * |
||
| 134 | * @param array $params |
||
| 135 | * @return string |
||
| 136 | */ |
||
| 137 | public function showFlashes(array $params = []) |
||
| 178 | |||
| 179 | /** |
||
| 180 | * Delete a key of an array |
||
| 181 | * |
||
| 182 | * @param array $array Source array |
||
| 183 | * @param string $key The key to remove |
||
| 184 | * |
||
| 185 | * @return array |
||
| 186 | */ |
||
| 187 | public function arrayUnset($array, $key) |
||
| 193 | |||
| 194 | /** |
||
| 195 | * @param string $code |
||
| 196 | * @return string |
||
| 197 | */ |
||
| 198 | public function languageName($code) |
||
| 202 | |||
| 203 | public function yesNo($string) |
||
| 211 | |||
| 212 | /** |
||
| 213 | * Apply an existing function (e.g. php's `md5`) to a string. |
||
| 214 | * |
||
| 215 | * @param $string |
||
| 216 | * @param $func |
||
| 217 | * @return mixed |
||
| 218 | */ |
||
| 219 | public function applyPhp($string, $func) |
||
| 227 | |||
| 228 | /** |
||
| 229 | * Protect a given mail address by finding the text 'x@y' and replacing |
||
| 230 | * it with HTML entities. This provides protection against email harvesters. |
||
| 231 | * |
||
| 232 | * @param string |
||
| 233 | * @return string |
||
| 234 | */ |
||
| 235 | public function protectMailAddress($string) |
||
| 247 | |||
| 248 | /** |
||
| 249 | * Create a link to a users profile from the UID. |
||
| 250 | * |
||
| 251 | * Examples |
||
| 252 | * |
||
| 253 | * Simple version, shows the username |
||
| 254 | * {{ uid|profileLinkByUserId() }} |
||
| 255 | * Simple version, shows username, using class="classname" |
||
| 256 | * {{ uid|profileLinkByUserId(class='classname') }} |
||
| 257 | * Using profile.gif instead of username, no class |
||
| 258 | * {{ uid|profileLinkByUserId(image='images/profile.gif') }} |
||
| 259 | * |
||
| 260 | * @param integer $userId The users uid |
||
| 261 | * @param string $class The class name for the link (optional) |
||
| 262 | * @param string $image Path to the image to show instead of the username (optional) |
||
| 263 | * @param integer $maxLength If set then user names are truncated to x chars |
||
| 264 | * @return string The output |
||
| 265 | */ |
||
| 266 | View Code Duplication | public function profileLinkByUserId($userId, $class = '', $image = '', $maxLength = 0) |
|
| 274 | |||
| 275 | /** |
||
| 276 | * Create a link to a users profile from the username. |
||
| 277 | * |
||
| 278 | * Examples |
||
| 279 | * |
||
| 280 | * Simple version, shows the username |
||
| 281 | * {{ username|profileLinkByUserName() }} |
||
| 282 | * Simple version, shows username, using class="classname" |
||
| 283 | * {{ username|profileLinkByUserName(class='classname') }} |
||
| 284 | * Using profile.gif instead of username, no class |
||
| 285 | * {{ username|profileLinkByUserName('image'='images/profile.gif') }} |
||
| 286 | * |
||
| 287 | * @param string $userName The users name |
||
| 288 | * @param string $class The class name for the link (optional) |
||
| 289 | * @param string $image Path to the image to show instead of the username (optional) |
||
| 290 | * @param integer $maxLength If set then user names are truncated to x chars |
||
| 291 | * @return string The output |
||
| 292 | */ |
||
| 293 | View Code Duplication | public function profileLinkByUserName($userName, $class = '', $image = '', $maxLength = 0) |
|
| 301 | |||
| 302 | /** |
||
| 303 | * Internal function used by profileLinkByUserId() and profileLinkByUserName(). |
||
| 304 | * |
||
| 305 | * @param integer $userId The users uid |
||
| 306 | * @param string $userName The users name |
||
| 307 | * @param string $class The class name for the link (optional) |
||
| 308 | * @param string $imagePath Path to the image to show instead of the username (optional) |
||
| 309 | * @param integer $maxLength If set then user names are truncated to x chars |
||
| 310 | * @return string The output |
||
| 311 | */ |
||
| 312 | private function determineProfileLink($userId = null, $userName = null, $class = '', $imagePath = '', $maxLength = 0) |
||
| 350 | |||
| 351 | /** |
||
| 352 | * Zikula imposes no restriction on page variable names. |
||
| 353 | * Typical usage is to set `title` `meta.charset` `lang` etc. |
||
| 354 | * array values are set using `.` in the `$name` string (e.g. `meta.charset`) |
||
| 355 | * @param string $name |
||
| 356 | * @param string $value |
||
| 357 | */ |
||
| 358 | View Code Duplication | public function pageSetVar($name, $value) |
|
| 366 | |||
| 367 | /** |
||
| 368 | * Zikula allows only the following asset types |
||
| 369 | * <ul> |
||
| 370 | * <li>stylesheet</li> |
||
| 371 | * <li>javascript</li> |
||
| 372 | * <li>header</li> |
||
| 373 | * <li>footer</li> |
||
| 374 | * </ul> |
||
| 375 | * |
||
| 376 | * @param string $type |
||
| 377 | * @param string $value |
||
| 378 | * @param int $weight |
||
| 379 | */ |
||
| 380 | public function pageAddAsset($type, $value, $weight = AssetBag::WEIGHT_DEFAULT) |
||
| 404 | |||
| 405 | /** |
||
| 406 | * @param $name |
||
| 407 | * @param null $default |
||
| 408 | * @return mixed |
||
| 409 | */ |
||
| 410 | View Code Duplication | public function pageGetVar($name, $default = null) |
|
| 418 | |||
| 419 | /** |
||
| 420 | * @param $module |
||
| 421 | * @param $name |
||
| 422 | * @param null $default |
||
| 423 | * @return mixed |
||
| 424 | */ |
||
| 425 | View Code Duplication | public function getModVar($module, $name, $default = null) |
|
| 433 | |||
| 434 | /** |
||
| 435 | * @param $name |
||
| 436 | * @param null $default |
||
| 437 | * @return mixed |
||
| 438 | */ |
||
| 439 | View Code Duplication | public function getSystemVar($name, $default = null) |
|
| 447 | |||
| 448 | /** |
||
| 449 | * @param string $name |
||
| 450 | * @param string $value |
||
| 451 | */ |
||
| 452 | public function setMetaTag($name, $value) |
||
| 462 | |||
| 463 | /** |
||
| 464 | * @deprecated remove at Core-2.0 |
||
| 465 | * @param string $modname |
||
| 466 | * @param bool $force |
||
| 467 | * @return bool |
||
| 468 | */ |
||
| 469 | public function modAvailable($modname, $force = false) |
||
| 475 | |||
| 476 | /** |
||
| 477 | * Call a php callable with parameters. |
||
| 478 | * @param callable $callable |
||
| 479 | * @param array $params |
||
| 480 | * @return mixed |
||
| 481 | */ |
||
| 482 | public function callFunc(callable $callable, array $params = []) |
||
| 489 | } |
||
| 490 |
If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe: