Retour::installGlobalEventListeners()   F
last analyzed

Complexity

Conditions 24
Paths 1

Size

Total Lines 169
Code Lines 102

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 102
c 2
b 0
f 0
dl 0
loc 169
rs 3.3333
cc 24
nc 1
nop 0

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
 * Retour plugin for Craft CMS
4
 *
5
 * Retour allows you to intelligently redirect legacy URLs, so that you don't
6
 * lose SEO value when rebuilding & restructuring a website
7
 *
8
 * @link      https://nystudio107.com/
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @copyright tag
Loading history...
9
 * @copyright Copyright (c) 2018 nystudio107
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
10
 */
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...
11
12
namespace nystudio107\retour;
13
14
use Craft;
15
use craft\base\Element;
16
use craft\base\Model;
17
use craft\base\Plugin;
18
use craft\events\ElementEvent;
19
use craft\events\ExceptionEvent;
20
use craft\events\PluginEvent;
21
use craft\events\RegisterCacheOptionsEvent;
22
use craft\events\RegisterComponentTypesEvent;
23
use craft\events\RegisterGqlQueriesEvent;
24
use craft\events\RegisterGqlSchemaComponentsEvent;
25
use craft\events\RegisterGqlTypesEvent;
26
use craft\events\RegisterUrlRulesEvent;
27
use craft\events\RegisterUserPermissionsEvent;
28
use craft\helpers\ElementHelper;
29
use craft\helpers\UrlHelper;
30
use craft\services\Dashboard;
31
use craft\services\Elements;
32
use craft\services\Fields;
33
use craft\services\Gql;
34
use craft\services\Plugins;
35
use craft\services\UserPermissions;
36
use craft\utilities\ClearCaches;
37
use craft\web\ErrorHandler;
38
use craft\web\twig\variables\CraftVariable;
39
use craft\web\UrlManager;
40
use nystudio107\retour\fields\ShortLink as ShortLinkField;
41
use nystudio107\retour\gql\interfaces\RetourInterface;
42
use nystudio107\retour\gql\queries\RetourQuery;
43
use nystudio107\retour\models\Settings;
44
use nystudio107\retour\services\ServicesTrait;
45
use nystudio107\retour\variables\RetourVariable;
46
use nystudio107\retour\widgets\RetourWidget;
47
use Twig\Error\RuntimeError;
48
use yii\base\Event;
49
use yii\web\HttpException;
50
51
/** @noinspection MissingPropertyAnnotationsInspection */
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...
52
53
/**
54
 * Class Retour
55
 *
56
 * @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 for @author tag indented incorrectly; expected 2 spaces but found 4
Loading history...
57
 * @package   Retour
0 ignored issues
show
Coding Style introduced by
Tag value for @package tag indented incorrectly; expected 1 spaces but found 3
Loading history...
58
 * @since     3.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 for @since tag indented incorrectly; expected 3 spaces but found 5
Loading history...
59
 * @method Settings getSettings()
0 ignored issues
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
60
 */
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...
61
class Retour extends Plugin
62
{
63
    // Traits
64
    // =========================================================================
65
66
    use ServicesTrait;
67
68
    // Constants
69
    // =========================================================================
70
71
    public const DEVMODE_CACHE_DURATION = 30;
72
73
    // Static Properties
74
    // =========================================================================
75
76
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
77
     * @var Retour
78
     */
79
    public static ?Plugin $plugin = null;
80
81
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
82
     * @var ?Settings
83
     */
84
    public static ?Settings $settings = null;
85
86
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
87
     * @var int
88
     */
89
    public static int $cacheDuration = 0;
90
91
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
92
     * @var ?HttpException
93
     */
94
    public static ?HttpException $currentException = null;
95
96
    // Public Properties
97
    // =========================================================================
98
99
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
100
     * @var string
101
     */
102
    public string $schemaVersion = '3.0.12';
103
104
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
105
     * @var bool
106
     */
107
    public bool $hasCpSection = true;
108
109
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
110
     * @var bool
111
     */
112
    public bool $hasCpSettings = true;
113
114
    // Public Methods
115
    // =========================================================================
116
117
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
118
     * @inheritdoc
119
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
120
    public function init(): void
121
    {
122
        parent::init();
123
        self::$plugin = $this;
124
        // Initialize properties
125
        self::$settings = $this->getSettings();
126
        $this->name = self::$settings->pluginName;
127
        self::$cacheDuration = Craft::$app->getConfig()->getGeneral()->devMode
128
            ? $this::DEVMODE_CACHE_DURATION
129
            : 0;
130
        // Handle any console commands
131
        $request = Craft::$app->getRequest();
132
        if ($request->getIsConsoleRequest()) {
133
            $this->controllerNamespace = 'nystudio107\retour\console\controllers';
134
        }
135
        // Install our event listeners
136
        $this->installEventListeners();
137
        // Log that Retour has been loaded
138
        Craft::info(
139
            Craft::t(
140
                'retour',
141
                '{name} plugin loaded',
142
                ['name' => $this->name]
143
            ),
144
            __METHOD__
145
        );
146
    }
147
148
    /**
149
     * Clear all the caches!
150
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
151
    public function clearAllCaches(): void
152
    {
153
        // Clear all of Retour's caches
154
        self::$plugin->redirects->invalidateCaches();
0 ignored issues
show
Bug introduced by
The method invalidateCaches() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

154
        self::$plugin->redirects->/** @scrutinizer ignore-call */ 
155
                                  invalidateCaches();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
155
    }
156
157
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
158
     * @inheritdoc
159
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
160
    public function getSettingsResponse(): mixed
161
    {
162
        // Just redirect to the plugin settings page
163
        return Craft::$app->getResponse()->redirect(UrlHelper::cpUrl('retour/settings'));
164
    }
165
166
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
167
     * @inheritdoc
168
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
169
    public function getCpNavItem(): ?array
170
    {
171
        $subNavs = [];
172
        $navItem = parent::getCpNavItem();
173
        $currentUser = Craft::$app->getUser()->getIdentity();
174
        // Only show sub-navs the user has permission to view
175
        if ($currentUser->can('retour:dashboard')) {
0 ignored issues
show
Bug introduced by
The method can() does not exist on yii\web\IdentityInterface. It seems like you code against a sub-type of yii\web\IdentityInterface such as craft\elements\User. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

175
        if ($currentUser->/** @scrutinizer ignore-call */ can('retour:dashboard')) {
Loading history...
176
            $subNavs['dashboard'] = [
177
                'label' => 'Dashboard',
178
                'url' => 'retour/dashboard',
179
            ];
180
        }
181
        if ($currentUser->can('retour:redirects')) {
182
            $subNavs['redirects'] = [
183
                'label' => 'Redirects',
184
                'url' => 'retour/redirects',
185
            ];
186
        }
187
        if ($currentUser->can('retour:shortlinks')) {
188
            $subNavs['shortlinks'] = [
189
                'label' => 'Short Links',
190
                'url' => 'retour/shortlinks',
191
            ];
192
        }
193
        $editableSettings = true;
194
        $general = Craft::$app->getConfig()->getGeneral();
195
        if (!$general->allowAdminChanges) {
196
            $editableSettings = false;
197
        }
198
        if ($currentUser->can('retour:settings') && $editableSettings) {
199
            $subNavs['settings'] = [
200
                'label' => 'Settings',
201
                'url' => 'retour/settings',
202
            ];
203
        }
204
        // Retour doesn't really have an index page, so if the user can't access any sub nav items, we probably shouldn't show the main sub nav item either
205
        if (empty($subNavs)) {
206
            return null;
207
        }
208
        // A single sub nav item is redundant
209
        if (count($subNavs) === 1) {
210
            $subNavs = [];
211
        }
212
        $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...
213
            'subnav' => $subNavs,
214
        ]);
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...
215
216
        return $navItem;
217
    }
218
219
    // Protected Methods
220
    // =========================================================================
221
222
    /**
223
     * Install our event listeners.
224
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
225
    protected function installEventListeners(): void
226
    {
227
        // Install our event listeners only if our table schema exists
228
        if ($this->tableSchemaExists()) {
229
            $request = Craft::$app->getRequest();
230
            // Add in our event listeners that are needed for every request
231
            $this->installGlobalEventListeners();
232
            // Install only for non-console site requests
233
            if ($request->getIsSiteRequest() && !$request->getIsConsoleRequest()) {
234
                $this->installSiteEventListeners();
235
            }
236
            // Install only for non-console Control Panel requests
237
            if ($request->getIsCpRequest() && !$request->getIsConsoleRequest()) {
238
                $this->installCpEventListeners();
239
            }
240
        }
241
        // Handler: ClearCaches::EVENT_REGISTER_CACHE_OPTIONS
242
        Event::on(
243
            ClearCaches::class,
244
            ClearCaches::EVENT_REGISTER_CACHE_OPTIONS,
245
            function(RegisterCacheOptionsEvent $event) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
246
                Craft::debug(
247
                    'ClearCaches::EVENT_REGISTER_CACHE_OPTIONS',
248
                    __METHOD__
249
                );
250
                // Register our Control Panel routes
251
                $event->options = array_merge(
252
                    $event->options,
253
                    $this->customAdminCpCacheOptions()
254
                );
255
            }
256
        );
257
        // Handler: EVENT_AFTER_INSTALL_PLUGIN
258
        Event::on(
259
            Plugins::class,
260
            Plugins::EVENT_AFTER_INSTALL_PLUGIN,
261
            function(PluginEvent $event) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
262
                if ($event->plugin === $this) {
0 ignored issues
show
introduced by
The condition $event->plugin === $this is always false.
Loading history...
263
                    // Invalidate our caches after we've been installed
264
                    $this->clearAllCaches();
265
                    // Send them to our welcome screen
266
                    $request = Craft::$app->getRequest();
267
                    if ($request->isCpRequest) {
268
                        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...
269
                            'retour/dashboard',
270
                            [
271
                                'showWelcome' => true,
272
                            ]
273
                        ))->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...
274
                    }
275
                }
276
            }
277
        );
278
    }
279
280
    /**
281
     * Determine whether our table schema exists or not; this is needed because
282
     * migrations such as the install migration and base_install migration may
283
     * not have been run by the time our init() method has been called
284
     *
285
     * @return bool
286
     */
287
    protected function tableSchemaExists(): bool
288
    {
289
        return (Craft::$app->db->schema->getTableSchema('{{%retour_redirects}}') !== null);
290
    }
291
292
    /**
293
     * Install global event listeners for all request types
294
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
295
    protected function installGlobalEventListeners(): void
296
    {
297
        Event::on(
298
            CraftVariable::class,
299
            CraftVariable::EVENT_INIT,
300
            function(Event $event) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
301
                /** @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...
302
                $variable = $event->sender;
303
                $variable->set('retour', [
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...
304
                    'class' => RetourVariable::class,
305
                    'viteService' => $this->vite,
306
                ]);
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...
307
            }
308
        );
309
310
        $prepareRedirectOnElementChange = function(ElementEvent $event) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
311
            /** @var Element $element */
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...
312
            $element = $event->element;
313
            if (!$event->isNew && $element->getUrl() !== null && !$element->propagating) {
314
                $checkElementSlug = true;
315
                // Make sure the element is enabled
316
                if (!$element->enabled || !$element->getEnabledForSite()) {
317
                    $checkElementSlug = false;
318
                }
319
                // If we're running Craft 3.2 or later, also check that isn't not a draft or revision
320
                if (ElementHelper::isDraftOrRevision($element)) {
321
                    $checkElementSlug = false;
322
                }
323
                // Only do this for elements that aren't new, pass $checkElementSlug, and the user
324
                // has turned on the setting
325
                if (self::$settings->createUriChangeRedirects && $checkElementSlug) {
326
                    // Make sure this isn't a transitioning temporary draft/revision and that it's
327
                    // not propagating to other sites
328
                    if ($element->uri && !str_contains($element->uri, '__temp_')) {
329
                        Retour::$plugin->events->stashElementUris($element);
0 ignored issues
show
Bug introduced by
The method stashElementUris() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

329
                        Retour::$plugin->events->/** @scrutinizer ignore-call */ 
330
                                                 stashElementUris($element);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
330
                    }
331
                }
332
            }
333
        };
334
335
        $insertRedirectOnElementChange = function(ElementEvent $event) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
336
            /** @var Element $element */
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...
337
            $element = $event->element;
338
            if ($element !== null && !$event->isNew && $element->getUrl() !== null) {
339
                $checkElementSlug = true;
340
                // Make sure the element is enabled
341
                if (!$element->enabled || !$element->getEnabledForSite()) {
342
                    $checkElementSlug = false;
343
                }
344
                if (ElementHelper::isDraftOrRevision($element)) {
345
                    $checkElementSlug = false;
346
                }
347
                if (self::$settings->createUriChangeRedirects && $checkElementSlug) {
348
                    Retour::$plugin->events->handleElementUriChange($element);
349
                }
350
            }
351
        };
352
353
        // Handler: Elements::EVENT_BEFORE_SAVE_ELEMENT
354
        Event::on(
355
            Elements::class,
356
            Elements::EVENT_BEFORE_SAVE_ELEMENT,
357
            static function(ElementEvent $event) use ($prepareRedirectOnElementChange) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
358
                Craft::debug(
359
                    'Elements::EVENT_BEFORE_SAVE_ELEMENT',
360
                    __METHOD__
361
                );
362
                $prepareRedirectOnElementChange($event);
363
            }
364
        );
365
        // Handler: Elements::EVENT_AFTER_SAVE_ELEMENT
366
        Event::on(
367
            Elements::class,
368
            Elements::EVENT_AFTER_SAVE_ELEMENT,
369
            static function(ElementEvent $event) use ($insertRedirectOnElementChange) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
370
                Craft::debug(
371
                    'Elements::EVENT_AFTER_SAVE_ELEMENT',
372
                    __METHOD__
373
                );
374
                $insertRedirectOnElementChange($event);
375
            }
376
        );
377
        // Handler: Elements::EVENT_BEFORE_UPDATE_SLUG_AND_URI
378
        Event::on(
379
            Elements::class,
380
            Elements::EVENT_BEFORE_UPDATE_SLUG_AND_URI,
381
            static function(ElementEvent $event) use ($prepareRedirectOnElementChange) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
382
                Craft::debug(
383
                    'Elements::EVENT_BEFORE_UPDATE_SLUG_AND_URI',
384
                    __METHOD__
385
                );
386
                $prepareRedirectOnElementChange($event);
387
            }
388
        );
389
        // Handler: Elements::EVENT_AFTER_UPDATE_SLUG_AND_URI
390
        Event::on(
391
            Elements::class,
392
            Elements::EVENT_AFTER_UPDATE_SLUG_AND_URI,
393
            static function(ElementEvent $event) use ($insertRedirectOnElementChange) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
394
                Craft::debug(
395
                    'Elements::EVENT_AFTER_UPDATE_SLUG_AND_URI',
396
                    __METHOD__
397
                );
398
                $insertRedirectOnElementChange($event);
399
            }
400
        );
401
        // Handler: Plugins::EVENT_AFTER_LOAD_PLUGINS
402
        Event::on(
403
            Plugins::class,
404
            Plugins::EVENT_AFTER_LOAD_PLUGINS,
405
            function() {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
406
                // Install these only after all other plugins have loaded
407
                $request = Craft::$app->getRequest();
408
                // Only respond to non-console site requests
409
                if ($request->getIsSiteRequest() && !$request->getIsConsoleRequest()) {
410
                    $this->handleSiteRequest();
411
                }
412
                // Respond to Control Panel requests
413
                if ($request->getIsCpRequest() && !$request->getIsConsoleRequest()) {
414
                    $this->handleAdminCpRequest();
415
                }
416
            }
417
        );
418
        // Handler: Fields::EVENT_REGISTER_FIELD_TYPES
419
        Event::on(
420
            Fields::class,
421
            Fields::EVENT_REGISTER_FIELD_TYPES,
422
            function(RegisterComponentTypesEvent $event) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
423
                $event->types[] = ShortLinkField::class;
424
            }
425
        );
426
        // Handler: Gql::EVENT_REGISTER_GQL_TYPES
427
        Event::on(
428
            Gql::class,
429
            Gql::EVENT_REGISTER_GQL_TYPES,
430
            static function(RegisterGqlTypesEvent $event) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
431
                Craft::debug(
432
                    'Gql::EVENT_REGISTER_GQL_TYPES',
433
                    __METHOD__
434
                );
435
                $event->types[] = RetourInterface::class;
436
            }
437
        );
438
        // Handler: Gql::EVENT_REGISTER_GQL_QUERIES
439
        Event::on(
440
            Gql::class,
441
            Gql::EVENT_REGISTER_GQL_QUERIES,
442
            static function(RegisterGqlQueriesEvent $event) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
443
                Craft::debug(
444
                    'Gql::EVENT_REGISTER_GQL_QUERIES',
445
                    __METHOD__
446
                );
447
                $queries = RetourQuery::getQueries();
448
                foreach ($queries as $key => $value) {
449
                    $event->queries[$key] = $value;
450
                }
451
            }
452
        );
453
        // Handler: Gql::EVENT_REGISTER_SCHEMA_COMPONENTS
454
        Event::on(
455
            Gql::class,
456
            Gql::EVENT_REGISTER_GQL_SCHEMA_COMPONENTS,
457
            static function(RegisterGqlSchemaComponentsEvent $event) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
458
                Craft::debug(
459
                    'Gql::EVENT_REGISTER_GQL_SCHEMA_COMPONENTS',
460
                    __METHOD__
461
                );
462
                $label = Craft::t('retour', 'Retour');
463
                $event->queries[$label]['retour.all:read'] = ['label' => Craft::t('retour', 'Query Retour data')];
464
            }
465
        );
466
    }
467
468
    /**
469
     * Handle site requests.  We do it only after we receive the event
470
     * EVENT_AFTER_LOAD_PLUGINS so that any pending db migrations can be run
471
     * before our event listeners kick in
472
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
473
    protected function handleSiteRequest(): void
474
    {
475
        // Handler: ErrorHandler::EVENT_BEFORE_HANDLE_EXCEPTION
476
        Event::on(
477
            ErrorHandler::class,
478
            ErrorHandler::EVENT_BEFORE_HANDLE_EXCEPTION,
479
            static function(ExceptionEvent $event) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
480
                Craft::debug(
481
                    'ErrorHandler::EVENT_BEFORE_HANDLE_EXCEPTION',
482
                    __METHOD__
483
                );
484
                $exception = $event->exception;
485
                // If this is a Twig Runtime exception, use the previous one instead
486
                if ($exception instanceof RuntimeError &&
487
                    ($previousException = $exception->getPrevious()) !== null) {
0 ignored issues
show
Coding Style introduced by
Each line in a multi-line IF statement must begin with a boolean operator
Loading history...
Coding Style introduced by
Closing parenthesis of a multi-line IF statement must be on a new line
Loading history...
488
                    $exception = $previousException;
489
                }
490
                // If this is a 404 error, see if we can handle it
491
                if ($exception instanceof HttpException && $exception->statusCode === 404) {
492
                    self::$currentException = $exception;
493
                    Retour::$plugin->redirects->handle404();
0 ignored issues
show
Bug introduced by
The method handle404() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

493
                    Retour::$plugin->redirects->/** @scrutinizer ignore-call */ 
494
                                                handle404();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
494
                }
495
            }
496
        );
497
    }
498
499
    /**
500
     * Handle Control Panel requests. We do it only after we receive the event
501
     * EVENT_AFTER_LOAD_PLUGINS so that any pending db migrations can be run
502
     * before our event listeners kick in
503
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
504
    protected function handleAdminCpRequest(): void
505
    {
506
    }
507
508
    /**
509
     * Install site event listeners for site requests only
510
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
511
    protected function installSiteEventListeners(): void
512
    {
513
        // Handler: UrlManager::EVENT_REGISTER_SITE_URL_RULES
514
        Event::on(
515
            UrlManager::class,
516
            UrlManager::EVENT_REGISTER_SITE_URL_RULES,
517
            function(RegisterUrlRulesEvent $event) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
518
                Craft::debug(
519
                    'UrlManager::EVENT_REGISTER_SITE_URL_RULES',
520
                    __METHOD__
521
                );
522
                // Register our Control Panel routes
523
                $event->rules = array_merge(
524
                    $event->rules,
525
                    $this->customFrontendRoutes()
526
                );
527
            }
528
        );
529
    }
530
531
    /**
532
     * Return the custom frontend routes
533
     *
534
     * @return array
535
     */
536
    protected function customFrontendRoutes(): array
537
    {
538
        return [
539
        ];
540
    }
541
542
    /**
543
     * Install site event listeners for Control Panel requests only
544
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
545
    protected function installCpEventListeners(): void
546
    {
547
        // Handler: Dashboard::EVENT_REGISTER_WIDGET_TYPES
548
        Event::on(
549
            Dashboard::class,
550
            Dashboard::EVENT_REGISTER_WIDGET_TYPES,
551
            function(RegisterComponentTypesEvent $event) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
552
                $currentUser = Craft::$app->getUser()->getIdentity();
553
                if ($currentUser->can('accessPlugin-retour')) {
554
                    $event->types[] = RetourWidget::class;
555
                }
556
            }
557
        );
558
        // Handler: UrlManager::EVENT_REGISTER_CP_URL_RULES
559
        Event::on(
560
            UrlManager::class,
561
            UrlManager::EVENT_REGISTER_CP_URL_RULES,
562
            function(RegisterUrlRulesEvent $event) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
563
                Craft::debug(
564
                    'UrlManager::EVENT_REGISTER_CP_URL_RULES',
565
                    __METHOD__
566
                );
567
                // Register our Control Panel routes
568
                $event->rules = array_merge(
569
                    $event->rules,
570
                    $this->customAdminCpRoutes()
571
                );
572
            }
573
        );
574
        // Handler: UserPermissions::EVENT_REGISTER_PERMISSIONS
575
        Event::on(
576
            UserPermissions::class,
577
            UserPermissions::EVENT_REGISTER_PERMISSIONS,
578
            function(RegisterUserPermissionsEvent $event) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
579
                Craft::debug(
580
                    'UserPermissions::EVENT_REGISTER_PERMISSIONS',
581
                    __METHOD__
582
                );
583
                // Register our custom permissions
584
                $event->permissions[] = [
585
                    'heading' => Craft::t('retour', 'Retour'),
586
                    'permissions' => $this->customAdminCpPermissions(),
587
                ];
588
            }
589
        );
590
    }
591
592
    /**
593
     * Return the custom Control Panel routes
594
     *
595
     * @return array
596
     */
597
    protected function customAdminCpRoutes(): array
598
    {
599
        return [
600
            'retour' => '',
601
602
            'retour/redirects' => 'retour/redirects/redirects',
603
            'retour/redirects/<siteHandle:{handle}>' => 'retour/redirects/redirects',
604
605
            'retour/edit-redirect/<redirectId:\d+>' => 'retour/redirects/edit-redirect',
606
607
            'retour/add-redirect' => 'retour/redirects/edit-redirect',
608
            'retour/add-redirect/<siteId:\d+>' => 'retour/redirects/edit-redirect',
609
610
            'retour/dashboard' => 'retour/statistics/dashboard',
611
            'retour/dashboard/<siteHandle:{handle}>' => 'retour/statistics/dashboard',
612
613
            'retour/shortlinks' => 'retour/redirects/shortlinks',
614
            'retour/shortlinks/<siteHandle:{handle}>' => 'retour/redirects/shortlinks',
615
616
            'retour/settings' => 'retour/settings/plugin-settings',
617
        ];
618
    }
619
620
    /**
621
     * Returns the custom Control Panel user permissions.
622
     *
623
     * @return array
624
     */
625
    protected function customAdminCpPermissions(): array
626
    {
627
        return [
628
            'retour:dashboard' => [
629
                'label' => Craft::t('retour', 'Dashboard'),
630
            ],
631
            'retour:redirects' => [
632
                'label' => Craft::t('retour', 'Redirects'),
633
            ],
634
            'retour:shortlinks' => [
635
                'label' => Craft::t('retour', 'Short Links'),
636
            ],
637
            'retour:settings' => [
638
                'label' => Craft::t('retour', 'Settings'),
639
            ],
640
        ];
641
    }
642
643
    /**
644
     * Returns the custom Control Panel cache options.
645
     *
646
     * @return array
647
     */
648
    protected function customAdminCpCacheOptions(): array
649
    {
650
        return [
651
            [
652
                'key' => 'retour-redirect-caches',
653
                'label' => Craft::t('retour', 'Retour redirect caches'),
654
                'action' => [self::$plugin->redirects, 'invalidateCaches'],
655
            ],
656
        ];
657
    }
658
659
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
660
     * @inheritdoc
661
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
662
    protected function createSettingsModel(): ?Model
663
    {
664
        return new Settings();
665
    }
666
}
667