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 Addons 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 Addons, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 21 | class Addons { |
||
| 22 | /// Constants /// |
||
| 23 | const K_BOOTSTRAP = 'bootstrap'; // bootstrap path key |
||
| 24 | const K_CLASSES = 'classes'; |
||
| 25 | const K_DIR = 'dir'; |
||
| 26 | const K_INFO = 'info'; // addon info key |
||
| 27 | |||
| 28 | /// Properties /// |
||
| 29 | |||
| 30 | /** |
||
| 31 | * @var array An array that maps addon keys to full addon information. |
||
| 32 | */ |
||
| 33 | protected static $all; |
||
| 34 | |||
| 35 | /** |
||
| 36 | * @var string The base directory where all of the addons are found. |
||
| 37 | */ |
||
| 38 | protected static $baseDir; |
||
| 39 | |||
| 40 | /** |
||
| 41 | * @var array An array that maps class names to their fully namespaced class names. |
||
| 42 | */ |
||
| 43 | // protected static $basenameMap; |
||
| 44 | |||
| 45 | /** |
||
| 46 | * @var array|null An array that maps class names to file paths. |
||
| 47 | */ |
||
| 48 | protected static $classMap; |
||
| 49 | |||
| 50 | /** |
||
| 51 | * @var array An array that maps addon keys to full addon information for enabled addons. |
||
| 52 | */ |
||
| 53 | protected static $enabled; |
||
| 54 | |||
| 55 | /** |
||
| 56 | * @var array An array of enabled addon keys. |
||
| 57 | */ |
||
| 58 | protected static $enabledKeys; |
||
| 59 | |||
| 60 | /** |
||
| 61 | * @var bool Signals that the addon framework is in a shared environment and shouldn't use the enabled cache. |
||
| 62 | */ |
||
| 63 | public static $sharedEnvironment; |
||
| 64 | |||
| 65 | /// Methods /// |
||
| 66 | |||
| 67 | /** |
||
| 68 | * Get all of the available addons or a single addon from the available list. |
||
| 69 | * |
||
| 70 | * @param string $addon_key If you supply an addon key then only that addon will be returned. |
||
| 71 | * @param string $key Supply one of the Addons::K_* constants to get a specific key from the addon. |
||
| 72 | * @return array Returns the addon with the given key or all available addons if no key is passed. |
||
| 73 | */ |
||
| 74 | public static function all($addon_key = null, $key = null) { |
||
| 93 | |||
| 94 | /** |
||
| 95 | * An autoloader that will autoload a class based on which addons are enabled. |
||
| 96 | * |
||
| 97 | * @param string $classname The name of the class to load. |
||
| 98 | */ |
||
| 99 | 6 | public static function autoload($classname) { |
|
| 105 | |||
| 106 | /** |
||
| 107 | * Gets/sets the base directory for addons. |
||
| 108 | * |
||
| 109 | * @param string $value Pass a value to set the new base directory. |
||
| 110 | * @return string Returns the base directory for addons. |
||
| 111 | */ |
||
| 112 | 34 | public static function baseDir($value = null) { |
|
| 119 | |||
| 120 | |||
| 121 | /** |
||
| 122 | * Start up the addon framework. |
||
| 123 | * |
||
| 124 | * @param array $enabled_addons An array of enabled addons. |
||
| 125 | */ |
||
| 126 | 34 | public static function bootstrap($enabled_addons = null) { |
|
| 165 | |||
| 166 | /** |
||
| 167 | * Get the cached file or hydrate the cache with a callback. |
||
| 168 | * |
||
| 169 | * @param string $key The cache key to get. |
||
| 170 | * @param callable $cache_cb The function to run when hydrating the cache. |
||
| 171 | * @return array Returns the cached array. |
||
| 172 | */ |
||
| 173 | 1 | protected static function cacheGet($key, callable $cache_cb) { |
|
| 187 | |||
| 188 | /** |
||
| 189 | * A an array that maps class names to physical paths. |
||
| 190 | * |
||
| 191 | * @param string $classname An optional class name to get the path of. |
||
| 192 | * @return array Returns an array in the form `[fullClassname, classPath]`. |
||
| 193 | * If no {@link $classname} is passed then the entire class map is returned. |
||
| 194 | * @throws \Exception Throws an exception if the class map is corrupt. |
||
| 195 | */ |
||
| 196 | 36 | public static function classMap($classname = null) { |
|
| 231 | |||
| 232 | /** |
||
| 233 | * Get all of the enabled addons or a single addon from the enabled list. |
||
| 234 | * |
||
| 235 | * @param string $addon_key If you supply an addon key then only that addon will be returned. |
||
| 236 | * @param string $key Supply one of the Addons::K_* constants to get a specific key from the addon. |
||
| 237 | * @return array Returns the addon with the given key or all enabled addons if no key is passed. |
||
| 238 | * @throws \Exception Throws an exception if {@link Addons::bootstrap()} hasn't been called yet. |
||
| 239 | */ |
||
| 240 | 34 | public static function enabled($addon_key = null, $key = null) { |
|
| 278 | |||
| 279 | /** |
||
| 280 | * Return the info array for an addon. |
||
| 281 | * |
||
| 282 | * @param string $addon_key The addon key. |
||
| 283 | * @return array|null Returns the addon's info array or null if the addon wasn't found. |
||
| 284 | */ |
||
| 285 | public static function info($addon_key) { |
||
| 295 | |||
| 296 | /** |
||
| 297 | * Scan an addon directory for information. |
||
| 298 | * |
||
| 299 | * @param string $dir The addon directory to scan. |
||
| 300 | * @param array &$addons The addons array. |
||
| 301 | * @param array $enabled An array of enabled addons or null to scan all addons. |
||
| 302 | * @return array Returns an array in the form [addonKey, addonInfo]. |
||
| 303 | */ |
||
| 304 | 1 | protected static function scanAddonRecursive($dir, &$addons, $enabled = null) { |
|
| 330 | |||
| 331 | /** |
||
| 332 | * Scan an individual addon directory and return the information about that addon. |
||
| 333 | * |
||
| 334 | * @param string $dir The path to the addon. |
||
| 335 | * @return array An array in the form of `[$addon_key, $addon_row]` or `[$addon_key, null]` if the directory doesn't |
||
| 336 | * represent an addon. |
||
| 337 | */ |
||
| 338 | 1 | protected static function scanAddon($dir) { |
|
| 393 | |||
| 394 | /** |
||
| 395 | * Scan a directory for addons. |
||
| 396 | * |
||
| 397 | * @param string $dir The directory to scan. |
||
| 398 | * @param array $enabled An array of enabled addons in the form `[addonKey => enabled, ...]`. |
||
| 399 | * @param array &$addons The addons will fill this array. |
||
| 400 | * @return array Returns all of the addons. |
||
| 401 | */ |
||
| 402 | 1 | protected static function scanAddons($dir = null, $enabled = null, &$addons = null) { |
|
| 419 | |||
| 420 | /** |
||
| 421 | * Looks what classes and namespaces are defined in a file and returns the first found. |
||
| 422 | * |
||
| 423 | * @param string $file Path to file. |
||
| 424 | * @return array Returns an empty array if no classes are found or an array with namespaces and |
||
| 425 | * classes found in the file. |
||
| 426 | * @see http://stackoverflow.com/a/11114724/1984219 |
||
| 427 | */ |
||
| 428 | 1 | protected static function scanFile($file) { |
|
| 481 | |||
| 482 | /** |
||
| 483 | * Start an addon. |
||
| 484 | * |
||
| 485 | * This function does the following: |
||
| 486 | * |
||
| 487 | * 1. Make the addon available in the autoloader. |
||
| 488 | * 2. Run the addon's bootstrap.php if it exists. |
||
| 489 | * |
||
| 490 | * @param string $addon_key The key of the addon to enable. |
||
| 491 | * @return bool Returns true if the addon was enabled. False otherwise. |
||
| 492 | */ |
||
| 493 | 34 | public static function startAddon($addon_key) { |
|
| 505 | } |
In PHP, under loose comparison (like
==, or!=, orswitchconditions), values of different types might be equal.For
stringvalues, the empty string''is a special case, in particular the following results might be unexpected: