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 ZikulaKernel 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 ZikulaKernel, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 41 | abstract class ZikulaKernel extends Kernel implements ZikulaHttpKernelInterface |
||
| 42 | { |
||
| 43 | const VERSION = '2.0.0'; |
||
| 44 | |||
| 45 | const VERSION_SUB = 'Concerto'; |
||
| 46 | |||
| 47 | const PHP_MINIMUM_VERSION = '5.5.9'; |
||
| 48 | |||
| 49 | /** |
||
| 50 | * The parameter name identifying the currently installed version of the core. |
||
| 51 | */ |
||
| 52 | const CORE_INSTALLED_VERSION_PARAM = 'core_installed_version'; |
||
| 53 | |||
| 54 | /** |
||
| 55 | * Public list of core modules and their bundle class. |
||
| 56 | * @var array |
||
| 57 | */ |
||
| 58 | public static $coreModules = [ |
||
| 59 | 'ZikulaAdminModule' => 'Zikula\AdminModule\ZikulaAdminModule', |
||
| 60 | 'ZikulaBlocksModule' => 'Zikula\BlocksModule\ZikulaBlocksModule', |
||
| 61 | 'ZikulaCategoriesModule' => 'Zikula\CategoriesModule\ZikulaCategoriesModule', |
||
| 62 | 'ZikulaExtensionsModule' => 'Zikula\ExtensionsModule\ZikulaExtensionsModule', |
||
| 63 | 'ZikulaGroupsModule' => 'Zikula\GroupsModule\ZikulaGroupsModule', |
||
| 64 | 'ZikulaMailerModule' => 'Zikula\MailerModule\ZikulaMailerModule', |
||
| 65 | 'ZikulaPermissionsModule' => 'Zikula\PermissionsModule\ZikulaPermissionsModule', |
||
| 66 | 'ZikulaRoutesModule' => 'Zikula\RoutesModule\ZikulaRoutesModule', |
||
| 67 | 'ZikulaSearchModule' => 'Zikula\SearchModule\ZikulaSearchModule', |
||
| 68 | 'ZikulaSecurityCenterModule' => 'Zikula\SecurityCenterModule\ZikulaSecurityCenterModule', |
||
| 69 | 'ZikulaSettingsModule' => 'Zikula\SettingsModule\ZikulaSettingsModule', |
||
| 70 | 'ZikulaThemeModule' => 'Zikula\ThemeModule\ZikulaThemeModule', |
||
| 71 | 'ZikulaUsersModule' => 'Zikula\UsersModule\ZikulaUsersModule', |
||
| 72 | 'ZikulaZAuthModule' => 'Zikula\ZAuthModule\ZikulaZAuthModule', |
||
| 73 | 'ZikulaMenuModule' => 'Zikula\MenuModule\ZikulaMenuModule', |
||
| 74 | ]; |
||
| 75 | |||
| 76 | /** |
||
| 77 | * @var boolean |
||
| 78 | */ |
||
| 79 | private $dump = true; |
||
| 80 | |||
| 81 | /** |
||
| 82 | * @var array |
||
| 83 | */ |
||
| 84 | private $modules = []; |
||
| 85 | |||
| 86 | /** |
||
| 87 | * @var array |
||
| 88 | */ |
||
| 89 | private $moduleMap = []; |
||
| 90 | |||
| 91 | /** |
||
| 92 | * @var array |
||
| 93 | */ |
||
| 94 | private $themes = []; |
||
| 95 | |||
| 96 | /** |
||
| 97 | * @var array |
||
| 98 | */ |
||
| 99 | private $themeMap = []; |
||
| 100 | |||
| 101 | /** |
||
| 102 | * @var ClassLoader |
||
| 103 | */ |
||
| 104 | private $autoloader; |
||
| 105 | |||
| 106 | /** |
||
| 107 | * Flag determines if container is dumped or not |
||
| 108 | * |
||
| 109 | * @param $flag |
||
| 110 | */ |
||
| 111 | public function setDump($flag) |
||
| 112 | { |
||
| 113 | $this->dump = $flag; |
||
| 114 | } |
||
| 115 | |||
| 116 | public function boot() |
||
| 117 | { |
||
| 118 | if (null === $this->autoloader) { |
||
| 119 | $this->getAutoloader(); |
||
| 120 | } |
||
| 121 | |||
| 122 | parent::boot(); |
||
| 123 | |||
| 124 | foreach ($this->bundles as $name => $bundle) { |
||
| 125 | if ($bundle instanceof AbstractModule && !isset($this->modules[$name])) { |
||
| 126 | $this->modules[$name] = $bundle; |
||
| 127 | } elseif ($bundle instanceof AbstractTheme && !isset($this->themes[$name])) { |
||
| 128 | $this->themes[$name] = $bundle; |
||
| 129 | } |
||
| 130 | } |
||
| 131 | |||
| 132 | foreach ($this->bundleMap as $name => $bundles) { |
||
| 133 | if ($bundles[0] instanceof AbstractModule) { |
||
| 134 | $this->moduleMap[$name] = $bundles; |
||
| 135 | } elseif ($bundles[0] instanceof AbstractTheme) { |
||
| 136 | $this->themeMap[$name] = $bundles; |
||
| 137 | } |
||
| 138 | } |
||
| 139 | } |
||
| 140 | |||
| 141 | /** |
||
| 142 | * Get named module bundle. |
||
| 143 | * |
||
| 144 | * @param string $moduleName |
||
| 145 | * @param boolean $first |
||
| 146 | * |
||
| 147 | * @throws \InvalidArgumentException when the bundle is not enabled |
||
| 148 | * @return \Zikula\Core\AbstractModule|\Zikula\Core\AbstractModule[] |
||
| 149 | */ |
||
| 150 | View Code Duplication | public function getModule($moduleName, $first = true) |
|
| 162 | |||
| 163 | public function getModules() |
||
| 167 | |||
| 168 | /** |
||
| 169 | * Checks if name is is the list of core modules. |
||
| 170 | * @param $moduleName |
||
| 171 | * @return bool |
||
| 172 | */ |
||
| 173 | public static function isCoreModule($moduleName) |
||
| 177 | |||
| 178 | /** |
||
| 179 | * Get named theme bundle. |
||
| 180 | * |
||
| 181 | * @param string $themeName |
||
| 182 | * @param boolean $first |
||
| 183 | * |
||
| 184 | * @throws \InvalidArgumentException when the bundle is not enabled |
||
| 185 | * |
||
| 186 | * @return AbstractTheme|AbstractTheme |
||
| 187 | */ |
||
| 188 | View Code Duplication | public function getTheme($themeName, $first = true) |
|
| 200 | |||
| 201 | public function getThemes() |
||
| 205 | |||
| 206 | public function getJustBundles() |
||
| 217 | |||
| 218 | /** |
||
| 219 | * Is this a Bundle? |
||
| 220 | * |
||
| 221 | * @param $name |
||
| 222 | * @param bool $first |
||
| 223 | * @return bool |
||
| 224 | */ |
||
| 225 | public function isBundle($name, $first = true) |
||
| 235 | |||
| 236 | public function setAutoloader(ClassLoader $autoloader) |
||
| 240 | |||
| 241 | public function getAutoloader() |
||
| 259 | |||
| 260 | public function getConnectionConfig() |
||
| 269 | |||
| 270 | public function isClassInBundle($class) |
||
| 281 | |||
| 282 | /** |
||
| 283 | * Initializes the data structures related to the bundle management. |
||
| 284 | * |
||
| 285 | * - the bundles property maps a bundle name to the bundle instance, |
||
| 286 | * - the bundleMap property maps a bundle name to the bundle inheritance hierarchy (most derived bundle first). |
||
| 287 | * |
||
| 288 | * @throws \LogicException if two bundles share a common name |
||
| 289 | * @throws \LogicException if a bundle tries to extend a non-registered bundle |
||
| 290 | * @throws \LogicException if a bundle tries to extend itself |
||
| 291 | * @throws \LogicException if two bundles extend the same ancestor |
||
| 292 | */ |
||
| 293 | protected function initializeBundles() |
||
| 343 | |||
| 344 | /** |
||
| 345 | * Initializes the service container. |
||
| 346 | * |
||
| 347 | * The cached version of the service container is used when fresh, otherwise the |
||
| 348 | * container is built. |
||
| 349 | * |
||
| 350 | * Overridden not to dump the container. |
||
| 351 | */ |
||
| 352 | protected function initializeContainer() |
||
| 361 | |||
| 362 | /** |
||
| 363 | * Dumps the service container to PHP code in the cache. |
||
| 364 | * |
||
| 365 | * @param ConfigCache $cache The config cache |
||
| 366 | * @param SymfonyContainerBuilder $container The service container |
||
| 367 | * @param string $class The name of the class to generate |
||
| 368 | * @param string $baseClass The name of the container's base class |
||
| 369 | */ |
||
| 370 | protected function dumpContainer(ConfigCache $cache, SymfonyContainerBuilder $container, $class, $baseClass) |
||
| 381 | |||
| 382 | /** |
||
| 383 | * Gets the container's base class. |
||
| 384 | * |
||
| 385 | * All names except Container must be fully qualified. |
||
| 386 | * |
||
| 387 | * Allows container to build services after being dumped and frozen |
||
| 388 | * |
||
| 389 | * @return string |
||
| 390 | */ |
||
| 391 | protected function getContainerBaseClass() |
||
| 396 | |||
| 397 | /** |
||
| 398 | * Gets a new ContainerBuilder instance used to build the service container. |
||
| 399 | * |
||
| 400 | * @return ContainerBuilder |
||
| 401 | */ |
||
| 402 | protected function getContainerBuilder() |
||
| 406 | |||
| 407 | /** |
||
| 408 | * Gets the environment parameters. |
||
| 409 | * |
||
| 410 | * Only the parameters starting with "ZIKULA__" are considered. |
||
| 411 | * |
||
| 412 | * @return array An array of parameters |
||
| 413 | */ |
||
| 414 | protected function getEnvParameters() |
||
| 425 | |||
| 426 | /** |
||
| 427 | * Prepares the ContainerBuilder before it is compiled. |
||
| 428 | * |
||
| 429 | * @param SymfonyContainerBuilder $container A ContainerBuilder instance |
||
| 430 | */ |
||
| 431 | protected function prepareContainer(SymfonyContainerBuilder $container) |
||
| 457 | |||
| 458 | /** |
||
| 459 | * {@inheritdoc} |
||
| 460 | * |
||
| 461 | * @throws \RuntimeException if a custom resource is hidden by a resource in a derived bundle |
||
| 462 | */ |
||
| 463 | public function locateResource($name, $dir = null, $first = true) |
||
| 485 | } |
||
| 486 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.