Passed
Push — v1 ( ce78b2...2675f6 )
by Andrew
06:06 queued 03:01
created

TablesController::actionErrorsIndex()   D

Complexity

Conditions 14
Paths 240

Size

Total Lines 127
Code Lines 85

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 85
dl 0
loc 127
rs 4.2739
c 0
b 0
f 0
cc 14
nc 240
nop 7

How to fix   Long Method    Complexity   

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\controllers;
12
13
use nystudio107\webperf\helpers\Permission as PermissionHelper;
14
15
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...
16
use craft\db\Query;
0 ignored issues
show
Bug introduced by
The type craft\db\Query 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...
17
use craft\helpers\DateTimeHelper;
0 ignored issues
show
Bug introduced by
The type craft\helpers\DateTimeHelper 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...
18
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...
19
use craft\web\Controller;
0 ignored issues
show
Bug introduced by
The type craft\web\Controller 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...
20
21
use yii\web\ForbiddenHttpException;
0 ignored issues
show
Bug introduced by
The type yii\web\ForbiddenHttpException 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...
22
use yii\web\Response;
0 ignored issues
show
Bug introduced by
The type yii\web\Response 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...
23
24
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
25
 * @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...
26
 * @package   Webperf
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 3
Loading history...
27
 * @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...
28
 */
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...
29
class TablesController extends Controller
30
{
31
    // Constants
32
    // =========================================================================
33
34
    // Protected Properties
35
    // =========================================================================
36
37
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
38
     * @var    bool|array
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 4
Loading history...
39
     */
40
    protected $allowAnonymous = [];
41
42
    // Public Methods
43
    // =========================================================================
44
45
    /**
46
     * Handle requests for the performance index table
47
     *
48
     * @param string $sort
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $sort does not match actual variable name $start
Loading history...
49
     * @param int    $page
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $page does not match actual variable name $end
Loading history...
50
     * @param int    $per_page
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $per_page does not match actual variable name $sort
Loading history...
51
     * @param string $filter
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $filter does not match actual variable name $page
Loading history...
52
     * @param string $start
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $start does not match actual variable name $per_page
Loading history...
53
     * @param string $end
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $end does not match actual variable name $filter
Loading history...
54
     * @param int    $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
55
     *
56
     * @return Response
57
     * @throws ForbiddenHttpException
58
     */
59
    public function actionPagesIndex(
60
        string $start = '',
61
        string $end = '',
62
        string $sort = 'pageLoad|DESC',
63
        int $page = 1,
64
        int $per_page = 20,
65
        $filter = '',
66
        $siteId = 0
67
    ): Response {
68
        PermissionHelper::controllerPermissionCheck('webperf:performance');
69
        $data = [];
70
        $sortField = 'pageLoad';
71
        $sortType = 'DESC';
72
        // Add a day since YYYY-MM-DD is really YYYY-MM-DD 00:00:00
73
        $end = date('Y-m-d', strtotime($end.'+1 day'));
74
        // Figure out the sorting type
75
        if ($sort !== '') {
76
            if (strpos($sort, '|') === false) {
77
                $sortField = $sort;
78
            } else {
79
                list($sortField, $sortType) = explode('|', $sort);
80
            }
81
        }
82
        // Query the db table
83
        $offset = ($page - 1) * $per_page;
84
        $query = (new Query())
85
            ->select([
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...
86
                '[[url]]',
87
                'MIN([[title]]) AS [[title]]',
88
                'COUNT([[url]]) AS [[cnt]]',
89
                'AVG([[pageLoad]]) AS [[pageLoad]]',
90
                'AVG([[domInteractive]]) AS [[domInteractive]]',
91
                'AVG([[firstContentfulPaint]]) AS [[firstContentfulPaint]]',
92
                'AVG([[firstPaint]]) AS [[firstPaint]]',
93
                'AVG([[firstByte]]) AS [[firstByte]]',
94
                'AVG([[connect]]) AS [[connect]]',
95
                'AVG([[dns]]) AS [[dns]]',
96
                'AVG([[craftTotalMs]]) AS [[craftTotalMs]]',
97
                'AVG([[craftDbCnt]]) AS [[craftDbCnt]]',
98
                'AVG([[craftDbMs]]) AS [[craftDbMs]]',
99
                'AVG([[craftTwigCnt]]) AS [[craftTwigCnt]]',
100
                'AVG([[craftTwigMs]]) AS [[craftTwigMs]]',
101
                'AVG([[craftTotalMemory]]) AS [[craftTotalMemory]]',
102
            ])
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...
103
            ->from(['{{%webperf_data_samples}}'])
104
            ->offset($offset)
105
            ->where(['between', 'dateCreated', $start, $end])
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
106
        ;
107
        if ((int)$siteId !== 0) {
108
            $query->andWhere(['siteId' => $siteId]);
109
        }
110
        if ($filter !== '') {
111
            $query
112
                ->andWhere(['like', 'url', $filter])
113
                ->orWhere(['like', 'title', $filter])
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
114
            ;
115
        }
116
        $query
117
            ->orderBy("[[{$sortField}]] {$sortType}")
118
            ->groupBy('url')
119
            ->limit($per_page)
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
120
        ;
121
122
        $stats = $query->all();
123
        if ($stats) {
124
            $user = Craft::$app->getUser()->getIdentity();
125
            // Compute the largest page load time
126
            $maxTotalPageLoad = 0;
127
            foreach ($stats as &$stat) {
128
             // Determine the stat type
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected at least 16 spaces, found 13
Loading history...
129
                if (!empty($stat['pageLoad']) && !empty($stat['craftTotalMs'])) {
130
                    $stat['type'] = 'both';
131
                }
132
                if (empty($stat['firstByte'])) {
133
                    $stat['type'] = 'craft';
134
                }
135
                if (empty($stat['craftTotalMs'])) {
136
                    $stat['type'] = 'frontend';
137
                }
138
                if ($stat['pageLoad'] > $maxTotalPageLoad) {
139
                    $maxTotalPageLoad = $stat['pageLoad'];
140
                }
141
            }
142
            // Massage the stats
143
            $index = 1;
144
            foreach ($stats as &$stat) {
145
                $stat['id'] = $index++;
146
                $stat['cnt'] = (int)$stat['cnt'];
147
                $stat['maxTotalPageLoad'] = (int)$maxTotalPageLoad;
148
                // Decode any emojis in the title
149
                if (!empty($stat['title'])) {
150
                    $stat['title'] = html_entity_decode($stat['title'], ENT_NOQUOTES, 'UTF-8');
151
                }
152
                // Set up the appropriate helper links
153
                $stat['deleteLink'] = UrlHelper::actionUrl('webperf/data-samples/delete-samples-by-url', [
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...
154
                    'pageUrl' => $stat['url'],
155
                    'siteId' => $siteId
156
                ]);
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...
157
                $stat['detailPageUrl'] = UrlHelper::cpUrl('webperf/performance/page-detail', [
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...
158
                    'pageUrl' => $stat['url'],
159
                    'siteId' => $siteId,
160
                ]);
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...
161
                // Override based on permissions
162
                if (!$user->can('webperf:delete-data-samples')) {
163
                    $stat['deleteLink'] = '';
164
                }
165
                if (!$user->can('webperf:performance-detail')) {
166
                    $stat['detailPageUrl'] = '';
167
                }
168
            }
169
            // Format the data for the API
170
            $data['data'] = $stats;
171
            $query = (new Query())
172
                ->select(['[[url]]'])
173
                ->from(['{{%webperf_data_samples}}'])
174
                ->groupBy('[[url]]')
175
                ->where(['between', 'dateCreated', $start, $end])
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
176
                ;
177
            if ($filter !== '') {
178
                $query->andWhere(['like', 'url', $filter]);
179
                $query->orWhere(['like', 'title', $filter]);
180
            }
181
            $count = $query->count();
182
            $data['links']['pagination'] = [
183
                'total' => $count,
184
                'per_page' => $per_page,
185
                'current_page' => $page,
186
                'last_page' => ceil($count / $per_page),
187
                'next_page_url' => null,
188
                'prev_page_url' => null,
189
                'from' => $offset + 1,
190
                'to' => $offset + ($count > $per_page ? $per_page : $count),
191
            ];
192
        }
193
194
        return $this->asJson($data);
195
    }
196
197
    /**
198
     * Handle requests for the performance detail table
199
     *
200
     * @param string $sort
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $sort does not match actual variable name $start
Loading history...
201
     * @param int    $page
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $page does not match actual variable name $end
Loading history...
202
     * @param int    $per_page
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $per_page does not match actual variable name $sort
Loading history...
203
     * @param string $filter
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $filter does not match actual variable name $page
Loading history...
204
     * @param string $pageUrl
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $pageUrl does not match actual variable name $per_page
Loading history...
205
     * @param string $start
0 ignored issues
show
Coding Style introduced by
Doc comment for parameter $start does not match actual variable name $filter
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
206
     * @param string $end
0 ignored issues
show
Coding Style introduced by
Doc comment for parameter $end does not match actual variable name $pageUrl
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
207
     * @param int    $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
208
     *
209
     * @return Response
210
     * @throws ForbiddenHttpException
211
     */
212
    public function actionPageDetail(
213
        string $start = '',
214
        string $end = '',
215
        string $sort = 'pageLoad|DESC',
216
        int $page = 1,
217
        int $per_page = 20,
218
        $filter = '',
219
        $pageUrl = '',
220
        $siteId = 0
221
    ): Response {
222
        PermissionHelper::controllerPermissionCheck('webperf:performance');
223
        $data = [];
224
        $sortField = 'pageLoad';
225
        $sortType = 'DESC';
226
        // Add a day since YYYY-MM-DD is really YYYY-MM-DD 00:00:00
227
        $end = date('Y-m-d', strtotime($end.'+1 day'));
228
        $pageUrl = urldecode($pageUrl);
229
        // Figure out the sorting type
230
        if ($sort !== '') {
231
            if (strpos($sort, '|') === false) {
232
                $sortField = $sort;
233
            } else {
234
                list($sortField, $sortType) = explode('|', $sort);
235
            }
236
        }
237
        // Query the db table
238
        $offset = ($page - 1) * $per_page;
239
        $query = (new Query())
240
            ->from(['{{%webperf_data_samples}}'])
241
            ->offset($offset)
242
            ->where(['url' => $pageUrl])
243
            ->andWhere(['between', 'dateCreated', $start, $end])
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
244
        ;
245
        if ((int)$siteId !== 0) {
246
            $query->andWhere(['siteId' => $siteId]);
247
        }
248
        if ($filter !== '') {
249
            $query
250
                ->andWhere(['like', 'device', $filter])
251
                ->orWhere(['like', 'os', $filter])
252
                ->orWhere(['like', 'browser', $filter])
253
                ->orWhere(['like', 'countryCode', $filter])
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
254
            ;
255
        }
256
        $query
257
            ->orderBy("{$sortField} {$sortType}")
258
            ->limit($per_page)
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
259
        ;
260
        $stats = $query->all();
261
        if ($stats) {
262
            $user = Craft::$app->getUser()->getIdentity();
263
            // Compute the largest page load time
264
            $maxTotalPageLoad = 0;
265
            foreach ($stats as &$stat) {
266
                // Determine the stat type
267
                if (!empty($stat['pageLoad']) && !empty($stat['craftTotalMs'])) {
268
                    $stat['type'] = 'both';
269
                }
270
                if (empty($stat['firstByte'])) {
271
                    $stat['type'] = 'craft';
272
                }
273
                if (empty($stat['craftTotalMs'])) {
274
                    $stat['type'] = 'frontend';
275
                }
276
                if ($stat['pageLoad'] > $maxTotalPageLoad) {
277
                    $maxTotalPageLoad = (int)$stat['pageLoad'];
278
                }
279
            }
280
            // Massage the stats
281
            foreach ($stats as &$stat) {
282
                if (!empty($stats['dateCreated'])) {
283
                    $date = DateTimeHelper::toDateTime($stats['dateCreated']);
284
                    $stats['dateCreated'] = $date->format('Y-m-d H:i:s');
285
                }
286
                $stat['mobile'] = (bool)$stat['mobile'];
287
                $stat['maxTotalPageLoad'] = (int)$maxTotalPageLoad;
288
                // Decode any emojis in the title
289
                if (!empty($stat['title'])) {
290
                    $stat['title'] = html_entity_decode($stat['title'], ENT_NOQUOTES, 'UTF-8');
291
                }
292
                $stat['deleteLink'] = UrlHelper::actionUrl('webperf/data-samples/delete-sample-by-id', [
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...
293
                    'id' => $stat['id']
294
                ]);
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...
295
                // Override based on permissions
296
                if (!$user->can('webperf:delete-data-samples')) {
297
                    $stat['deleteLink'] = '';
298
                }
299
            }
300
            // Format the data for the API
301
            $data['data'] = $stats;
302
            $query = (new Query())
303
                ->select(['[[url]]'])
304
                ->from(['{{%webperf_data_samples}}'])
305
                ->where(['url' => $pageUrl])
306
                ->andWhere(['between', 'dateCreated', $start, $end])
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
307
            ;
308
            if ($filter !== '') {
309
                $query
310
                    ->andWhere(['like', 'device', $filter])
311
                    ->orWhere(['like', 'os', $filter])
312
                    ->orWhere(['like', 'browser', $filter])
313
                    ->orWhere(['like', 'countryCode', $filter])
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
314
                ;
315
            }
316
            $count = $query->count();
317
            $data['links']['pagination'] = [
318
                'total' => $count,
319
                'per_page' => $per_page,
320
                'current_page' => $page,
321
                'last_page' => ceil($count / $per_page),
322
                'next_page_url' => null,
323
                'prev_page_url' => null,
324
                'from' => $offset + 1,
325
                'to' => $offset + ($count > $per_page ? $per_page : $count),
326
            ];
327
        }
328
329
        return $this->asJson($data);
330
    }
331
332
    /**
333
     * Handle requests for the pages index table
334
     *
335
     * @param string $sort
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $sort does not match actual variable name $start
Loading history...
336
     * @param int    $page
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $page does not match actual variable name $end
Loading history...
337
     * @param int    $per_page
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $per_page does not match actual variable name $sort
Loading history...
338
     * @param string $filter
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $filter does not match actual variable name $page
Loading history...
339
     * @param string $start
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $start does not match actual variable name $per_page
Loading history...
340
     * @param string $end
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $end does not match actual variable name $filter
Loading history...
341
     * @param int    $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
342
     *
343
     * @return Response
344
     * @throws ForbiddenHttpException
345
     */
346
    public function actionErrorsIndex(
347
        string $start = '',
348
        string $end = '',
349
        string $sort = 'url|DESC',
350
        int $page = 1,
351
        int $per_page = 20,
352
        $filter = '',
353
        $siteId = 0
354
    ): Response {
355
        PermissionHelper::controllerPermissionCheck('webperf:errors');
356
        $data = [];
357
        $sortField = 'url';
358
        $sortType = 'DESC';
359
        // Add a day since YYYY-MM-DD is really YYYY-MM-DD 00:00:00
360
        $end = date('Y-m-d', strtotime($end.'+1 day'));
361
        // Figure out the sorting type
362
        if ($sort !== '') {
363
            if (strpos($sort, '|') === false) {
364
                $sortField = $sort;
365
            } else {
366
                list($sortField, $sortType) = explode('|', $sort);
367
            }
368
        }
369
        $db = Craft::$app->getDb();
370
        // Query the db table
371
        $offset = ($page - 1) * $per_page;
372
        $query = (new Query())
373
            ->select([
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...
374
                '[[url]]',
375
                'MIN([[title]]) as [[title]]',
376
                'MAX([[dateCreated]]) as [[latestErrorDate]]',
377
                'SUM([[type]] = \'craft\') as [[craftCount]]',
378
                'SUM([[type]] = \'boomerang\') as [[boomerangCount]]',
379
                'COUNT([[url]]) AS cnt',
380
            ])
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...
381
            ->from(['{{%webperf_error_samples}}'])
382
            ->offset($offset)
383
            ->where(['between', 'dateCreated', $start, $end])
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
384
        ;
385
        if ($db->getIsMysql()) {
386
            $query
387
                ->addSelect([
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...
388
                    'SUM([[type]] = \'craft\') as [[craftCount]]',
389
                    'SUM([[type]] = \'boomerang\') as [[boomerangCount]]',
390
                ]);
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...
391
        }
392
        if ($db->getIsPgsql()) {
393
            $query
394
                ->addSelect([
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...
395
                    'SUM(case when [[type]] = \'craft\' then 1 else 0 end) as [[craftCount]]',
396
                    'SUM(case when [[type]] = \'boomerang\' then 1 else 0 end) as [[boomerangCount]]',
397
                ]);
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...
398
        }
399
        if ((int)$siteId !== 0) {
400
            $query->andWhere(['siteId' => $siteId]);
401
        }
402
        if ($filter !== '') {
403
            $query
404
                ->andWhere(['like', 'url', $filter])
405
                ->orWhere(['like', 'title', $filter])
406
                ->orWhere(['like', 'pageErrors', $filter])
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
407
            ;
408
        }
409
        $query
410
            ->orderBy("[[{$sortField}]] {$sortType}")
411
            ->groupBy('url')
412
            ->limit($per_page)
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
413
        ;
414
415
        $stats = $query->all();
416
        if ($stats) {
417
            $user = Craft::$app->getUser()->getIdentity();
418
            // Massage the stats
419
            foreach ($stats as &$stat) {
420
                $stat['cnt'] = (int)$stat['cnt'];
421
                $stat['craftCount'] = (int)$stat['craftCount'];
422
                $stat['boomerangCount'] = (int)$stat['boomerangCount'];
423
                // Decode any emojis in the title
424
                if (!empty($stat['title'])) {
425
                    $stat['title'] = html_entity_decode($stat['title'], ENT_NOQUOTES, 'UTF-8');
426
                }
427
                // Set up the appropriate helper links
428
                $stat['deleteLink'] = UrlHelper::actionUrl('webperf/error-samples/delete-samples-by-url', [
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...
429
                    'pageUrl' => $stat['url'],
430
                    'siteId' => $siteId
431
                ]);
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...
432
                $stat['detailPageUrl'] = UrlHelper::cpUrl('webperf/errors/page-detail', [
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...
433
                    'pageUrl' => $stat['url'],
434
                    'siteId' => $siteId,
435
                ]);
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...
436
                // Override based on permissions
437
                if (!$user->can('webperf:delete-error-samples')) {
438
                    $stat['deleteLink'] = '';
439
                }
440
                if (!$user->can('webperf:errors-detail')) {
441
                    $stat['detailPageUrl'] = '';
442
                }
443
            }
444
            // Format the data for the API
445
            $data['data'] = $stats;
446
            $query = (new Query())
447
                ->select(['[[url]]'])
448
                ->from(['{{%webperf_error_samples}}'])
449
                ->groupBy('[[url]]')
450
                ->where(['between', 'dateCreated', $start, $end])
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
451
            ;
452
            if ($filter !== '') {
453
                $query
454
                    ->andWhere(['like', 'url', $filter])
455
                    ->orWhere(['like', 'title', $filter])
456
                    ->orWhere(['like', 'pageErrors', $filter])
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
457
                ;
458
            }
459
            $count = $query->count();
460
            $data['links']['pagination'] = [
461
                'total' => $count,
462
                'per_page' => $per_page,
463
                'current_page' => $page,
464
                'last_page' => ceil($count / $per_page),
465
                'next_page_url' => null,
466
                'prev_page_url' => null,
467
                'from' => $offset + 1,
468
                'to' => $offset + ($count > $per_page ? $per_page : $count),
469
            ];
470
        }
471
472
        return $this->asJson($data);
473
    }
474
475
476
    /**
477
     * Handle requests for the performance detail table
478
     *
479
     * @param string $sort
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $sort does not match actual variable name $start
Loading history...
480
     * @param int    $page
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $page does not match actual variable name $end
Loading history...
481
     * @param int    $per_page
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $per_page does not match actual variable name $sort
Loading history...
482
     * @param string $filter
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $filter does not match actual variable name $page
Loading history...
483
     * @param string $pageUrl
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $pageUrl does not match actual variable name $per_page
Loading history...
484
     * @param string $start
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $start does not match actual variable name $filter
Loading history...
485
     * @param string $end
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $end does not match actual variable name $pageUrl
Loading history...
486
     * @param int    $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
487
     *
488
     * @return Response
489
     * @throws ForbiddenHttpException
490
     */
491
    public function actionErrorsDetail(
492
        string $start = '',
493
        string $end = '',
494
        string $sort = 'dateCreated|DESC',
495
        int $page = 1,
496
        int $per_page = 20,
497
        $filter = '',
498
        $pageUrl = '',
499
        $siteId = 0
500
    ): Response {
501
        PermissionHelper::controllerPermissionCheck('webperf:errors');
502
        $data = [];
503
        $sortField = 'dateCreated';
504
        $sortType = 'DESC';
505
        // Add a day since YYYY-MM-DD is really YYYY-MM-DD 00:00:00
506
        $end = date('Y-m-d', strtotime($end.'+1 day'));
507
        $pageUrl = urldecode($pageUrl);
508
        // Figure out the sorting type
509
        if ($sort !== '') {
510
            if (strpos($sort, '|') === false) {
511
                $sortField = $sort;
512
            } else {
513
                list($sortField, $sortType) = explode('|', $sort);
514
            }
515
        }
516
        // Query the db table
517
        $offset = ($page - 1) * $per_page;
518
        $query = (new Query())
519
            ->from(['{{%webperf_error_samples}} webperf_error_samples'])
520
            ->select([
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...
521
                '[[webperf_error_samples.url]]',
522
                '[[webperf_error_samples.id]]',
523
                '[[webperf_error_samples.type]]',
524
                '[[webperf_error_samples.dateCreated]]',
525
                '[[webperf_error_samples.pageErrors]]',
526
                '[[webperf_error_samples.id]]',
527
528
                '[[webperf_data_samples.device]]',
529
                '[[webperf_data_samples.os]]',
530
                '[[webperf_data_samples.browser]]',
531
                '[[webperf_data_samples.countryCode]]',
532
                '[[webperf_data_samples.mobile]]',
533
            ])
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...
534
            ->offset($offset)
535
            ->where(['[[webperf_error_samples.url]]' => $pageUrl])
536
            ->andWhere(['between', '[[webperf_error_samples.dateCreated]]', $start, $end])
537
            ->leftJoin('{{%webperf_data_samples}} webperf_data_samples', '[[webperf_data_samples.requestId]] = [[webperf_error_samples.requestId]]')
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
538
        ;
539
        if ((int)$siteId !== 0) {
540
            $query->andWhere(['siteId' => $siteId]);
541
        }
542
        if ($filter !== '') {
543
            $query
544
                ->andWhere(['like', 'pageErrors', $filter])
545
                /*
546
                ->orWhere(['like', 'device', $filter])
547
                ->orWhere(['like', 'os', $filter])
548
                ->orWhere(['like', 'browser', $filter])
549
                ->orWhere(['like', 'countryCode', $filter])
550
                */
551
            ;
552
        }
553
        $query
554
            ->orderBy("{$sortField} {$sortType}")
555
            ->limit($per_page)
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
556
        ;
557
        $stats = $query->all();
558
        if ($stats) {
559
            $user = Craft::$app->getUser()->getIdentity();
560
            // Massage the stats
561
            foreach ($stats as &$stat) {
562
                if (!empty($stats['dateCreated'])) {
563
                    $date = DateTimeHelper::toDateTime($stats['dateCreated']);
564
                    $stats['dateCreated'] = $date->format('Y-m-d H:i:s');
565
                }
566
                if (isset($stat['mobile'])) {
567
                    $stat['mobile'] = (bool)$stat['mobile'];
568
                }
569
                // Decode any emojis in the title
570
                if (!empty($stat['title'])) {
571
                    $stat['title'] = html_entity_decode($stat['title'], ENT_NOQUOTES, 'UTF-8');
572
                }
573
                $stat['deleteLink'] = UrlHelper::actionUrl('webperf/error-samples/delete-sample-by-id', [
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...
574
                    'id' => $stat['id']
575
                ]);
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...
576
                // Override based on permissions
577
                if (!$user->can('webperf:delete-error-samples')) {
578
                    $stat['deleteLink'] = '';
579
                }
580
            }
581
            // Format the data for the API
582
            $data['data'] = $stats;
583
            $query = (new Query())
584
                ->select(['[[url]]'])
585
                ->from(['{{%webperf_error_samples}}'])
586
                ->where(['url' => $pageUrl])
587
                ->andWhere(['between', 'dateCreated', $start, $end])
0 ignored issues
show
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
588
            ;
589
            if ($filter !== '') {
590
                $query
591
                    ->andWhere(['like', 'pageErrors', $filter])
592
                    /*
593
                    ->orWhere(['like', 'device', $filter])
594
                    ->orWhere(['like', 'os', $filter])
595
                    ->orWhere(['like', 'browser', $filter])
596
                    ->orWhere(['like', 'countryCode', $filter])
597
                    */
598
                ;
599
            }
600
            $count = $query->count();
601
            $data['links']['pagination'] = [
602
                'total' => $count,
603
                'per_page' => $per_page,
604
                'current_page' => $page,
605
                'last_page' => ceil($count / $per_page),
606
                'next_page_url' => null,
607
                'prev_page_url' => null,
608
                'from' => $offset + 1,
609
                'to' => $offset + ($count > $per_page ? $per_page : $count),
610
            ];
611
        }
612
613
        Craft::error('crap: '.print_r($data, true), __METHOD__);
614
        return $this->asJson($data);
615
    }
616
617
    // Protected Methods
618
    // =========================================================================
619
}
620