Complex classes like DebugBar 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 DebugBar, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 6 | class DebugBar extends Object |
||
| 7 | { |
||
| 8 | |||
| 9 | /** |
||
| 10 | * @var DebugBar\DebugBar |
||
| 11 | */ |
||
| 12 | protected static $debugbar = null; |
||
| 13 | |||
| 14 | /** |
||
| 15 | * |
||
| 16 | * @var bool |
||
| 17 | */ |
||
| 18 | public static $bufferingEnabled = false; |
||
| 19 | |||
| 20 | /** |
||
| 21 | * @var DebugBar\JavascriptRenderer |
||
| 22 | */ |
||
| 23 | protected static $renderer = null; |
||
| 24 | |||
| 25 | /** |
||
| 26 | * |
||
| 27 | * @var bool |
||
| 28 | */ |
||
| 29 | protected static $showQueries = false; |
||
| 30 | |||
| 31 | /** |
||
| 32 | * Get the Debug Bar instance |
||
| 33 | * @return \DebugBar\StandardDebugBar |
||
| 34 | * @throws Exception |
||
| 35 | * @global array $databaseConfig |
||
| 36 | */ |
||
| 37 | public static function getDebugBar() |
||
| 38 | { |
||
| 39 | if (self::$debugbar !== null) { |
||
| 40 | return self::$debugbar; |
||
| 41 | } |
||
| 42 | |||
| 43 | if (!Director::isDev() || self::isDisabled() || self::vendorNotInstalled() || |
||
| 44 | self::notLocalIp() || Director::is_cli() || self::isDevUrl() || |
||
| 45 | (self::isAdminUrl() && !self::config()->enabled_in_admin) |
||
| 46 | ) { |
||
| 47 | self::$debugbar = null; // No need to check again |
||
| 48 | return; |
||
| 49 | } |
||
| 50 | |||
| 51 | self::initDebugBar(); |
||
| 52 | |||
| 53 | if (!self::$debugbar) { |
||
| 54 | throw new Exception("Failed to initialize the DebugBar"); |
||
| 55 | } |
||
| 56 | |||
| 57 | return self::$debugbar; |
||
| 58 | } |
||
| 59 | |||
| 60 | /** |
||
| 61 | * Init the debugbar instance |
||
| 62 | * |
||
| 63 | * @global array $databaseConfig |
||
| 64 | * @return DebugBar\StandardDebugBar |
||
| 65 | */ |
||
| 66 | public static function initDebugBar() |
||
| 67 | { |
||
| 68 | // Prevent multiple inits |
||
| 69 | if (self::$debugbar) { |
||
| 70 | return self::$debugbar; |
||
| 71 | } |
||
| 72 | |||
| 73 | // Add the controller extension programmaticaly because it might not be added properly through yml |
||
| 74 | Controller::add_extension('DebugBarControllerExtension'); |
||
| 75 | |||
| 76 | // Add a custom logger that logs everything under the Messages tab |
||
| 77 | SS_Log::add_writer(new DebugBarLogWriter(), SS_Log::DEBUG, '<='); |
||
| 78 | |||
| 79 | self::$debugbar = $debugbar = new DebugBar\DebugBar(); |
||
| 80 | |||
| 81 | if (isset($_REQUEST['showqueries'])) { |
||
| 82 | self::setShowQueries(true); |
||
| 83 | echo "The queries above have been run before we started DebugBar"; |
||
| 84 | echo '<hr>'; |
||
| 85 | unset($_REQUEST['showqueries']); |
||
| 86 | } |
||
| 87 | |||
| 88 | $debugbar->addCollector(new DebugBar\DataCollector\PhpInfoCollector()); |
||
| 89 | $debugbar->addCollector(new DebugBarTimeDataCollector()); |
||
| 90 | $debugbar->addCollector(new DebugBar\DataCollector\MemoryCollector()); |
||
| 91 | |||
| 92 | if (!DB::get_conn()) { |
||
| 93 | global $databaseConfig; |
||
| 94 | if ($databaseConfig) { |
||
| 95 | DB::connect($databaseConfig); |
||
| 96 | } |
||
| 97 | } |
||
| 98 | |||
| 99 | $connector = DB::get_connector(); |
||
| 100 | if (!self::config()->force_proxy && $connector instanceof PDOConnector) { |
||
| 101 | // Use a little bit of magic to replace the pdo instance |
||
| 102 | $refObject = new ReflectionObject($connector); |
||
| 103 | $refProperty = $refObject->getProperty('pdoConnection'); |
||
| 104 | $refProperty->setAccessible(true); |
||
| 105 | $traceablePdo = new DebugBar\DataCollector\PDO\TraceablePDO($refProperty->getValue($connector)); |
||
| 106 | $refProperty->setValue($connector, $traceablePdo); |
||
| 107 | |||
| 108 | $debugbar->addCollector(new DebugBar\DataCollector\PDO\PDOCollector($traceablePdo)); |
||
| 109 | } else { |
||
| 110 | DB::set_conn($db = new DebugBarDatabaseNewProxy(DB::get_conn())); |
||
| 111 | $db->setShowQueries(self::getShowQueries()); |
||
| 112 | $debugbar->addCollector(new DebugBarDatabaseCollector); |
||
| 113 | } |
||
| 114 | |||
| 115 | } else { |
||
| 116 | DB::set_conn($db = new DebugBarDatabaseNewProxy(DB::get_conn())); |
||
| 117 | $db->setShowQueries(self::getShowQueries()); |
||
| 118 | $debugbar->addCollector(new DebugBarDatabaseCollector($db)); |
||
| 119 | } |
||
| 120 | |||
| 121 | // Add message collector last so other collectors can send messages to the console using it |
||
| 122 | $debugbar->addCollector(new DebugBar\DataCollector\MessagesCollector()); |
||
| 123 | |||
| 124 | // Add some SilverStripe specific infos |
||
| 125 | $debugbar->addCollector(new DebugBarSilverStripeCollector()); |
||
| 126 | |||
| 127 | if (self::config()->enable_storage) { |
||
| 128 | $debugbar->setStorage(new DebugBar\Storage\FileStorage(TEMP_FOLDER . '/debugbar')); |
||
| 129 | } |
||
| 130 | |||
| 131 | // Since we buffer everything, why not enable all dev options ? |
||
| 132 | if (self::config()->auto_debug) { |
||
| 133 | $_REQUEST['debug'] = true; |
||
| 134 | $_REQUEST['debug_request'] = true; |
||
| 135 | } |
||
| 136 | |||
| 137 | if (isset($_REQUEST['debug']) || isset($_REQUEST['debug_request'])) { |
||
| 138 | self::$bufferingEnabled = true; |
||
| 139 | ob_start(); // We buffer everything until we have called an action |
||
| 140 | } |
||
| 141 | |||
| 142 | return $debugbar; |
||
| 143 | } |
||
| 144 | |||
| 145 | public static function clearDebugBar() |
||
| 146 | { |
||
| 147 | self::$debugbar = null; |
||
| 148 | } |
||
| 149 | |||
| 150 | public static function getShowQueries() |
||
| 151 | { |
||
| 152 | return self::$showQueries; |
||
| 153 | } |
||
| 154 | |||
| 155 | public static function setShowQueries($showQueries) |
||
| 156 | { |
||
| 157 | self::$showQueries = $showQueries; |
||
| 158 | } |
||
| 159 | |||
| 160 | public static function includeRequirements() |
||
| 161 | { |
||
| 162 | $debugbar = self::getDebugBar(); |
||
| 163 | |||
| 164 | if (!$debugbar) { |
||
| 165 | return; |
||
| 166 | } |
||
| 167 | |||
| 168 | // Already called |
||
| 169 | if (self::$renderer) { |
||
| 170 | return; |
||
| 171 | } |
||
| 172 | |||
| 173 | $renderer = $debugbar->getJavascriptRenderer(); |
||
| 174 | |||
| 175 | // We don't need the true path since we are going to use Requirements API that appends the BASE_PATH |
||
| 176 | $renderer->setBasePath(DEBUGBAR_DIR . '/assets'); |
||
| 177 | $renderer->setBaseUrl(DEBUGBAR_DIR . '/assets'); |
||
| 178 | |||
| 179 | $includeJquery = self::config()->include_jquery; |
||
| 180 | // In CMS, jQuery is already included |
||
| 181 | if (self::isAdminController()) { |
||
| 182 | $includeJquery = false; |
||
| 183 | } |
||
| 184 | // If jQuery is already included, set to false |
||
| 185 | $js = Requirements::backend()->get_javascript(); |
||
| 186 | foreach ($js as $url) { |
||
| 187 | $name = basename($url); |
||
| 188 | if ($name == 'jquery.js' || $name == 'jquery.min.js') { |
||
| 189 | $includeJquery = false; |
||
| 190 | break; |
||
| 191 | } |
||
| 192 | } |
||
| 193 | |||
| 194 | if ($includeJquery) { |
||
| 195 | $renderer->setEnableJqueryNoConflict(true); |
||
| 196 | } else { |
||
| 197 | $renderer->disableVendor('jquery'); |
||
| 198 | $renderer->setEnableJqueryNoConflict(false); |
||
| 199 | } |
||
| 200 | |||
| 201 | if (DebugBar::config()->enable_storage) { |
||
| 202 | $renderer->setOpenHandlerUrl('__debugbar'); |
||
| 203 | } |
||
| 204 | |||
| 205 | foreach ($renderer->getAssets('css') as $cssFile) { |
||
| 206 | Requirements::css(ltrim($cssFile, '/')); |
||
| 207 | } |
||
| 208 | |||
| 209 | foreach ($renderer->getAssets('js') as $jsFile) { |
||
| 210 | Requirements::javascript(ltrim($jsFile, '/')); |
||
| 211 | } |
||
| 212 | |||
| 213 | self::$renderer = $renderer; |
||
| 214 | } |
||
| 215 | |||
| 216 | public static function renderDebugBar() |
||
| 217 | { |
||
| 218 | if (!self::$renderer) { |
||
| 219 | return; |
||
| 220 | } |
||
| 221 | |||
| 222 | // Requirements may have been cleared (CMS iframes...) or not set (Security...) |
||
| 223 | $js = Requirements::backend()->get_javascript(); |
||
| 224 | if (!in_array('debugbar/assets/debugbar.js', $js)) { |
||
| 225 | return; |
||
| 226 | } |
||
| 227 | $initialize = true; |
||
| 228 | if (Director::is_ajax()) { |
||
| 229 | $initialize = false; |
||
| 230 | } |
||
| 231 | |||
| 232 | $script = self::$renderer->render($initialize); |
||
| 233 | return $script; |
||
| 234 | } |
||
| 235 | |||
| 236 | /** |
||
| 237 | * Determine why DebugBar is disabled |
||
| 238 | * |
||
| 239 | * @return string |
||
| 240 | */ |
||
| 241 | public static function whyDisabled() |
||
| 242 | { |
||
| 243 | if (!Director::isDev()) { |
||
| 244 | return 'Not in dev mode'; |
||
| 245 | } |
||
| 246 | if (self::isDisabled()) { |
||
| 247 | return 'Disabled by a constant or configuration'; |
||
| 248 | } |
||
| 249 | if (self::vendorNotInstalled()) { |
||
| 250 | return 'DebugBar is not installed in vendors'; |
||
| 251 | } |
||
| 252 | if (self::notLocalIp()) { |
||
| 253 | return 'Not a local ip'; |
||
| 254 | } |
||
| 255 | if (Director::is_cli()) { |
||
| 256 | return 'In CLI mode'; |
||
| 257 | } |
||
| 258 | if (self::isDevUrl()) { |
||
| 259 | return 'Dev tools'; |
||
| 260 | } |
||
| 261 | if (self::isAdminUrl() && !self::config()->enabled_in_admin) { |
||
| 262 | return 'In admin'; |
||
| 263 | } |
||
| 264 | return "I don't know why"; |
||
| 265 | } |
||
| 266 | |||
| 267 | public static function vendorNotInstalled() |
||
| 268 | { |
||
| 269 | return !class_exists('DebugBar\\StandardDebugBar'); |
||
| 270 | } |
||
| 271 | |||
| 272 | public static function notLocalIp() |
||
| 273 | { |
||
| 274 | if (!self::config()->check_local_ip) { |
||
| 275 | return false; |
||
| 276 | } |
||
| 277 | if (isset($_SERVER['REMOTE_ADDR'])) { |
||
| 278 | return !in_array($_SERVER['REMOTE_ADDR'], array('127.0.0.1', '::1', '1')); |
||
| 279 | } |
||
| 280 | return false; |
||
| 281 | } |
||
| 282 | |||
| 283 | public static function isDisabled() |
||
| 284 | { |
||
| 285 | if ((defined('DEBUGBAR_DISABLE') && DEBUGBAR_DISABLE) || static::config()->disabled) { |
||
| 286 | return true; |
||
| 287 | } |
||
| 288 | return false; |
||
| 289 | } |
||
| 290 | |||
| 291 | public static function isDevUrl() |
||
| 292 | { |
||
| 293 | return strpos(self::getRequestUrl(), '/dev/') === 0; |
||
| 294 | } |
||
| 295 | |||
| 296 | public static function isAdminUrl() |
||
| 297 | { |
||
| 298 | return strpos(self::getRequestUrl(), '/admin/') === 0; |
||
| 299 | } |
||
| 300 | |||
| 301 | public static function isAdminController() |
||
| 302 | { |
||
| 303 | if (Controller::curr()) { |
||
| 304 | return Controller::curr() instanceof LeftAndMain; |
||
| 305 | } |
||
| 306 | return self::isAdminUrl(); |
||
| 307 | } |
||
| 308 | |||
| 309 | /** |
||
| 310 | * Avoid triggering data collection for open handler |
||
| 311 | * |
||
| 312 | * @return boolean |
||
| 313 | */ |
||
| 314 | public static function isDebugBarRequest() |
||
| 315 | { |
||
| 316 | if ($url = self::getRequestUrl()) { |
||
| 317 | return strpos($url, '/__debugbar') === 0; |
||
| 318 | } |
||
| 319 | return true; |
||
| 320 | } |
||
| 321 | |||
| 322 | /** |
||
| 323 | * Get request url |
||
| 324 | * |
||
| 325 | * @return string |
||
| 326 | */ |
||
| 327 | public static function getRequestUrl() |
||
| 328 | { |
||
| 329 | if (isset($_REQUEST['url'])) { |
||
| 330 | return $_REQUEST['url']; |
||
| 331 | } |
||
| 332 | if (isset($_SERVER['REQUEST_URI'])) { |
||
| 333 | return $_SERVER['REQUEST_URI']; |
||
| 334 | } |
||
| 335 | return ''; |
||
| 336 | } |
||
| 337 | |||
| 338 | /** |
||
| 339 | * Helper to make code cleaner |
||
| 340 | * |
||
| 341 | * @param callable $callback |
||
| 342 | */ |
||
| 343 | public static function withDebugBar($callback) |
||
| 344 | { |
||
| 350 |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.