| Total Complexity | 47 | 
| Total Lines | 468 | 
| Duplicated Lines | 0 % | 
| Changes | 0 | ||
Complex classes like Webperf 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.
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 Webperf, and based on these observations, apply Extract Interface, too.
| 1 | <?php  | 
            ||
| 49 | class Webperf extends Plugin  | 
            ||
| 50 | { | 
            ||
| 51 | // Static Properties  | 
            ||
| 52 | // =========================================================================  | 
            ||
| 53 | |||
| 54 | /**  | 
            ||
| 55 | * @var Webperf  | 
            ||
| 56 | */  | 
            ||
| 57 | public static $plugin;  | 
            ||
| 58 | |||
| 59 | /**  | 
            ||
| 60 | * @var Settings  | 
            ||
| 61 | */  | 
            ||
| 62 | public static $settings;  | 
            ||
| 63 | |||
| 64 | /**  | 
            ||
| 65 | * @var int|null  | 
            ||
| 66 | */  | 
            ||
| 67 | public static $requestUuid;  | 
            ||
| 68 | |||
| 69 | /**  | 
            ||
| 70 | * @var int|null  | 
            ||
| 71 | */  | 
            ||
| 72 | public static $requestUrl;  | 
            ||
| 73 | |||
| 74 | /**  | 
            ||
| 75 | * @var bool  | 
            ||
| 76 | */  | 
            ||
| 77 | public static $beaconIncluded = false;  | 
            ||
| 78 | |||
| 79 | /**  | 
            ||
| 80 | * @var string  | 
            ||
| 81 | */  | 
            ||
| 82 | public static $renderType = 'html';  | 
            ||
| 83 | |||
| 84 | // Public Properties  | 
            ||
| 85 | // =========================================================================  | 
            ||
| 86 | |||
| 87 | /**  | 
            ||
| 88 | * @var string  | 
            ||
| 89 | */  | 
            ||
| 90 | public $schemaVersion = '1.0.0';  | 
            ||
| 91 | |||
| 92 | // Public Methods  | 
            ||
| 93 | // =========================================================================  | 
            ||
| 94 | |||
| 95 | /**  | 
            ||
| 96 | * @inheritdoc  | 
            ||
| 97 | */  | 
            ||
| 98 | public function init()  | 
            ||
| 99 |     { | 
            ||
| 100 | parent::init();  | 
            ||
| 101 | // Initialize properties  | 
            ||
| 102 | self::$plugin = $this;  | 
            ||
| 103 | self::$settings = $this->getSettings();  | 
            ||
| 104 |         try { | 
            ||
| 105 | self::$requestUuid = random_int(0, PHP_INT_MAX);  | 
            ||
| 106 |         } catch (\Exception $e) { | 
            ||
| 107 | self::$requestUuid = null;  | 
            ||
| 108 | }  | 
            ||
| 109 | $this->name = self::$settings->pluginName;  | 
            ||
| 110 | // Add in our components  | 
            ||
| 111 | $this->addComponents();  | 
            ||
| 112 | // Install event listeners  | 
            ||
| 113 | $this->installEventListeners();  | 
            ||
| 114 | // Load that we've loaded  | 
            ||
| 115 | Craft::info(  | 
            ||
| 116 | Craft::t(  | 
            ||
| 117 | 'webperf',  | 
            ||
| 118 |                 '{name} plugin loaded', | 
            ||
| 119 | ['name' => $this->name]  | 
            ||
| 120 | ),  | 
            ||
| 121 | __METHOD__  | 
            ||
| 122 | );  | 
            ||
| 123 | }  | 
            ||
| 124 | |||
| 125 | /**  | 
            ||
| 126 | * @inheritdoc  | 
            ||
| 127 | */  | 
            ||
| 128 | public function getSettingsResponse()  | 
            ||
| 132 | }  | 
            ||
| 133 | |||
| 134 | /**  | 
            ||
| 135 | * @inheritdoc  | 
            ||
| 136 | */  | 
            ||
| 137 | public function getCpNavItem()  | 
            ||
| 166 | }  | 
            ||
| 167 | |||
| 168 | // Protected Methods  | 
            ||
| 169 | // =========================================================================  | 
            ||
| 170 | |||
| 171 | /**  | 
            ||
| 172 | * Add in our components  | 
            ||
| 173 | */  | 
            ||
| 174 | protected function addComponents()  | 
            ||
| 175 |     { | 
            ||
| 176 | $request = Craft::$app->getRequest();  | 
            ||
| 177 |         if ($request->getIsSiteRequest() && !$request->getIsConsoleRequest()) { | 
            ||
| 178 |             try { | 
            ||
| 179 | $uri = $request->getPathInfo();  | 
            ||
| 180 |             } catch (InvalidConfigException $e) { | 
            ||
| 181 | $uri = '';  | 
            ||
| 182 | }  | 
            ||
| 183 | $this->setRequestUrl();  | 
            ||
| 184 | // Ignore our own controllers  | 
            ||
| 185 |             if (self::$settings->includeCraftProfiling && strpos($uri, 'webperf/') !== 0) { | 
            ||
| 186 | // Add in the ProfileTarget component  | 
            ||
| 187 |                 try { | 
            ||
| 188 |                     $this->set('profileTarget', [ | 
            ||
| 189 | 'class' => ProfileTarget::class,  | 
            ||
| 190 | 'levels' => ['profile'],  | 
            ||
| 191 | 'categories' => [],  | 
            ||
| 192 | 'logVars' => [],  | 
            ||
| 193 | 'except' => [],  | 
            ||
| 194 | ]);  | 
            ||
| 195 |                 } catch (InvalidConfigException $e) { | 
            ||
| 196 | Craft::error($e->getMessage(), __METHOD__);  | 
            ||
| 197 | }  | 
            ||
| 198 | // Attach our log target  | 
            ||
| 199 | Craft::$app->getLog()->targets['webperf'] = $this->profileTarget;  | 
            ||
| 200 | }  | 
            ||
| 201 | }  | 
            ||
| 202 | }  | 
            ||
| 203 | |||
| 204 | /**  | 
            ||
| 205 | * Set the request URL  | 
            ||
| 206 | */  | 
            ||
| 207 | protected function setRequestUrl()  | 
            ||
| 208 |     { | 
            ||
| 209 | self::$requestUrl = DataSample::PLACEHOLDER_URL;  | 
            ||
| 210 |         if (!self::$settings->includeBeacon) { | 
            ||
| 211 | $request = Craft::$app->getRequest();  | 
            ||
| 212 | self::$requestUrl = UrlHelper::stripQueryString(  | 
            ||
| 213 | urldecode($request->getAbsoluteUrl())  | 
            ||
| 214 | );  | 
            ||
| 215 | }  | 
            ||
| 216 | }  | 
            ||
| 217 | |||
| 218 | /**  | 
            ||
| 219 | * Install our event listeners.  | 
            ||
| 220 | */  | 
            ||
| 221 | protected function installEventListeners()  | 
            ||
| 222 |     { | 
            ||
| 223 | $request = Craft::$app->getRequest();  | 
            ||
| 224 | // Add in our event listeners that are needed for every request  | 
            ||
| 225 | $this->installGlobalEventListeners();  | 
            ||
| 226 | // Install only for non-console site requests  | 
            ||
| 227 |         if ($request->getIsSiteRequest() && !$request->getIsConsoleRequest()) { | 
            ||
| 228 | $this->installSiteEventListeners();  | 
            ||
| 229 | }  | 
            ||
| 230 | // Install only for non-console Control Panel requests  | 
            ||
| 231 |         if ($request->getIsCpRequest() && !$request->getIsConsoleRequest()) { | 
            ||
| 232 | $this->installCpEventListeners();  | 
            ||
| 233 | }  | 
            ||
| 234 | // Handler: EVENT_AFTER_INSTALL_PLUGIN  | 
            ||
| 235 | Event::on(  | 
            ||
| 236 | Plugins::class,  | 
            ||
| 237 | Plugins::EVENT_AFTER_INSTALL_PLUGIN,  | 
            ||
| 238 |             function (PluginEvent $event) { | 
            ||
| 239 |                 if ($event->plugin === $this) { | 
            ||
| 240 | // Invalidate our caches after we've been installed  | 
            ||
| 241 | $this->clearAllCaches();  | 
            ||
| 242 | // Send them to our welcome screen  | 
            ||
| 243 | $request = Craft::$app->getRequest();  | 
            ||
| 244 |                     if ($request->isCpRequest) { | 
            ||
| 245 | Craft::$app->getResponse()->redirect(UrlHelper::cpUrl(  | 
            ||
| 246 | 'webperf/dashboard',  | 
            ||
| 247 | [  | 
            ||
| 248 | 'showWelcome' => true,  | 
            ||
| 249 | ]  | 
            ||
| 250 | ))->send();  | 
            ||
| 251 | }  | 
            ||
| 252 | }  | 
            ||
| 253 | }  | 
            ||
| 254 | );  | 
            ||
| 255 | }  | 
            ||
| 256 | |||
| 257 | /**  | 
            ||
| 258 | * Install global event listeners for all request types  | 
            ||
| 259 | */  | 
            ||
| 260 | protected function installGlobalEventListeners()  | 
            ||
| 261 |     { | 
            ||
| 262 | // Handler: CraftVariable::EVENT_INIT  | 
            ||
| 263 | Event::on(  | 
            ||
| 264 | CraftVariable::class,  | 
            ||
| 265 | CraftVariable::EVENT_INIT,  | 
            ||
| 266 |             function (Event $event) { | 
            ||
| 267 | /** @var CraftVariable $variable */  | 
            ||
| 268 | $variable = $event->sender;  | 
            ||
| 269 |                 $variable->set('webperf', WebperfVariable::class); | 
            ||
| 270 | }  | 
            ||
| 271 | );  | 
            ||
| 272 | // Handler: Plugins::EVENT_AFTER_LOAD_PLUGINS  | 
            ||
| 273 | Event::on(  | 
            ||
| 274 | Plugins::class,  | 
            ||
| 275 | Plugins::EVENT_AFTER_LOAD_PLUGINS,  | 
            ||
| 276 |             function () { | 
            ||
| 277 | // Install these only after all other plugins have loaded  | 
            ||
| 278 | $request = Craft::$app->getRequest();  | 
            ||
| 279 | // Only respond to non-console site requests  | 
            ||
| 280 |                 if ($request->getIsSiteRequest() && !$request->getIsConsoleRequest()) { | 
            ||
| 281 | $this->handleSiteRequest();  | 
            ||
| 282 | }  | 
            ||
| 283 | // Respond to Control Panel requests  | 
            ||
| 284 |                 if ($request->getIsCpRequest() && !$request->getIsConsoleRequest()) { | 
            ||
| 285 | $this->handleAdminCpRequest();  | 
            ||
| 286 | }  | 
            ||
| 287 | }  | 
            ||
| 288 | );  | 
            ||
| 289 | }  | 
            ||
| 290 | |||
| 291 | /**  | 
            ||
| 292 | * Install site event listeners for site requests only  | 
            ||
| 293 | */  | 
            ||
| 294 | protected function installSiteEventListeners()  | 
            ||
| 295 |     { | 
            ||
| 296 | // Handler: UrlManager::EVENT_REGISTER_SITE_URL_RULES  | 
            ||
| 297 | Event::on(  | 
            ||
| 298 | UrlManager::class,  | 
            ||
| 299 | UrlManager::EVENT_REGISTER_SITE_URL_RULES,  | 
            ||
| 300 |             function (RegisterUrlRulesEvent $event) { | 
            ||
| 301 | Craft::debug(  | 
            ||
| 302 | 'UrlManager::EVENT_REGISTER_SITE_URL_RULES',  | 
            ||
| 303 | __METHOD__  | 
            ||
| 304 | );  | 
            ||
| 305 | // Register our Control Panel routes  | 
            ||
| 306 | $event->rules = array_merge(  | 
            ||
| 307 | $event->rules,  | 
            ||
| 308 | $this->customFrontendRoutes()  | 
            ||
| 309 | );  | 
            ||
| 310 | }  | 
            ||
| 311 | );  | 
            ||
| 312 | }  | 
            ||
| 313 | |||
| 314 | /**  | 
            ||
| 315 | * Install site event listeners for Control Panel requests only  | 
            ||
| 316 | */  | 
            ||
| 317 | protected function installCpEventListeners()  | 
            ||
| 318 |     { | 
            ||
| 319 | // Handler: UrlManager::EVENT_REGISTER_CP_URL_RULES  | 
            ||
| 320 | Event::on(  | 
            ||
| 321 | UrlManager::class,  | 
            ||
| 322 | UrlManager::EVENT_REGISTER_CP_URL_RULES,  | 
            ||
| 323 |             function (RegisterUrlRulesEvent $event) { | 
            ||
| 324 | Craft::debug(  | 
            ||
| 325 | 'UrlManager::EVENT_REGISTER_CP_URL_RULES',  | 
            ||
| 326 | __METHOD__  | 
            ||
| 327 | );  | 
            ||
| 328 | // Register our Control Panel routes  | 
            ||
| 329 | $event->rules = array_merge(  | 
            ||
| 330 | $event->rules,  | 
            ||
| 331 | $this->customAdminCpRoutes()  | 
            ||
| 332 | );  | 
            ||
| 333 | }  | 
            ||
| 334 | );  | 
            ||
| 335 | // Handler: Dashboard::EVENT_REGISTER_WIDGET_TYPES  | 
            ||
| 336 | Event::on(  | 
            ||
| 337 | Dashboard::class,  | 
            ||
| 338 | Dashboard::EVENT_REGISTER_WIDGET_TYPES,  | 
            ||
| 339 |             function (RegisterComponentTypesEvent $event) { | 
            ||
| 340 | $event->types[] = MetricsWidget::class;  | 
            ||
| 341 | }  | 
            ||
| 342 | );  | 
            ||
| 343 | // Handler: UserPermissions::EVENT_REGISTER_PERMISSIONS  | 
            ||
| 344 | Event::on(  | 
            ||
| 345 | UserPermissions::class,  | 
            ||
| 346 | UserPermissions::EVENT_REGISTER_PERMISSIONS,  | 
            ||
| 347 |             function (RegisterUserPermissionsEvent $event) { | 
            ||
| 348 | Craft::debug(  | 
            ||
| 349 | 'UserPermissions::EVENT_REGISTER_PERMISSIONS',  | 
            ||
| 350 | __METHOD__  | 
            ||
| 351 | );  | 
            ||
| 352 | // Register our custom permissions  | 
            ||
| 353 |                 $event->permissions[Craft::t('webperf', 'Webperf')] = $this->customAdminCpPermissions(); | 
            ||
| 354 | }  | 
            ||
| 355 | );  | 
            ||
| 356 | }  | 
            ||
| 357 | |||
| 358 | /**  | 
            ||
| 359 | * Handle site requests. We do it only after we receive the event  | 
            ||
| 360 | * EVENT_AFTER_LOAD_PLUGINS so that any pending db migrations can be run  | 
            ||
| 361 | * before our event listeners kick in  | 
            ||
| 362 | */  | 
            ||
| 363 | protected function handleSiteRequest()  | 
            ||
| 364 |     { | 
            ||
| 365 | // Don't include the beacon for response codes >= 400  | 
            ||
| 366 | $response = Craft::$app->getResponse();  | 
            ||
| 367 |         if ($response->statusCode < 400) { | 
            ||
| 368 | // Handler: View::EVENT_END_PAGE  | 
            ||
| 369 | Event::on(  | 
            ||
| 370 | View::class,  | 
            ||
| 371 | View::EVENT_END_PAGE,  | 
            ||
| 372 |                 function () { | 
            ||
| 373 | Craft::debug(  | 
            ||
| 374 | 'View::EVENT_END_PAGE',  | 
            ||
| 375 | __METHOD__  | 
            ||
| 376 | );  | 
            ||
| 377 | $view = Craft::$app->getView();  | 
            ||
| 378 | // The page is done rendering, include our beacon  | 
            ||
| 379 |                     if (Webperf::$settings->includeBeacon && $view->getIsRenderingPageTemplate()) { | 
            ||
| 380 |                         switch (self::$renderType) { | 
            ||
| 381 | case 'html':  | 
            ||
| 382 | Webperf::$plugin->beacons->includeHtmlBeacon();  | 
            ||
| 383 | self::$beaconIncluded = true;  | 
            ||
| 384 | break;  | 
            ||
| 385 | case 'amp-html':  | 
            ||
| 386 | Webperf::$plugin->beacons->includeAmpHtmlScript();  | 
            ||
| 387 | break;  | 
            ||
| 388 | }  | 
            ||
| 389 | }  | 
            ||
| 390 | }  | 
            ||
| 391 | );  | 
            ||
| 392 | // Handler: View::EVENT_END_BODY  | 
            ||
| 393 | Event::on(  | 
            ||
| 394 | View::class,  | 
            ||
| 395 | View::EVENT_END_BODY,  | 
            ||
| 396 |                 function () { | 
            ||
| 397 | Craft::debug(  | 
            ||
| 398 | 'View::EVENT_END_BODY',  | 
            ||
| 399 | __METHOD__  | 
            ||
| 400 | );  | 
            ||
| 401 | $view = Craft::$app->getView();  | 
            ||
| 402 | // The page is done rendering, include our beacon  | 
            ||
| 403 |                     if (Webperf::$settings->includeBeacon && $view->getIsRenderingPageTemplate()) { | 
            ||
| 404 |                         switch (self::$renderType) { | 
            ||
| 405 | case 'html':  | 
            ||
| 406 | break;  | 
            ||
| 407 | case 'amp-html':  | 
            ||
| 408 | Webperf::$plugin->beacons->includeAmpHtmlBeacon();  | 
            ||
| 409 | self::$beaconIncluded = true;  | 
            ||
| 410 | break;  | 
            ||
| 411 | }  | 
            ||
| 412 | }  | 
            ||
| 413 | }  | 
            ||
| 414 | );  | 
            ||
| 415 | }  | 
            ||
| 416 | }  | 
            ||
| 417 | |||
| 418 | /**  | 
            ||
| 419 | * Handle Control Panel requests. We do it only after we receive the event  | 
            ||
| 420 | * EVENT_AFTER_LOAD_PLUGINS so that any pending db migrations can be run  | 
            ||
| 421 | * before our event listeners kick in  | 
            ||
| 422 | */  | 
            ||
| 423 | protected function handleAdminCpRequest()  | 
            ||
| 424 |     { | 
            ||
| 425 | }  | 
            ||
| 426 | |||
| 427 | /**  | 
            ||
| 428 | * Clear all the caches!  | 
            ||
| 429 | */  | 
            ||
| 430 | public function clearAllCaches()  | 
            ||
| 431 |     { | 
            ||
| 432 | }  | 
            ||
| 433 | |||
| 434 | /**  | 
            ||
| 435 | * @inheritdoc  | 
            ||
| 436 | */  | 
            ||
| 437 | protected function createSettingsModel()  | 
            ||
| 438 |     { | 
            ||
| 439 | return new Settings();  | 
            ||
| 440 | }  | 
            ||
| 441 | |||
| 442 | /**  | 
            ||
| 443 | * @inheritdoc  | 
            ||
| 444 | */  | 
            ||
| 445 | protected function settingsHtml(): string  | 
            ||
| 446 |     { | 
            ||
| 447 | return Craft::$app->view->renderTemplate(  | 
            ||
| 448 | 'webperf/settings',  | 
            ||
| 449 | [  | 
            ||
| 450 | 'settings' => $this->getSettings()  | 
            ||
| 451 | ]  | 
            ||
| 452 | );  | 
            ||
| 453 | }  | 
            ||
| 454 | |||
| 455 | /**  | 
            ||
| 456 | * Return the custom frontend routes  | 
            ||
| 457 | *  | 
            ||
| 458 | * @return array  | 
            ||
| 459 | */  | 
            ||
| 460 | protected function customFrontendRoutes(): array  | 
            ||
| 461 |     { | 
            ||
| 462 | return [  | 
            ||
| 463 | // Beacon  | 
            ||
| 464 | '/webperf/metrics/beacon' => 'webperf/metrics/beacon',  | 
            ||
| 465 | // Render  | 
            ||
| 466 | '/webperf/render/amp-iframe' => 'webperf/render/amp-iframe',  | 
            ||
| 467 | // Tables  | 
            ||
| 468 | '/webperf/tables/dashboard' => 'webperf/tables/dashboard',  | 
            ||
| 469 | '/webperf/tables/redirects' => 'webperf/tables/redirects',  | 
            ||
| 470 | // Charts  | 
            ||
| 471 |             '/webperf/charts/dashboard-stats-average/<days:\d+>/<column:{handle}>' | 
            ||
| 472 | => 'webperf/charts/dashboard-stats-average',  | 
            ||
| 473 |             '/webperf/charts/dashboard-stats-average/<days:\d+>/<column:{handle}>/<siteId:\d+>' | 
            ||
| 474 | => 'webperf/charts/dashboard-stats-average',  | 
            ||
| 475 |             '/webperf/charts/dashboard-slowest-pages/<days:\d+>/<column:{handle}>/<limit:\d+>' | 
            ||
| 476 | => 'webperf/charts/dashboard-slowest-pages',  | 
            ||
| 477 |             '/webperf/charts/dashboard-slowest-pages/<days:\d+>/<column:{handle}>/<limit:\d+>/<siteId:\d+>' | 
            ||
| 478 | => 'webperf/charts/dashboard-slowest-pages',  | 
            ||
| 479 | '/webperf/charts/widget/<days>' => 'webperf/charts/widget',  | 
            ||
| 480 | ];  | 
            ||
| 481 | }  | 
            ||
| 482 | /**  | 
            ||
| 483 | * Return the custom Control Panel routes  | 
            ||
| 484 | *  | 
            ||
| 485 | * @return array  | 
            ||
| 486 | */  | 
            ||
| 487 | protected function customAdminCpRoutes(): array  | 
            ||
| 488 |     { | 
            ||
| 489 | return [  | 
            ||
| 490 | 'webperf' => 'webperf/sections/dashboard',  | 
            ||
| 491 | 'webperf/dashboard' => 'webperf/sections/dashboard',  | 
            ||
| 492 |             'webperf/dashboard/<siteHandle:{handle}>' => 'webperf/sections/dashboard', | 
            ||
| 493 | |||
| 494 | 'webperf/pages' => 'webperf/sections/pages-index',  | 
            ||
| 495 |             'webperf/pages/<siteHandle:{handle}>' => 'webperf/sections/pages-index', | 
            ||
| 496 | |||
| 497 | 'webperf/settings' => 'webperf/settings/plugin-settings',  | 
            ||
| 498 | ];  | 
            ||
| 499 | }  | 
            ||
| 500 | |||
| 501 | /**  | 
            ||
| 502 | * Returns the custom Control Panel user permissions.  | 
            ||
| 503 | *  | 
            ||
| 504 | * @return array  | 
            ||
| 505 | */  | 
            ||
| 506 | protected function customAdminCpPermissions(): array  | 
            ||
| 517 | ],  | 
            ||
| 518 | ];  | 
            ||
| 519 | }  | 
            ||
| 520 | }  | 
            ||
| 521 |