Passed
Push — v1 ( 0f87a2...543469 )
by Andrew
08:17 queued 04:56
created

Webperf::getCpNavItem()   B

Complexity

Conditions 7
Paths 32

Size

Total Lines 52
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 36
dl 0
loc 52
rs 8.4106
c 0
b 0
f 0
cc 7
nc 32
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Webperf plugin for Craft CMS 3.x
4
 *
5
 * Monitor the performance of your webpages through real-world user timing data
6
 *
7
 * @link      https://nystudio107.com
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @copyright tag
Loading history...
8
 * @copyright Copyright (c) 2019 nystudio107
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
9
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
Coding Style introduced by
Missing @package tag in file comment
Loading history...
Coding Style introduced by
Missing @author tag in file comment
Loading history...
Coding Style introduced by
Missing @license tag in file comment
Loading history...
10
11
namespace nystudio107\webperf;
12
13
use nystudio107\webperf\base\CraftDataSample;
14
use nystudio107\webperf\log\ErrorsTarget;
15
use nystudio107\webperf\log\ProfileTarget;
16
use nystudio107\webperf\models\RecommendationDataSample;
17
use nystudio107\webperf\models\Settings;
18
use nystudio107\webperf\services\DataSamples as DataSamplesService;
19
use nystudio107\webperf\services\ErrorSamples as ErrorSamplesService;
20
use nystudio107\webperf\services\Beacons as BeaconsService;
21
use nystudio107\webperf\services\Recommendations as RecommendationsService;
22
use nystudio107\webperf\variables\WebperfVariable;
23
use nystudio107\webperf\widgets\Metrics as MetricsWidget;
24
25
use Craft;
0 ignored issues
show
Bug introduced by
The type Craft was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
26
use craft\base\Plugin;
0 ignored issues
show
Bug introduced by
The type craft\base\Plugin was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
27
use craft\services\Plugins;
0 ignored issues
show
Bug introduced by
The type craft\services\Plugins was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
28
use craft\events\PluginEvent;
0 ignored issues
show
Bug introduced by
The type craft\events\PluginEvent was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
29
use craft\events\RegisterComponentTypesEvent;
0 ignored issues
show
Bug introduced by
The type craft\events\RegisterComponentTypesEvent was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
30
use craft\events\RegisterUserPermissionsEvent;
0 ignored issues
show
Bug introduced by
The type craft\events\RegisterUserPermissionsEvent was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
31
use craft\events\RegisterUrlRulesEvent;
0 ignored issues
show
Bug introduced by
The type craft\events\RegisterUrlRulesEvent was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
32
use craft\helpers\UrlHelper;
0 ignored issues
show
Bug introduced by
The type craft\helpers\UrlHelper was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
33
use craft\services\Dashboard;
0 ignored issues
show
Bug introduced by
The type craft\services\Dashboard was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
34
use craft\services\UserPermissions;
0 ignored issues
show
Bug introduced by
The type craft\services\UserPermissions was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
35
use craft\web\Application;
0 ignored issues
show
Bug introduced by
The type craft\web\Application was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
36
use craft\web\twig\variables\CraftVariable;
0 ignored issues
show
Bug introduced by
The type craft\web\twig\variables\CraftVariable was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
37
use craft\web\UrlManager;
0 ignored issues
show
Bug introduced by
The type craft\web\UrlManager was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
38
use craft\web\View;
0 ignored issues
show
Bug introduced by
The type craft\web\View was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
39
40
use yii\base\Event;
0 ignored issues
show
Bug introduced by
The type yii\base\Event was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
41
use yii\base\InvalidConfigException;
0 ignored issues
show
Bug introduced by
The type yii\base\InvalidConfigException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
42
43
/**
44
 * Class Webperf
45
 *
46
 * @author    nystudio107
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @package tag
Loading history...
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 4
Loading history...
47
 * @package   Webperf
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 3
Loading history...
48
 * @since     1.0.0
0 ignored issues
show
Coding Style introduced by
The tag in position 3 should be the @author tag
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 3 spaces but found 5
Loading history...
49
 *
50
 * @property  RecommendationsService  $recommendations
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 2
Loading history...
51
 * @property  DataSamplesService      $dataSamples
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 2
Loading history...
52
 * @property  ErrorSamplesService     $errorSamples
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 2
Loading history...
53
 * @property  BeaconsService          $beacons
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 2
Loading history...
54
 * @property  ErrorsTarget            $errorsTarget
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 2
Loading history...
55
 * @property  ProfileTarget           $profileTarget
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 2
Loading history...
56
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
57
class Webperf extends Plugin
58
{
59
    // Constants
60
    // =========================================================================
61
62
    const RECOMMENDATIONS_CACHE_KEY = 'webperf-recommendations';
63
    const RECOMMENDATIONS_CACHE_DURATION = 60;
64
65
    // Static Properties
66
    // =========================================================================
67
68
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
69
     * @var Webperf
70
     */
71
    public static $plugin;
72
73
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
74
     * @var Settings
75
     */
76
    public static $settings;
77
78
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
79
     * @var int|null
80
     */
81
    public static $requestUuid;
82
83
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
84
     * @var int|null
85
     */
86
    public static $requestUrl;
87
88
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
89
     * @var bool
90
     */
91
    public static $beaconIncluded = false;
92
93
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
94
     * @var string
95
     */
96
    public static $renderType = 'html';
97
98
    // Public Properties
99
    // =========================================================================
100
101
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
102
     * @var string
103
     */
104
    public $schemaVersion = '1.0.0';
105
106
    // Public Methods
107
    // =========================================================================
108
109
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
110
     * @inheritdoc
111
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
112
    public function init()
113
    {
114
        parent::init();
115
        // Initialize properties
116
        self::$plugin = $this;
117
        self::$settings = $this->getSettings();
118
        try {
119
            self::$requestUuid = random_int(0, PHP_INT_MAX);
120
        } catch (\Exception $e) {
121
            self::$requestUuid = null;
122
        }
123
        $this->name = self::$settings->pluginName;
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
124
        // Handle any console commands
125
        $request = Craft::$app->getRequest();
126
        if ($request->getIsConsoleRequest()) {
127
            $this->controllerNamespace = 'nystudio107\webperf\console\controllers';
0 ignored issues
show
Bug Best Practice introduced by
The property controllerNamespace does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
128
        }
129
        // Add in our components
130
        $this->addComponents();
131
        // Install event listeners
132
        $this->installEventListeners();
133
        // Load that we've loaded
134
        Craft::info(
135
            Craft::t(
136
                'webperf',
137
                '{name} plugin loaded',
138
                ['name' => $this->name]
139
            ),
140
            __METHOD__
141
        );
142
    }
143
144
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
145
     * @inheritdoc
146
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
147
    public function getSettingsResponse()
148
    {
149
        // Just redirect to the plugin settings page
150
        Craft::$app->getResponse()->redirect(UrlHelper::cpUrl('webperf/settings'));
151
    }
152
153
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
154
     * @inheritdoc
155
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
156
    public function getCpNavItem()
157
    {
158
        $subNavs = [];
159
        $navItem = parent::getCpNavItem();
160
        $cache = Craft::$app->getCache();
161
        // See if there are any recommendations to add as a badge
162
        $recommendations = $cache->getOrSet(self::RECOMMENDATIONS_CACHE_KEY, function () {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
163
            $data = [];
164
            $now = new \DateTime();
165
            $end = $now->format('Y-m-d');
166
            $start = $now->modify('-1 year')->format('Y-m-d');
167
            $stats = Webperf::$plugin->recommendations->data('', $start, $end);
168
            if (!empty($stats)) {
169
                $recSample = new RecommendationDataSample($stats);
170
                $data = Webperf::$plugin->recommendations->list($recSample);
171
            }
172
            return count($data);
173
        }, self::RECOMMENDATIONS_CACHE_DURATION);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
174
        if ($recommendations) {
175
            $navItem['badgeCount'] = $recommendations;
176
        }
177
        $currentUser = Craft::$app->getUser()->getIdentity();
178
        // Only show sub-navs the user has permission to view
179
        if ($currentUser->can('webperf:dashboard')) {
180
            $subNavs['dashboard'] = [
181
                'label' => 'Dashboard',
182
                'url' => 'webperf/dashboard',
183
            ];
184
        }
185
        if ($currentUser->can('webperf:performance')) {
186
            $subNavs['performance'] = [
187
                'label' => 'Performance',
188
                'url' => 'webperf/performance',
189
            ];
190
        }
191
        if ($currentUser->can('webperf:errors')) {
192
            $subNavs['errors'] = [
193
                'label' => 'Errors',
194
                'url' => 'webperf/errors',
195
            ];
196
        }
197
        if ($currentUser->can('webperf:settings')) {
198
            $subNavs['settings'] = [
199
                'label' => 'Settings',
200
                'url' => 'webperf/settings',
201
            ];
202
        }
203
        $navItem = array_merge($navItem, [
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
204
            'subnav' => $subNavs,
205
        ]);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
206
207
        return $navItem;
208
    }
209
210
    // Protected Methods
211
    // =========================================================================
212
213
    /**
214
     * Add in our components
215
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
216
    protected function addComponents()
217
    {
218
        $request = Craft::$app->getRequest();
219
        if ($request->getIsSiteRequest() && !$request->getIsConsoleRequest()) {
220
            $this->setRequestUrl();
221
            try {
222
                $uri = $request->getPathInfo();
223
            } catch (InvalidConfigException $e) {
224
                $uri = '';
225
            }
226
            // Ignore our own controllers
227
            if (self::$settings->includeCraftProfiling && strpos($uri, 'webperf/') === false) {
228
                // Add in the ProfileTarget component
229
                try {
230
                    $this->set('profileTarget', [
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
231
                        'class' => ProfileTarget::class,
232
                        'levels' => ['profile'],
233
                        'categories' => [],
234
                        'logVars' => [],
235
                        'except' => [],
236
                    ]);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
237
                } catch (InvalidConfigException $e) {
238
                    Craft::error($e->getMessage(), __METHOD__);
239
                }
240
                // Attach our log target
241
                Craft::$app->getLog()->targets['webperf-profile'] = $this->profileTarget;
242
                // Add in the ErrorsTarget component
243
                $except = [];
244
                // If devMode is on, exclude errors/warnings from `seomatic`
245
                if (Craft::$app->getConfig()->getGeneral()->devMode) {
246
                    $except = ['nystudio107\seomatic\*'];
247
                }
248
                try {
249
                    $this->set('errorsTarget', [
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
250
                        'class' => ErrorsTarget::class,
251
                        'levels' => ['error','warning'],
252
                        'categories' => [],
253
                        'logVars' => [],
254
                        'except' => $except,
255
                    ]);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
256
                } catch (InvalidConfigException $e) {
257
                    Craft::error($e->getMessage(), __METHOD__);
258
                }
259
                // Attach our log target
260
                Craft::$app->getLog()->targets['webperf-errors'] = $this->errorsTarget;
261
            }
262
        }
263
    }
264
265
    /**
266
     * Set the request URL
267
     *
268
     * @param bool $force
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
269
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
270
    protected function setRequestUrl(bool $force = false)
271
    {
272
        self::$requestUrl = CraftDataSample::PLACEHOLDER_URL;
0 ignored issues
show
Documentation Bug introduced by
It seems like nystudio107\webperf\base...Sample::PLACEHOLDER_URL of type string is incompatible with the declared type integer|null of property $requestUrl.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
273
        if (!self::$settings->includeBeacon || $force || self::$settings->staticCachedSite) {
274
            $request = Craft::$app->getRequest();
275
            self::$requestUrl = UrlHelper::stripQueryString(
276
                urldecode($request->getAbsoluteUrl())
277
            );
278
        }
279
    }
280
281
    /**
282
     * Install our event listeners.
283
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
284
    protected function installEventListeners()
285
    {
286
        $request = Craft::$app->getRequest();
287
        // Add in our event listeners that are needed for every request
288
        $this->installGlobalEventListeners();
289
        // Install only for non-console site requests
290
        if ($request->getIsSiteRequest() && !$request->getIsConsoleRequest()) {
291
            $this->installSiteEventListeners();
292
        }
293
        // Install only for non-console Control Panel requests
294
        if ($request->getIsCpRequest() && !$request->getIsConsoleRequest()) {
295
            $this->installCpEventListeners();
296
        }
297
        // Handler: EVENT_AFTER_INSTALL_PLUGIN
298
        Event::on(
299
            Plugins::class,
300
            Plugins::EVENT_AFTER_INSTALL_PLUGIN,
301
            function (PluginEvent $event) {
302
                if ($event->plugin === $this) {
303
                    // Invalidate our caches after we've been installed
304
                    $this->clearAllCaches();
305
                    // Send them to our welcome screen
306
                    $request = Craft::$app->getRequest();
307
                    if ($request->isCpRequest) {
308
                        Craft::$app->getResponse()->redirect(UrlHelper::cpUrl(
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
309
                            'webperf/dashboard',
310
                            [
311
                                'showWelcome' => true,
312
                            ]
313
                        ))->send();
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
314
                    }
315
                }
316
            }
317
        );
318
    }
319
320
    /**
321
     * Install global event listeners for all request types
322
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
323
    protected function installGlobalEventListeners()
324
    {
325
        // Handler: CraftVariable::EVENT_INIT
326
        Event::on(
327
            CraftVariable::class,
328
            CraftVariable::EVENT_INIT,
329
            function (Event $event) {
330
                /** @var CraftVariable $variable */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
331
                $variable = $event->sender;
332
                $variable->set('webperf', WebperfVariable::class);
333
            }
334
        );
335
        // Handler: Plugins::EVENT_AFTER_LOAD_PLUGINS
336
        Event::on(
337
            Plugins::class,
338
            Plugins::EVENT_AFTER_LOAD_PLUGINS,
339
            function () {
340
                // Install these only after all other plugins have loaded
341
                $request = Craft::$app->getRequest();
342
                // Only respond to non-console site requests
343
                if ($request->getIsSiteRequest() && !$request->getIsConsoleRequest()) {
344
                    $this->handleSiteRequest();
345
                }
346
                // Respond to Control Panel requests
347
                if ($request->getIsCpRequest() && !$request->getIsConsoleRequest()) {
348
                    $this->handleAdminCpRequest();
349
                }
350
            }
351
        );
352
    }
353
354
    /**
355
     * Install site event listeners for site requests only
356
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
357
    protected function installSiteEventListeners()
358
    {
359
        // Handler: UrlManager::EVENT_REGISTER_SITE_URL_RULES
360
        Event::on(
361
            UrlManager::class,
362
            UrlManager::EVENT_REGISTER_SITE_URL_RULES,
363
            function (RegisterUrlRulesEvent $event) {
364
                Craft::debug(
365
                    'UrlManager::EVENT_REGISTER_SITE_URL_RULES',
366
                    __METHOD__
367
                );
368
                // Register our Control Panel routes
369
                $event->rules = array_merge(
370
                    $event->rules,
371
                    $this->customFrontendRoutes()
372
                );
373
            }
374
        );
375
    }
376
377
    /**
378
     * Install site event listeners for Control Panel requests only
379
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
380
    protected function installCpEventListeners()
381
    {
382
        // Handler: UrlManager::EVENT_REGISTER_CP_URL_RULES
383
        Event::on(
384
            UrlManager::class,
385
            UrlManager::EVENT_REGISTER_CP_URL_RULES,
386
            function (RegisterUrlRulesEvent $event) {
387
                Craft::debug(
388
                    'UrlManager::EVENT_REGISTER_CP_URL_RULES',
389
                    __METHOD__
390
                );
391
                // Register our Control Panel routes
392
                $event->rules = array_merge(
393
                    $event->rules,
394
                    $this->customAdminCpRoutes()
395
                );
396
            }
397
        );
398
        // Handler: Dashboard::EVENT_REGISTER_WIDGET_TYPES
399
        Event::on(
400
            Dashboard::class,
401
            Dashboard::EVENT_REGISTER_WIDGET_TYPES,
402
            function (RegisterComponentTypesEvent $event) {
403
                $event->types[] = MetricsWidget::class;
404
            }
405
        );
406
        // Handler: UserPermissions::EVENT_REGISTER_PERMISSIONS
407
        Event::on(
408
            UserPermissions::class,
409
            UserPermissions::EVENT_REGISTER_PERMISSIONS,
410
            function (RegisterUserPermissionsEvent $event) {
411
                Craft::debug(
412
                    'UserPermissions::EVENT_REGISTER_PERMISSIONS',
413
                    __METHOD__
414
                );
415
                // Register our custom permissions
416
                $event->permissions[Craft::t('webperf', 'Webperf')] = $this->customAdminCpPermissions();
417
            }
418
        );
419
    }
420
421
    /**
422
     * Handle site requests.  We do it only after we receive the event
423
     * EVENT_AFTER_LOAD_PLUGINS so that any pending db migrations can be run
424
     * before our event listeners kick in
425
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
426
    protected function handleSiteRequest()
427
    {
428
        // Don't include the beacon for response codes >= 400
429
        $response = Craft::$app->getResponse();
430
        if ($response->statusCode < 400) {
431
            // Handler: View::EVENT_END_PAGE
432
            Event::on(
433
                View::class,
434
                View::EVENT_END_PAGE,
435
                function () {
436
                    Craft::debug(
437
                        'View::EVENT_END_PAGE',
438
                        __METHOD__
439
                    );
440
                    $view = Craft::$app->getView();
441
                    // The page is done rendering, include our beacon
442
                    if (Webperf::$settings->includeBeacon && $view->getIsRenderingPageTemplate()) {
443
                        switch (self::$renderType) {
444
                            case 'html':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
445
                                Webperf::$plugin->beacons->includeHtmlBeacon();
446
                                self::$beaconIncluded = true;
447
                                break;
448
                            case 'amp-html':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
449
                                Webperf::$plugin->beacons->includeAmpHtmlScript();
450
                                break;
451
                        }
452
                    }
453
                }
454
            );
455
            // Handler: View::EVENT_END_BODY
456
            Event::on(
457
                View::class,
458
                View::EVENT_END_BODY,
459
                function () {
460
                    Craft::debug(
461
                        'View::EVENT_END_BODY',
462
                        __METHOD__
463
                    );
464
                    $view = Craft::$app->getView();
465
                    // The page is done rendering, include our beacon
466
                    if (Webperf::$settings->includeBeacon && $view->getIsRenderingPageTemplate()) {
467
                        switch (self::$renderType) {
468
                            case 'html':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
469
                                break;
470
                            case 'amp-html':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
471
                                Webperf::$plugin->beacons->includeAmpHtmlBeacon();
472
                                self::$beaconIncluded = true;
473
                                break;
474
                        }
475
                    }
476
                }
477
            );
478
            // Handler: Application::EVENT_AFTER_REQUEST
479
            Event::on(
480
                Application::class,
481
                Application::EVENT_AFTER_REQUEST,
482
                function () {
483
                    Craft::debug(
484
                        'Application::EVENT_AFTER_REQUEST',
485
                        __METHOD__
486
                    );
487
                    // If the beacon wasn't included, allow for the Craft timings
488
                    if (!self::$beaconIncluded) {
489
                        $this->setRequestUrl(true);
490
                    }
491
                }
492
            );
493
        }
494
    }
495
496
    /**
497
     * Handle Control Panel requests. We do it only after we receive the event
498
     * EVENT_AFTER_LOAD_PLUGINS so that any pending db migrations can be run
499
     * before our event listeners kick in
500
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
501
    protected function handleAdminCpRequest()
502
    {
503
    }
504
505
    /**
506
     * Clear all the caches!
507
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
508
    public function clearAllCaches()
509
    {
510
    }
511
512
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
513
     * @inheritdoc
514
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
515
    protected function createSettingsModel()
516
    {
517
        return new Settings();
518
    }
519
520
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
521
     * @inheritdoc
522
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
523
    protected function settingsHtml(): string
524
    {
525
        return Craft::$app->view->renderTemplate(
526
            'webperf/settings',
527
            [
528
                'settings' => $this->getSettings()
529
            ]
530
        );
531
    }
532
533
    /**
534
     * Return the custom frontend routes
535
     *
536
     * @return array
537
     */
538
    protected function customFrontendRoutes(): array
539
    {
540
        return [
541
            // Beacon
542
            '/webperf/metrics/beacon' => 'webperf/metrics/beacon',
543
            // Render
544
            '/webperf/render/amp-iframe' => 'webperf/render/amp-iframe',
545
            // Tables
546
            '/webperf/tables/pages-index' => 'webperf/tables/pages-index',
547
            '/webperf/tables/page-detail' => 'webperf/tables/page-detail',
548
            // Charts
549
            '/webperf/charts/dashboard-stats-average/<column:{handle}>'
550
            => 'webperf/charts/dashboard-stats-average',
551
            '/webperf/charts/dashboard-stats-average/<column:{handle}>/<siteId:\d+>'
552
            => 'webperf/charts/dashboard-stats-average',
553
554
            '/webperf/charts/dashboard-slowest-pages/<column:{handle}>/<limit:\d+>'
555
            => 'webperf/charts/dashboard-slowest-pages',
556
            '/webperf/charts/dashboard-slowest-pages/<column:{handle}>/<limit:\d+>/<siteId:\d+>'
557
            => 'webperf/charts/dashboard-slowest-pages',
558
559
            '/webperf/charts/pages-area-chart'
560
            => 'webperf/charts/pages-area-chart',
561
            '/webperf/charts/pages-area-chart/<siteId:\d+>'
562
            => 'webperf/charts/pages-area-chart',
563
564
            '/webperf/recommendations/list'
565
            => 'webperf/recommendations/list',
566
            '/webperf/recommendations/list/<siteId:\d+>'
567
            => 'webperf/recommendations/list',
568
569
            '/webperf/charts/widget/<days>' => 'webperf/charts/widget',
570
        ];
571
    }
572
    /**
573
     * Return the custom Control Panel routes
574
     *
575
     * @return array
576
     */
577
    protected function customAdminCpRoutes(): array
578
    {
579
        return [
580
            'webperf' => 'webperf/sections/dashboard',
581
            'webperf/dashboard' => 'webperf/sections/dashboard',
582
            'webperf/dashboard/<siteHandle:{handle}>' => 'webperf/sections/dashboard',
583
584
            'webperf/performance' => 'webperf/sections/pages-index',
585
            'webperf/performance/<siteHandle:{handle}>' => 'webperf/sections/pages-index',
586
587
            'webperf/performance/page-detail' => 'webperf/sections/page-detail',
588
            'webperf/performance/page-detail/<siteHandle:{handle}>' => 'webperf/sections/page-detail',
589
590
            'webperf/errors' => 'webperf/sections/errors-index',
591
            'webperf/errors/<siteHandle:{handle}>' => 'webperf/sections/errors-index',
592
593
            'webperf/errors/page-detail' => 'webperf/sections/errors-detail',
594
            'webperf/errors/page-detail/<siteHandle:{handle}>' => 'webperf/errors/page-detail',
595
596
            'webperf/settings' => 'webperf/settings/plugin-settings',
597
        ];
598
    }
599
600
    /**
601
     * Returns the custom Control Panel user permissions.
602
     *
603
     * @return array
604
     */
605
    protected function customAdminCpPermissions(): array
606
    {
607
        return [
608
            'webperf:dashboard' => [
609
                'label' => Craft::t('webperf', 'Dashboard'),
610
            ],
611
            'webperf:performance' => [
612
                'label' => Craft::t('webperf', 'Performance'),
613
            ],
614
            'webperf:performance-detail' => [
615
                'label' => Craft::t('webperf', 'Performance Detail'),
616
            ],
617
            'webperf:delete-data-samples' => [
618
                'label' => Craft::t('webperf', 'Delete Data Samples'),
619
            ],
620
            'webperf:errors' => [
621
                'label' => Craft::t('webperf', 'Errors'),
622
            ],
623
            'webperf:errors-detail' => [
624
                'label' => Craft::t('webperf', 'Errors Detail'),
625
            ],
626
            'webperf:delete-error-samples' => [
627
                'label' => Craft::t('webperf', 'Delete Error Samples'),
628
            ],
629
            'webperf:recommendations' => [
630
                'label' => Craft::t('webperf', 'Recommendations'),
631
            ],
632
            'webperf:settings' => [
633
                'label' => Craft::t('webperf', 'Settings'),
634
            ],
635
        ];
636
    }
637
}
638