Passed
Push — v3 ( 4358aa...b8a538 )
by Andrew
05:33
created

Seomatic::installEventListeners()   B

Complexity

Conditions 5
Paths 1

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 10
nc 1
nop 0
dl 0
loc 17
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * SEOmatic plugin for Craft CMS 3.x
4
 *
5
 * A turnkey SEO implementation for Craft CMS that is comprehensive, powerful,
6
 * and flexible
7
 *
8
 * @link      https://nystudio107.com
9
 * @copyright Copyright (c) 2017 nystudio107
10
 */
11
12
namespace nystudio107\seomatic;
13
14
use craft\elements\User;
15
use nystudio107\seomatic\assetbundles\seomatic\SeomaticAsset;
16
use nystudio107\seomatic\helpers\MetaValue as MetaValueHelper;
17
use nystudio107\seomatic\helpers\PluginTemplate;
18
use nystudio107\seomatic\models\MetaScriptContainer;
19
use nystudio107\seomatic\models\Settings;
20
use nystudio107\seomatic\services\FrontendTemplates as FrontendTemplatesService;
21
use nystudio107\seomatic\services\Helper as HelperService;
22
use nystudio107\seomatic\services\JsonLd as JsonLdService;
23
use nystudio107\seomatic\services\Link as LinkService;
24
use nystudio107\seomatic\services\MetaBundles as MetaBundlesService;
25
use nystudio107\seomatic\services\MetaContainers as MetaContainersService;
26
use nystudio107\seomatic\services\Redirects as RedirectsService;
27
use nystudio107\seomatic\services\Script as ScriptService;
28
use nystudio107\seomatic\services\Sitemaps as SitemapsService;
29
use nystudio107\seomatic\services\Tag as TagService;
30
use nystudio107\seomatic\services\Title as TitleService;
31
use nystudio107\seomatic\twigextensions\SeomaticTwigExtension;
32
use nystudio107\seomatic\variables\SeomaticVariable;
33
34
use Craft;
35
use craft\base\Element;
36
use craft\base\ElementInterface;
37
use craft\base\Plugin;
38
use craft\elements\Entry;
39
use craft\elements\Category;
40
use craft\errors\SiteNotFoundException;
41
use craft\events\CategoryGroupEvent;
42
use craft\events\ElementEvent;
43
use craft\events\ExceptionEvent;
44
use craft\events\PluginEvent;
45
use craft\events\RegisterCacheOptionsEvent;
46
use craft\events\RegisterUrlRulesEvent;
47
use craft\events\RegisterUserPermissionsEvent;
48
use craft\events\SectionEvent;
49
use craft\services\Categories;
50
use craft\services\Elements;
51
use craft\services\Plugins;
52
use craft\services\Sections;
53
use craft\services\UserPermissions;
54
use craft\helpers\UrlHelper;
55
use craft\utilities\ClearCaches;
56
use craft\web\ErrorHandler;
57
use yii\web\HttpException;
58
use craft\web\UrlManager;
59
use craft\web\View;
60
61
use yii\base\Event;
62
63
/**
64
 * Class Seomatic
65
 *
66
 * @author    nystudio107
67
 * @package   Seomatic
68
 * @since     3.0.0
69
 *
70
 * @property  FrontendTemplatesService frontendTemplates
71
 * @property  HelperService            helper
72
 * @property  JsonLdService            jsonLd
73
 * @property  LinkService              link
74
 * @property  MetaBundlesService       metaBundles
75
 * @property  MetaContainersService    metaContainers
76
 * @property  RedirectsService         redirects
77
 * @property  ScriptService            script
78
 * @property  SitemapsService          sitemaps
79
 * @property  TagService               tag
80
 * @property  TitleService             title
81
 */
82
class Seomatic extends Plugin
83
{
84
    // Constants
85
    // =========================================================================
86
87
    const SEOMATIC_HANDLE = 'Seomatic';
88
89
    // Static Properties
90
    // =========================================================================
91
92
    /**
93
     * @var Seomatic
94
     */
95
    public static $plugin;
96
97
    /**
98
     * @var SeomaticVariable
99
     */
100
    public static $seomaticVariable;
101
102
    /**
103
     * @var Settings
104
     */
105
    public static $settings;
106
107
    /**
108
     * @var ElementInterface
109
     */
110
    public static $matchedElement;
111
112
    /**
113
     * @var bool
114
     */
115
    public static $devMode;
116
117
    /**
118
     * @var View
119
     */
120
    public static $view;
121
122
    /**
123
     * @var
124
     */
125
    public static $language;
126
127
    /**
128
     * @var bool
129
     */
130
    public static $previewingMetaContainers = false;
131
132
    // Static Methods
133
    // =========================================================================
134
135
    /**
136
     * Set the matched element
137
     *
138
     * @param $element null|ElementInterface
139
     */
140
    public static function setMatchedElement($element)
141
    {
142
        self::$matchedElement = $element;
143
        /** @var  $element Element */
144
        if ($element) {
145
            self::$language = MetaValueHelper::getSiteLanguage($element->siteId);
0 ignored issues
show
Bug introduced by
It seems like $element->siteId can also be of type null; however, parameter $siteId of nystudio107\seomatic\hel...alue::getSiteLanguage() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

145
            self::$language = MetaValueHelper::getSiteLanguage(/** @scrutinizer ignore-type */ $element->siteId);
Loading history...
146
        } else {
147
            self::$language = MetaValueHelper::getSiteLanguage(null);
148
        }
149
        MetaValueHelper::cache();
150
    }
151
152
    // Public Properties
153
    // =========================================================================
154
155
    /**
156
     * @var string
157
     */
158
    public $schemaVersion = '3.0.3';
159
160
    // Public Methods
161
    // =========================================================================
162
163
    /**
164
     * @inheritdoc
165
     */
166
    public function init()
167
    {
168
        parent::init();
169
        self::$plugin = $this;
170
        // Initialize properties
171
        self::$settings = Seomatic::$plugin->getSettings();
172
        self::$devMode = Craft::$app->getConfig()->getGeneral()->devMode;
173
        self::$view = Craft::$app->getView();
174
        MetaValueHelper::cache();
175
        // If devMode is on, always force the environment to be "local"
176
        if (self::$devMode) {
177
            self::$settings->environment = "local";
178
        }
179
        $this->name = Seomatic::$settings->pluginName;
180
        // Install our event listeners
181
        $this->installEventListeners();
182
        // We're loaded
183
        Craft::info(
184
            Craft::t(
185
                'seomatic',
186
                '{name} plugin loaded',
187
                ['name' => $this->name]
188
            ),
189
            __METHOD__
190
        );
191
    }
192
193
    /**
194
     * @inheritdoc
195
     */
196
    public function getSettingsResponse()
197
    {
198
        return Craft::$app->runAction('seomatic/settings/plugin');
199
    }
200
201
    /**
202
     * @inheritdoc
203
     */
204
    public function getCpNavItem()
205
    {
206
        $subNavs = [];
207
        $navItem = parent::getCpNavItem();
208
        /** @var User $currentUser */
209
        $currentUser = Craft::$app->getUser()->getIdentity();
210
        // Only show sub-navs the user has permission to view
211
        if ($currentUser->can('seomatic:dashboard')) {
212
            $subNavs['dashboard'] = [
213
                'label' => 'Dashboard',
214
                'url'   => 'seomatic/dashboard',
215
            ];
216
        }
217
        if ($currentUser->can('seomatic:global-meta')) {
218
            $subNavs['global'] = [
219
                'label' => 'Global SEO',
220
                'url'   => 'seomatic/global',
221
            ];
222
        }
223
        if ($currentUser->can('seomatic:content-meta')) {
224
            $subNavs['content'] = [
225
                'label' => 'Content SEO',
226
                'url'   => 'seomatic/content',
227
            ];
228
        }
229
        if ($currentUser->can('seomatic:site-settings')) {
230
            $subNavs['site'] = [
231
                'label' => 'Site Settings',
232
                'url'   => 'seomatic/site',
233
            ];
234
        }
235
        if ($currentUser->can('seomatic:tracking-scripts')) {
236
            $subNavs['tracking'] = [
237
                'label' => 'Tracking Scripts',
238
                'url'   => 'seomatic/tracking',
239
            ];
240
        }
241
        if ($currentUser->can('seomatic:plugin-settings')) {
242
            $subNavs['plugin'] = [
243
                'label' => 'Plugin Settings',
244
                'url'   => 'seomatic/plugin',
245
            ];
246
        }
247
        $navItem = array_merge($navItem, [
248
            'subnav' => $subNavs,
249
        ]);
250
251
        return $navItem;
252
    }
253
254
    /**
255
     * Clear all the caches!
256
     */
257
    public function clearAllCaches()
258
    {
259
        Seomatic::$plugin->frontendTemplates->invalidateCaches();
260
        Seomatic::$plugin->metaContainers->invalidateCaches();
261
        Seomatic::$plugin->sitemaps->invalidateCaches();
262
    }
263
264
    // Protected Methods
265
    // =========================================================================
266
267
    /**
268
     * Install our event listeners. We do it only after we receive the event
269
     * EVENT_AFTER_LOAD_PLUGINS so that any pending db migrations can be run
270
     * before our event listeners kick in
271
     */
272
    protected function installEventListeners()
273
    {
274
        // Handler: EVENT_AFTER_LOAD_PLUGINS
275
        Event::on(
276
            Plugins::class,
277
            Plugins::EVENT_AFTER_LOAD_PLUGINS,
278
            function () {
279
                // Add in our event listeners that are needed for every request
280
                $this->installGlobalEventListeners();
281
                // Only respond to non-console site requests
282
                $request = Craft::$app->getRequest();
283
                if ($request->getIsSiteRequest() && !$request->getIsConsoleRequest()) {
284
                    $this->handleSiteRequest();
285
                }
286
                // AdminCP magic
287
                if ($request->getIsCpRequest() && !$request->getIsConsoleRequest()) {
288
                    $this->handleAdminCpRequest();
289
                }
290
            }
291
        );
292
    }
293
294
    /**
295
     * Install global event listeners
296
     */
297
    protected function installGlobalEventListeners()
298
    {
299
        // Handler: EVENT_AFTER_INSTALL_PLUGIN
300
        Event::on(
301
            Plugins::class,
302
            Plugins::EVENT_AFTER_INSTALL_PLUGIN,
303
            function (PluginEvent $event) {
304
                if ($event->plugin === $this) {
305
                    // Invalidate our caches after we've been installed
306
                    $this->clearAllCaches();
307
                    // Send them to our welcome screen
308
                    $request = Craft::$app->getRequest();
309
                    if ($request->isCpRequest) {
310
                        Craft::$app->getResponse()->redirect(UrlHelper::cpUrl(
311
                            'seomatic/dashboard',
312
                            [
313
                                'showWelcome' => true
314
                            ]
315
                        ))->send();
316
                    }
317
                }
318
            }
319
        );
320
        // Handler: Sections::EVENT_AFTER_SAVE_SECTION
321
        Event::on(
322
            Sections::class,
323
            Sections::EVENT_AFTER_SAVE_SECTION,
324
            function (SectionEvent $event) {
325
                Craft::debug(
326
                    'Sections::EVENT_AFTER_SAVE_SECTION',
327
                    __METHOD__
328
                );
329
                if (!empty($event->section) && $event->section->id !== null) {
330
                    Seomatic::$plugin->metaBundles->invalidateMetaBundleById(
331
                        MetaBundlesService::SECTION_META_BUNDLE,
332
                        $event->section->id,
333
                        $event->isNew
334
                    );
335
                    // Create the meta bundles for this section if it's new
336
                    if ($event->isNew) {
337
                        Seomatic::$plugin->metaBundles->createContentMetaBundleForSection($event->section);
338
                        Seomatic::$plugin->sitemaps->submitSitemapIndex();
339
                    }
340
                }
341
            }
342
        );
343
        // Handler: Sections::EVENT_AFTER_DELETE_SECTION
344
        Event::on(
345
            Sections::class,
346
            Sections::EVENT_AFTER_DELETE_SECTION,
347
            function (SectionEvent $event) {
348
                Craft::debug(
349
                    'Sections::EVENT_AFTER_DELETE_SECTION',
350
                    __METHOD__
351
                );
352
                if (!empty($event->section) && $event->section->id !== null) {
353
                    Seomatic::$plugin->metaBundles->invalidateMetaBundleById(
354
                        MetaBundlesService::SECTION_META_BUNDLE,
355
                        $event->section->id,
356
                        false
357
                    );
358
                    // Delete the meta bundles for this section
359
                    Seomatic::$plugin->metaBundles->deleteMetaBundleBySourceId(
360
                        MetaBundlesService::SECTION_META_BUNDLE,
361
                        $event->section->id
362
                    );
363
                }
364
            }
365
        );
366
        // Handler: Categories::EVENT_AFTER_SAVE_GROUP
367
        Event::on(
368
            Categories::class,
369
            Categories::EVENT_AFTER_SAVE_GROUP,
370
            function (CategoryGroupEvent $event) {
371
                Craft::debug(
372
                    'Categories::EVENT_AFTER_SAVE_GROUP',
373
                    __METHOD__
374
                );
375
                if (!empty($event->categoryGroup) && $event->categoryGroup->id !== null) {
376
                    Seomatic::$plugin->metaBundles->invalidateMetaBundleById(
377
                        MetaBundlesService::CATEGORYGROUP_META_BUNDLE,
378
                        $event->categoryGroup->id,
379
                        $event->isNew
380
                    );
381
                    // Create the meta bundles for this category if it's new
382
                    if ($event->isNew) {
383
                        Seomatic::$plugin->metaBundles->createContentMetaBundleForCategoryGroup($event->categoryGroup);
384
                        Seomatic::$plugin->sitemaps->submitSitemapIndex();
385
                    }
386
                }
387
            }
388
        );
389
        // Handler: Categories::EVENT_AFTER_DELETE_GROUP
390
        Event::on(
391
            Categories::class,
392
            Categories::EVENT_AFTER_DELETE_GROUP,
393
            function (CategoryGroupEvent $event) {
394
                Craft::debug(
395
                    'Categories::EVENT_AFTER_DELETE_GROUP',
396
                    __METHOD__
397
                );
398
                if (!empty($event->categoryGroup) && $event->categoryGroup->id !== null) {
399
                    Seomatic::$plugin->metaBundles->invalidateMetaBundleById(
400
                        MetaBundlesService::CATEGORYGROUP_META_BUNDLE,
401
                        $event->categoryGroup->id,
402
                        false
403
                    );
404
                    // Delete the meta bundles for this category
405
                    Seomatic::$plugin->metaBundles->deleteMetaBundleBySourceId(
406
                        MetaBundlesService::CATEGORYGROUP_META_BUNDLE,
407
                        $event->categoryGroup->id
408
                    );
409
                }
410
            }
411
        );
412
        // Handler: Elements::EVENT_AFTER_SAVE_ELEMENT
413
        Event::on(
414
            Elements::class,
415
            Elements::EVENT_AFTER_SAVE_ELEMENT,
416
            function (ElementEvent $event) {
417
                Craft::debug(
418
                    'Elements::EVENT_AFTER_SAVE_ELEMENT',
419
                    __METHOD__
420
                );
421
                /** @var  $element Element */
422
                $element = $event->element;
423
                Seomatic::$plugin->metaBundles->invalidateMetaBundleByElement(
424
                    $element,
425
                    $event->isNew
426
                );
427
                if ($event->isNew) {
428
                    Seomatic::$plugin->sitemaps->submitSitemapForElement($element);
429
                }
430
            }
431
        );
432
        // Handler: Elements::EVENT_AFTER_DELETE_ELEMENT
433
        Event::on(
434
            Elements::class,
435
            Elements::EVENT_AFTER_DELETE_ELEMENT,
436
            function (ElementEvent $event) {
437
                Craft::debug(
438
                    'Elements::EVENT_AFTER_DELETE_ELEMENT',
439
                    __METHOD__
440
                );
441
                /** @var  $element Element */
442
                $element = $event->element;
443
                Seomatic::$plugin->metaBundles->invalidateMetaBundleByElement(
444
                    $element,
445
                    false
446
                );
447
            }
448
        );
449
    }
450
451
    /**
452
     * Handle site requests
453
     */
454
    protected function handleSiteRequest()
455
    {
456
        // Add in our Twig extensions
457
        Seomatic::$view->registerTwigExtension(new SeomaticTwigExtension);
458
        // Load the sitemap containers
459
        Seomatic::$plugin->sitemaps->loadSitemapContainers();
460
        // Load the frontend template containers
461
        Seomatic::$plugin->frontendTemplates->loadFrontendTemplateContainers();
462
        // Handler: ErrorHandler::EVENT_BEFORE_HANDLE_EXCEPTION
463
        Event::on(
464
            ErrorHandler::class,
465
            ErrorHandler::EVENT_BEFORE_HANDLE_EXCEPTION,
466
            function (ExceptionEvent $event) {
467
                Craft::debug(
468
                    'ErrorHandler::EVENT_BEFORE_HANDLE_EXCEPTION',
469
                    __METHOD__
470
                );
471
                $exception = $event->exception;
472
                // If this is a Twig Runtime exception, use the previous one instead
473
                if ($exception instanceof \Twig_Error_Runtime &&
474
                    ($previousException = $exception->getPrevious()) !== null) {
475
                    $exception = $previousException;
476
                }
477
                // If this is a 404 error, see if we can handle it
478
                if ($exception instanceof HttpException && $exception->statusCode === 404) {
479
                    Seomatic::$plugin->redirects->handle404();
480
                }
481
            }
482
        );
483
        // Handler: View::EVENT_BEGIN_BODY
484
        Event::on(
485
            View::class,
486
            View::EVENT_BEGIN_BODY,
487
            function () {
488
                Craft::debug(
489
                    'View::EVENT_BEGIN_BODY',
490
                    __METHOD__
491
                );
492
                // The <body> placeholder tag has just rendered, include any script HTML
493
                if (Seomatic::$settings->renderEnabled && Seomatic::$seomaticVariable) {
494
                    Seomatic::$plugin->metaContainers->includeScriptBodyHtml(View::POS_BEGIN);
495
                }
496
            }
497
        );
498
        // Handler: View::EVENT_END_BODY
499
        Event::on(
500
            View::class,
501
            View::EVENT_END_BODY,
502
            function () {
503
                Craft::debug(
504
                    'View::EVENT_END_BODY',
505
                    __METHOD__
506
                );
507
                // The </body> placeholder tag is about to be rendered, include any script HTML
508
                if (Seomatic::$settings->renderEnabled && Seomatic::$seomaticVariable) {
509
                    Seomatic::$plugin->metaContainers->includeScriptBodyHtml(View::POS_END);
510
                }
511
            }
512
        );
513
        // Handler: View::EVENT_END_PAGE
514
        Event::on(
515
            View::class,
516
            View::EVENT_END_PAGE,
517
            function () {
518
                Craft::debug(
519
                    'View::EVENT_END_PAGE',
520
                    __METHOD__
521
                );
522
                // The page is done rendering, include our meta containers
523
                if (Seomatic::$settings->renderEnabled && Seomatic::$seomaticVariable) {
524
                    Seomatic::$plugin->metaContainers->includeMetaContainers();
525
                }
526
            }
527
        );
528
    }
529
530
    /**
531
     * Handle AdminCP requests
532
     */
533
    protected function handleAdminCpRequest()
534
    {
535
        // Add in our Twig extensions
536
        Seomatic::$view->registerTwigExtension(new SeomaticTwigExtension);
537
        // Handler: UrlManager::EVENT_REGISTER_CP_URL_RULES
538
        Event::on(
539
            UrlManager::class,
540
            UrlManager::EVENT_REGISTER_CP_URL_RULES,
541
            function (RegisterUrlRulesEvent $event) {
542
                Craft::debug(
543
                    'UrlManager::EVENT_REGISTER_CP_URL_RULES',
544
                    __METHOD__
545
                );
546
                // Register our AdminCP routes
547
                $event->rules = array_merge(
548
                    $event->rules,
549
                    $this->customAdminCpRoutes()
550
                );
551
            }
552
        );
553
        // Handler: UserPermissions::EVENT_REGISTER_PERMISSIONS
554
        Event::on(
555
            UserPermissions::class,
556
            UserPermissions::EVENT_REGISTER_PERMISSIONS,
557
            function (RegisterUserPermissionsEvent $event) {
558
                Craft::debug(
559
                    'UserPermissions::EVENT_REGISTER_PERMISSIONS',
560
                    __METHOD__
561
                );
562
                // Register our custom permissions
563
                $event->permissions[Craft::t('seomatic', 'SEOmatic')] = $this->customAdminCpPermissions();
564
            }
565
        );
566
        // Handler: ClearCaches::EVENT_REGISTER_CACHE_OPTIONS
567
        Event::on(
568
            ClearCaches::class,
569
            ClearCaches::EVENT_REGISTER_CACHE_OPTIONS,
570
            function (RegisterCacheOptionsEvent $event) {
571
                Craft::debug(
572
                    'ClearCaches::EVENT_REGISTER_CACHE_OPTIONS',
573
                    __METHOD__
574
                );
575
                // Register our AdminCP routes
576
                $event->options = array_merge(
577
                    $event->options,
578
                    $this->customAdminCpCacheOptions()
579
                );
580
            }
581
        );
582
        // Entries sidebar
583
        self::$view->hook('cp.entries.edit.details', function (&$context) {
584
            $html = '';
585
            self::$view->registerAssetBundle(SeomaticAsset::class);
586
            /** @var  $entry Entry */
587
            $entry = $context['entry'];
588
            if (!empty($entry) && !empty($entry->uri)) {
589
                Seomatic::$plugin->metaContainers->previewMetaContainers($entry->uri, $entry->siteId, true);
590
                // Render our preview sidebar template
591
                if (self::$settings->displayPreviewSidebar && self::$matchedElement) {
592
                    $html .= PluginTemplate::renderPluginTemplate('_sidebars/entry-preview.twig');
593
                }
594
                // Render our analysis sidebar template
595
                if (self::$settings->displayAnalysisSidebar && self::$matchedElement) {
596
                    $html .= PluginTemplate::renderPluginTemplate('_sidebars/entry-analysis.twig');
597
                }
598
            }
599
600
            return $html;
601
        });
602
        // Category Groups sidebar
603
        self::$view->hook('cp.categories.edit.details', function (&$context) {
604
            $html = '';
605
            self::$view->registerAssetBundle(SeomaticAsset::class);
606
            /** @var  $category Category */
607
            $category = $context['category'];
608
            if (!empty($category) && !empty($category->uri)) {
609
                Seomatic::$plugin->metaContainers->previewMetaContainers($category->uri, $category->siteId, true);
610
                // Render our preview sidebar template
611
                if (self::$settings->displayPreviewSidebar) {
612
                    $html .= PluginTemplate::renderPluginTemplate('_sidebars/category-preview.twig');
613
                }
614
                // Render our analysis sidebar template
615
                if (self::$settings->displayAnalysisSidebar) {
616
                    $html .= PluginTemplate::renderPluginTemplate('_sidebars/category-analysis.twig');
617
                }
618
            }
619
620
            return $html;
621
        });
622
    }
623
624
    /**
625
     * @inheritdoc
626
     */
627
    protected function createSettingsModel()
628
    {
629
        return new Settings();
630
    }
631
632
    /**
633
     * Return the custom AdminCP routes
634
     *
635
     * @return array
636
     */
637
    protected function customAdminCpRoutes(): array
638
    {
639
        return [
640
            'seomatic' =>
641
                'seomatic/settings/dashboard',
642
            'seomatic/dashboard' =>
643
                'seomatic/settings/dashboard',
644
            'seomatic/dashboard/<siteHandle:{handle}>' =>
645
                'seomatic/settings/dashboard',
646
647
            'seomatic/global' => [
648
                'route' => 'seomatic/settings/global',
649
                'defaults' => ['subSection' => 'general'],
650
            ],
651
            'seomatic/global/<subSection:{handle}>' =>
652
                'seomatic/settings/global',
653
            'seomatic/global/<subSection:{handle}>/<siteHandle:{handle}>' =>
654
                'seomatic/settings/global',
655
656
            'seomatic/content' =>
657
                'seomatic/settings/content',
658
            'seomatic/content/<siteHandle:{handle}>' =>
659
                'seomatic/settings/content',
660
661
            'seomatic/edit-content/<subSection:{handle}>/<sourceBundleType:{handle}>/<sourceHandle:{handle}>' =>
662
                'seomatic/settings/edit-content',
663
            'seomatic/edit-content/<subSection:{handle}>/<sourceBundleType:{handle}>/<sourceHandle:{handle}>/<siteHandle:{handle}>' =>
664
                'seomatic/settings/edit-content',
665
666
            'seomatic/site' => [
667
                'route' => 'seomatic/settings/site',
668
                'defaults' => ['subSection' => 'identity'],
669
            ],
670
            'seomatic/site/<subSection:{handle}>' =>
671
                'seomatic/settings/site',
672
            'seomatic/site/<subSection:{handle}>/<siteHandle:{handle}>' =>
673
                'seomatic/settings/site',
674
675
            'seomatic/tracking' => [
676
                'route' => 'seomatic/settings/tracking',
677
                'defaults' => ['subSection' => 'googleAnalytics'],
678
            ],
679
            'seomatic/tracking/<subSection:{handle}>' =>
680
                'seomatic/settings/tracking',
681
            'seomatic/tracking/<subSection:{handle}>/<siteHandle:{handle}>' =>
682
                'seomatic/settings/tracking',
683
684
            'seomatic/plugin' =>
685
                'seomatic/settings/plugin',
686
        ];
687
    }
688
689
    /**
690
     * Returns the custom AdminCP cache options.
691
     *
692
     * @return array
693
     */
694
    protected function customAdminCpCacheOptions(): array
695
    {
696
        return [
697
            // Frontend template caches
698
            [
699
                'key'    => 'seomatic-frontendtemplate-caches',
700
                'label'  => Craft::t('seomatic', 'SEOmatic frontend template caches'),
701
                'action' => [Seomatic::$plugin->frontendTemplates, 'invalidateCaches'],
702
            ],
703
            // Meta bundle caches
704
            [
705
                'key'    => 'seomatic-metabundle-caches',
706
                'label'  => Craft::t('seomatic', 'SEOmatic metadata caches'),
707
                'action' => [Seomatic::$plugin->metaContainers, 'invalidateCaches'],
708
            ],
709
            // Sitemap caches
710
            [
711
                'key'    => 'seomatic-sitemap-caches',
712
                'label'  => Craft::t('seomatic', 'SEOmatic sitemap caches'),
713
                'action' => [Seomatic::$plugin->sitemaps, 'invalidateCaches'],
714
            ],
715
        ];
716
    }
717
718
    /**
719
     * Returns the custom AdminCP user permissions.
720
     *
721
     * @return array
722
     */
723
    protected function customAdminCpPermissions(): array
724
    {
725
        // The script meta containers for the global meta bundle
726
        try {
727
            $currentSiteId = Craft::$app->getSites()->getCurrentSite()->id ?? 1;
728
        } catch (SiteNotFoundException $e) {
729
            $currentSiteId = 1;
730
        }
731
        // Dynamic permissions for the scripts
732
        $metaBundle = Seomatic::$plugin->metaBundles->getGlobalMetaBundle($currentSiteId);
733
        $scripts = Seomatic::$plugin->metaBundles->getContainerDataFromBundle(
734
            $metaBundle,
735
            MetaScriptContainer::CONTAINER_TYPE
736
        );
737
        $scriptsPerms = [];
738
        foreach ($scripts as $scriptHandle => $scriptData) {
739
            $scriptsPerms["seomatic:tracking-scripts:${scriptHandle}"] = [
740
                'label' => Craft::t('seomatic', $scriptData->name),
741
            ];
742
        }
743
744
        return [
745
            "seomatic:dashboard"  => [
746
                'label' => Craft::t('seomatic', 'Dashboard'),
747
            ],
748
            "seomatic:global-meta"      => [
749
                'label'  => Craft::t('seomatic', 'Edit Global Meta'),
750
                'nested' => [
751
                    "seomatic:global-meta:general"  => [
752
                        'label' => Craft::t('seomatic', 'General'),
753
                    ],
754
                    "seomatic:global-meta:twitter"  => [
755
                        'label' => Craft::t('seomatic', 'Twitter'),
756
                    ],
757
                    "seomatic:global-meta:facebook" => [
758
                        'label' => Craft::t('seomatic', 'Facebook'),
759
                    ],
760
                    "seomatic:global-meta:robots"   => [
761
                        'label' => Craft::t('seomatic', 'Robots'),
762
                    ],
763
                    "seomatic:global-meta:humans"   => [
764
                        'label' => Craft::t('seomatic', 'Humans'),
765
                    ],
766
                ],
767
            ],
768
            "seomatic:content-meta"     => [
769
                'label'  => Craft::t('seomatic', 'Edit Content SEO'),
770
                'nested' => [
771
                    "seomatic:content-meta:general"  => [
772
                        'label' => Craft::t('seomatic', 'General'),
773
                    ],
774
                    "seomatic:content-meta:twitter"  => [
775
                        'label' => Craft::t('seomatic', 'Twitter'),
776
                    ],
777
                    "seomatic:content-meta:facebook" => [
778
                        'label' => Craft::t('seomatic', 'Facebook'),
779
                    ],
780
                    "seomatic:content-meta:sitemap"  => [
781
                        'label' => Craft::t('seomatic', 'Sitemap'),
782
                    ],
783
                ],
784
            ],
785
            "seomatic:site-settings"    => [
786
                'label'  => Craft::t('seomatic', 'Edit Site Settings'),
787
                'nested' => [
788
                    "seomatic:site-settings:identity"     => [
789
                        'label' => Craft::t('seomatic', 'Identity'),
790
                    ],
791
                    "seomatic:site-settings:creator"      => [
792
                        'label' => Craft::t('seomatic', 'Creator'),
793
                    ],
794
                    "seomatic:site-settings:social-media" => [
795
                        'label' => Craft::t('seomatic', 'Social Media'),
796
                    ],
797
                ],
798
            ],
799
            "seomatic:tracking-scripts" => [
800
                'label'  => Craft::t('seomatic', 'Edit Tracking Scripts'),
801
                'nested' => $scriptsPerms,
802
            ],
803
            "seomatic:plugin-settings"  => [
804
                'label' => Craft::t('seomatic', 'Edit Plugin Settings'),
805
            ],
806
        ];
807
    }
808
}
809