Passed
Push — develop ( 5e3929...c7f1f9 )
by Andrew
22:12 queued 11:32
created

MetaScriptContainer::normalizeContainerData()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 7
ccs 0
cts 5
cp 0
crap 6
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\models;
13
14
use Craft;
15
use nystudio107\seomatic\base\NonceContainer;
16
use nystudio107\seomatic\helpers\ImageTransform as ImageTransformHelper;
17
use nystudio107\seomatic\Seomatic;
18
use yii\caching\TagDependency;
19
use yii\web\View;
20
21
/**
22
 * @author    nystudio107
23
 * @package   Seomatic
24
 * @since     3.0.0
25
 */
26
class MetaScriptContainer extends NonceContainer
27
{
28
    // Constants
29
    // =========================================================================
30
31
    const CONTAINER_TYPE = 'MetaScriptContainer';
32
33
    // Public Properties
34
    // =========================================================================
35
36
    /**
37
     * The data in this container
38
     *
39
     * @var MetaScript[] $data
40
     */
41
    public $data = [];
42
43
    /**
44
     * @var int
45
     */
46
    public $position = View::POS_HEAD;
47
48
    // Public Methods
49
    // =========================================================================
50
51
    /**
52
     * @inheritdoc
53
     */
54
    public function includeMetaData($dependency)
55
    {
56
        Craft::beginProfile('MetaScriptContainer::includeMetaData', __METHOD__);
57
        $uniqueKey = $this->handle . $dependency->tags[3] . $this->dataLayerHash();
58
        $cache = Craft::$app->getCache();
59
        if ($this->clearCache) {
60
            TagDependency::invalidate($cache, $dependency->tags[3]);
61
        }
62
        $tagData = $cache->getOrSet(
63
            self::CONTAINER_TYPE . $uniqueKey,
64
            function () use ($uniqueKey) {
65
                Craft::info(
66
                    self::CONTAINER_TYPE . ' cache miss: ' . $uniqueKey,
67
                    __METHOD__
68
                );
69
                $tagData = [];
70
                if ($this->prepForInclusion()) {
71
                    /** @var $metaScriptModel MetaScript */
72
                    foreach ($this->data as $metaScriptModel) {
73
                        if ($metaScriptModel->include) {
74
                            // The regular script JS
75
                            $js = $metaScriptModel->render();
76
                            if (!empty($js)) {
77
                                $scenario = $this->scenario;
78
                                $metaScriptModel->setScenario('render');
79
                                $options = $metaScriptModel->tagAttributes();
80
                                $metaScriptModel->setScenario($scenario);
81
                                $tagData[] = [
82
                                    'js' => $js,
83
                                    'position' => $metaScriptModel->position ?? $this->position,
84
                                    'nonce' => $metaScriptModel->nonce ?? null,
85
                                    'tagAttrs' => $options,
86
                                ];
87
                                // If `devMode` is enabled, validate the Meta Script and output any model errors
88
                                if (Seomatic::$devMode) {
89
                                    $metaScriptModel->debugMetaItem(
90
                                        'Script attribute: '
91
                                    );
92
                                }
93
                            }
94
                            // The regular script JS
95
                            $bodyJs = $metaScriptModel->renderBodyHtml();
96
                            if (!empty($bodyJs)) {
97
                                $scenario = $this->scenario;
98
                                $metaScriptModel->setScenario('render');
99
                                $options = $metaScriptModel->tagAttributes();
100
                                $metaScriptModel->setScenario($scenario);
101
                                $tagData[] = [
102
                                    'js' => $bodyJs,
103
                                    'position' => $metaScriptModel->bodyPosition ?? $this->position,
104
                                    'nonce' => $metaScriptModel->nonce ?? null,
105
                                    'tagAttrs' => $options,
106
                                ];
107
                                // If `devMode` is enabled, validate the Meta Script and output any model errors
108
                                if (Seomatic::$devMode) {
109
                                    $metaScriptModel->debugMetaItem(
110
                                        'Script attribute: '
111
                                    );
112
                                }
113
                            }
114
                        }
115
                    }
116
                }
117
118
                return $tagData;
119
            },
120
            Seomatic::$cacheDuration,
121
            $dependency
122
        );
123
        // Invalidate the cache we just created if there were pending image transforms in it
124
        if (ImageTransformHelper::$pendingImageTransforms) {
125
            TagDependency::invalidate($cache, $dependency->tags[3]);
126
        }
127
        // Register the tags
128
        foreach ($tagData as $config) {
129
            // Register the tags
130
            $attrs = $config['tagAttrs'] ?? [];
131
            if (!empty($config['nonce'])) {
132
                /** @noinspection SlowArrayOperationsInLoopInspection */
133
                $attrs = array_merge($attrs, [
134
                    'nonce' => $config['nonce'],
135
                ]);
136
            }
137
            Seomatic::$view->registerScript(
138
                $config['js'],
139
                $config['position'],
140
                $attrs
141
            );
142
        }
143
144
        Craft::endProfile('MetaScriptContainer::includeMetaData', __METHOD__);
145
    }
146
147
    /**
148
     * @inheritdoc
149
     */
150
    public function render(array $params = []): string
151
    {
152
        $html = parent::render($params);
153
        if ($params['renderScriptTags']) {
154
            $html =
155
                '<script>'
156
                . $html
157
                . '</script>';
158
        }
159
160
        return $html;
161
    }
162
163
    /**
164
     * @inheritdoc
165
     */
166
    public function normalizeContainerData()
167
    {
168
        parent::normalizeContainerData();
169
170
        foreach ($this->data as $key => $config) {
171
            $config['key'] = $key;
172
            $this->data[$key] = MetaScript::create($config);
0 ignored issues
show
Bug introduced by
$config of type nystudio107\seomatic\models\MetaScript is incompatible with the type array expected by parameter $config of nystudio107\seomatic\models\MetaScript::create(). ( Ignorable by Annotation )

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

172
            $this->data[$key] = MetaScript::create(/** @scrutinizer ignore-type */ $config);
Loading history...
173
        }
174
    }
175
176
    // Protected Methods
177
    // =========================================================================
178
179
    protected function dataLayerHash(): string
180
    {
181
        $data = '';
182
        foreach ($this->data as $metaScriptModel) {
183
            $data .= serialize($metaScriptModel->dataLayer);
184
        }
185
186
        return md5($data);
187
    }
188
}
189