Test Failed
Push — develop ( fe9ea4...fb47e1 )
by Andrew
10:25
created

FrontendTemplates::init()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
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\services;
13
14
use nystudio107\seomatic\helpers\UrlHelper;
15
use nystudio107\seomatic\Seomatic;
16
use nystudio107\seomatic\models\EditableTemplate;
17
use nystudio107\seomatic\models\FrontendTemplateContainer;
18
19
use Craft;
20
use craft\base\Component;
21
use craft\errors\SiteNotFoundException;
22
use craft\events\RegisterUrlRulesEvent;
23
use craft\web\UrlManager;
24
25
use yii\base\Event;
26
use yii\caching\TagDependency;
27
28
/**
29
 * @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...
30
 * @package   Seomatic
31
 * @since     3.0.0
32
 */
33
class FrontendTemplates extends Component
34
{
35
    // Constants
36
    // =========================================================================
37
38
    const FRONTENDTEMPLATES_CONTAINER = Seomatic::SEOMATIC_HANDLE . EditableTemplate::TEMPLATE_TYPE;
39
40
    const HUMANS_TXT_HANDLE = 'humans';
41
    const ROBOTS_TXT_HANDLE = 'robots';
42
    const ADS_TXT_HANDLE = 'ads';
43
44
    const GLOBAL_FRONTENDTEMPLATE_CACHE_TAG = 'seomatic_frontendtemplate';
45
    const FRONTENDTEMPLATE_CACHE_TAG = 'seomatic_frontendtemplate_';
46
47
    const CACHE_KEY = 'seomatic_frontendtemplate_';
48
49
    const IGNORE_DB_ATTRIBUTES = [
50
        'id',
51
        'dateCreated',
52
        'dateUpdated',
53
        'uid',
54
    ];
55
56
    // Protected Properties
57
    // =========================================================================
58
59
    /**
60
     * @var FrontendTemplateContainer
61
     */
62
    protected $frontendTemplateContainer;
63
64
    // Public Methods
65
    // =========================================================================
66
67
    /**
68
     * @inheritdoc
69
     */
70
    public function init()
71
    {
72
        parent::init();
73
    }
74
75
    /**
76
     * Load the frontend template containers
77
     *
78
     * @param int|null $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
79
     */
80
    public function loadFrontendTemplateContainers(int $siteId = null)
81
    {
82
        $sites = Craft::$app->getSites();
83
        if ($siteId === null) {
84
            $siteId = $sites->getCurrentSite()->id ?? 1;
85
        }
86
        $metaBundle = Seomatic::$plugin->metaBundles->getGlobalMetaBundle($siteId, false);
87
        if ($metaBundle === null) {
88
            return;
89
        }
90
        // Don't register any frontend templates if this site has a sub-directory as part of the URL
91
        try {
92
            $baseUrl = $sites->getCurrentSite()->getBaseUrl(true);
93
        } catch (SiteNotFoundException $e) {
94
            $baseUrl = null;
95
        }
96
        if ($baseUrl === null || UrlHelper::urlHasSubDir($baseUrl)) {
97
            return;
98
        }
99
        $this->frontendTemplateContainer = $metaBundle->frontendTemplatesContainer;
100
        // Handler: UrlManager::EVENT_REGISTER_SITE_URL_RULES
101
        Event::on(
102
            UrlManager::class,
103
            UrlManager::EVENT_REGISTER_SITE_URL_RULES,
104
            function (RegisterUrlRulesEvent $event) {
105
                Craft::debug(
106
                    'UrlManager::EVENT_REGISTER_SITE_URL_RULES',
107
                    __METHOD__
108
                );
109
                // Register our sitemap routes
110
                $event->rules = array_merge(
111
                    $event->rules,
112
                    $this->frontendTemplateRouteRules()
113
                );
114
            }
115
        );
116
    }
117
118
    /**
119
     * @return array
120
     */
121
    public function frontendTemplateRouteRules(): array
122
    {
123
        $rules = [];
124
        foreach ($this->frontendTemplateContainer->data as $frontendTemplate) {
125
            if ($frontendTemplate->include) {
126
                /** @var $frontendTemplate EditableTemplate */
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
The close comment tag must be the only content on the line
Loading history...
127
                $rules = array_merge(
128
                    $rules,
129
                    $frontendTemplate->routeRules()
130
                );
131
            }
132
        }
133
134
        return $rules;
135
    }
136
137
    /**
138
     * @param string $template
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
139
     * @param array  $params
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
140
     *
141
     * @return string
142
     */
143
    public function renderTemplate(string $template, array $params = []): string
144
    {
145
        // Make sure the cache is on a per-site basis
146
        $siteId = 1;
147
        try {
148
            $currentSite = Craft::$app->getSites()->getCurrentSite();
149
        } catch (SiteNotFoundException $e) {
150
            $currentSite = null;
151
        }
152
        if ($currentSite) {
153
            $siteId = $currentSite->id;
154
        }
155
        $dependency = new TagDependency([
156
            'tags' => [
157
                self::GLOBAL_FRONTENDTEMPLATE_CACHE_TAG,
158
                self::FRONTENDTEMPLATE_CACHE_TAG . $template,
159
                self::FRONTENDTEMPLATE_CACHE_TAG . $template . $siteId,
160
            ],
161
        ]);
162
        $cache = Craft::$app->getCache();
163
        $html = $cache->getOrSet(
164
            self::CACHE_KEY . $template . $siteId,
165
            function () use ($template, $params) {
166
                Craft::info(
167
                    'Frontend template cache miss: ' . $template,
168
                    __METHOD__
169
                );
170
                $html = '';
171
                if (!empty($this->frontendTemplateContainer->data[$template])) {
172
                    /** @var $frontendTemplate EditableTemplate */
0 ignored issues
show
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
173
                    $frontendTemplate = $this->frontendTemplateContainer->data[$template];
174
                    // Special-case for the Robots.text template, to upgrade it
175
                    if ($template === FrontendTemplates::ROBOTS_TXT_HANDLE) {
176
                        $frontendTemplate->templateString = str_replace(
177
                            'Sitemap: {{ seomatic.helper.sitemapIndexForSiteId() }}',
178
                            '{{ seomatic.helper.sitemapIndex() }}',
179
                            $frontendTemplate->templateString
180
                        );
181
                    }
182
                    $html = $frontendTemplate->render($params);
183
                }
184
185
                return $html;
186
            },
187
            Seomatic::$cacheDuration,
188
            $dependency
189
        );
190
191
        return $html;
192
    }
193
194
    /**
195
     * Return a EditableTemplate object by $key from container $type
196
     *
197
     * @param string $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
198
     * @param string $type
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
199
     *
200
     * @return null|EditableTemplate
201
     */
202
    public function getFrontendTemplateByKey(string $key, string $type = '')
203
    {
204
        $frontendTemplate = null;
205
        if (!empty($this->frontendTemplateContainer) && !empty($this->frontendTemplateContainer->data)) {
206
            /** @var  $frontendTemplate EditableTemplate */
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
The close comment tag must be the only content on the line
Loading history...
207
            foreach ($this->frontendTemplateContainer->data as $frontendTemplate) {
208
                if ($key === $frontendTemplate->handle) {
209
                    return $frontendTemplate;
210
                }
211
            }
212
        }
213
214
        return $frontendTemplate;
215
    }
216
217
    /**
218
     * Invalidate all of the frontend template caches
219
     */
220
    public function invalidateCaches()
221
    {
222
        $cache = Craft::$app->getCache();
223
        TagDependency::invalidate($cache, self::GLOBAL_FRONTENDTEMPLATE_CACHE_TAG);
224
        Craft::info(
225
            'All frontend template caches cleared',
226
            __METHOD__
227
        );
228
    }
229
230
    /**
231
     * Invalidate a frontend template cache
232
     *
233
     * @param string $template
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
234
     */
235
    public function invalidateFrontendTemplateCache(string $template)
236
    {
237
        $cache = Craft::$app->getCache();
238
        TagDependency::invalidate($cache, self::FRONTENDTEMPLATE_CACHE_TAG . $template);
239
        Craft::info(
240
            'Frontend template cache cleared: ' . $template,
241
            __METHOD__
242
        );
243
    }
244
245
    // Protected Methods
246
    // =========================================================================
247
}
248