Passed
Push — v3 ( f3fd39...177c2d )
by Andrew
13:29 queued 06:36
created

MetaBundle::behaviors()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 9
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 16
rs 9.9666
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 nystudio107\seomatic\Seomatic;
15
use nystudio107\seomatic\base\MetaContainer;
16
use nystudio107\seomatic\helpers\ArrayHelper;
17
use nystudio107\seomatic\helpers\MetaValue as MetaValueHelper;
18
use nystudio107\seomatic\base\FluentModel;
19
use nystudio107\seomatic\variables\SeomaticVariable;
20
21
use craft\behaviors\EnvAttributeParserBehavior;
22
use craft\helpers\Json as JsonHelper;
23
use craft\validators\ArrayValidator;
24
use craft\validators\DateTimeValidator;
25
26
use yii\behaviors\AttributeTypecastBehavior;
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
0 ignored issues
show
Coding Style introduced by
The tag in position 3 should be the @author tag
Loading history...
32
 */
33
class MetaBundle extends FluentModel
34
{
35
    // Properties
36
    // =========================================================================
37
38
    /**
39
     * @var string
40
     */
41
    public $bundleVersion;
42
43
    /**
44
     * @var string
45
     */
46
    public $sourceBundleType;
47
48
    /**
49
     * @var int
50
     */
51
    public $sourceId;
52
53
    /**
54
     * @var string
55
     */
56
    public $sourceName;
57
58
    /**
59
     * @var string
60
     */
61
    public $sourceHandle;
62
63
    /**
64
     * @var string
65
     */
66
    public $sourceType;
67
68
    /**
69
     * @var string
70
     */
71
    public $sourceTemplate;
72
73
    /**
74
     * @var int
75
     */
76
    public $sourceSiteId;
77
78
    /**
79
     * @var array
80
     */
81
    public $sourceAltSiteSettings = [];
82
83
    /**
84
     * @var \DateTime
85
     */
86
    public $sourceDateUpdated;
87
88
    /**
89
     * @var MetaGlobalVars
90
     */
91
    public $metaGlobalVars;
92
93
    /**
94
     * @var MetaSiteVars
95
     */
96
    public $metaSiteVars;
97
98
    /**
99
     * @var MetaSitemapVars
100
     */
101
    public $metaSitemapVars;
102
103
    /**
104
     * @var MetaContainer[]
105
     */
106
    public $metaContainers;
107
108
    /**
109
     * @var array
110
     */
111
    public $redirectsContainer;
112
113
    /**
114
     * @var FrontendTemplateContainer
115
     */
116
    public $frontendTemplatesContainer;
117
118
    /**
119
     * @var MetaBundleSettings
120
     */
121
    public $metaBundleSettings;
122
123
    // Methods
124
    // =========================================================================
125
126
    /**
127
     * Create a new meta bundle
128
     *
129
     * @param array $config
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
130
     * @param bool $parse    Whether the resulting metabundle should be parsed
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter name; 4 found
Loading history...
131
     *
132
     * @return null|MetaBundle
133
     */
134
    public static function create(array $config = [], bool $parse = true)
135
    {
136
        self::cleanProperties(__CLASS__, $config);
137
        $model = new MetaBundle($config);
138
        if ($model) {
0 ignored issues
show
introduced by
$model is of type nystudio107\seomatic\models\MetaBundle, thus it always evaluated to true.
Loading history...
139
            $model->normalizeMetaBundleData($parse);
140
        }
141
142
        return $model;
143
    }
144
145
    /**
146
     * Normalizes the meta bundles’s data for use.
147
     *
148
     * This is called after meta bundle data is loaded, to allow it to be
149
     * parsed, models instantiated, etc.
150
     *
151
     * @param bool $parse    Whether the resulting metabundle should be parsed
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
152
     */
153
    public function normalizeMetaBundleData(bool $parse = true)
154
    {
155
        // Decode any JSON data
156
        $properties = $this->getAttributes();
157
        foreach ($properties as $property => $value) {
158
            if (!empty($value) && \is_string($value)) {
159
                $this->$property = JsonHelper::decodeIfJson($value);
160
            }
161
        }
162
163
        // Meta global variables
164
        if ($this->metaGlobalVars !== null && \is_array($this->metaGlobalVars)) {
0 ignored issues
show
introduced by
The condition is_array($this->metaGlobalVars) is always false.
Loading history...
165
            $this->metaGlobalVars = MetaGlobalVars::create($this->metaGlobalVars);
166
        }
167
        // Meta site variables
168
        if ($this->metaSiteVars !== null && \is_array($this->metaSiteVars)) {
0 ignored issues
show
introduced by
The condition is_array($this->metaSiteVars) is always false.
Loading history...
169
            $this->metaSiteVars = MetaSiteVars::create($this->metaSiteVars);
170
        }
171
        // Meta sitemap variables
172
        if ($this->metaSitemapVars !== null && \is_array($this->metaSitemapVars)) {
0 ignored issues
show
introduced by
The condition is_array($this->metaSitemapVars) is always false.
Loading history...
173
            $this->metaSitemapVars = MetaSitemapVars::create($this->metaSitemapVars);
174
        }
175
        // Meta bundle settings
176
        if ($this->metaBundleSettings !== null && \is_array($this->metaBundleSettings)) {
0 ignored issues
show
introduced by
The condition is_array($this->metaBundleSettings) is always false.
Loading history...
177
            $this->metaBundleSettings = MetaBundleSettings::create($this->metaBundleSettings);
178
        }
179
        // Frontend templates
180
        if ($this->frontendTemplatesContainer !== null && \is_array($this->frontendTemplatesContainer)) {
0 ignored issues
show
introduced by
The condition is_array($this->frontendTemplatesContainer) is always false.
Loading history...
181
            $this->frontendTemplatesContainer = FrontendTemplateContainer::create($this->frontendTemplatesContainer);
182
        }
183
        // Create our variable so that meta containers can be parsed based on dynamic values
184
        // Make sure Twig is loaded and instantiated first by priming the pump
185
        if ($parse) {
186
            MetaValueHelper::parseString('{prime}');
187
            $oldSeomaticVariable = Seomatic::$seomaticVariable;
188
            if (Seomatic::$seomaticVariable === null) {
189
                Seomatic::$seomaticVariable = new SeomaticVariable();
190
            }
191
            $oldMeta = Seomatic::$seomaticVariable->meta;
192
            $oldSite = Seomatic::$seomaticVariable->site;
193
            $oldLoadingContainers = Seomatic::$loadingContainers;
194
            $oldPreviewingMetaContainers = Seomatic::$previewingMetaContainers;
195
            Seomatic::$loadingContainers = false;
196
            Seomatic::$previewingMetaContainers = false;
197
            // Merge these global vars with the MetaContainers global vars
198
            $globalVars = [];
199
            if (Seomatic::$plugin->metaContainers->metaGlobalVars !== null) {
200
                $globalVars = Seomatic::$plugin->metaContainers->metaGlobalVars->getAttributes();
201
            }
202
            $thisGlobalVars = $this->metaGlobalVars->getAttributes();
203
            $thisGlobals = MetaGlobalVars::create(ArrayHelper::merge($globalVars, $thisGlobalVars));
204
            // Merge these site vars with the MetaContainers site vars
205
            $siteVars = [];
206
            if (Seomatic::$plugin->metaContainers->metaSiteVars !== null) {
207
                $siteVars = Seomatic::$plugin->metaContainers->metaSiteVars->getAttributes();
208
            }
209
            $thisSiteVars = $this->metaSiteVars->getAttributes();
210
            $thisSite = MetaSiteVars::create(ArrayHelper::merge($siteVars, $thisSiteVars));
211
            Seomatic::$seomaticVariable->meta = $thisGlobals;
212
            Seomatic::$seomaticVariable->site = $thisSite;
213
            MetaValueHelper::cache();
214
            Seomatic::$previewingMetaContainers = $oldPreviewingMetaContainers;
215
216
            // Meta containers
217
            if (!empty($this->metaContainers)) {
218
                $metaContainers = $this->metaContainers;
219
                $this->metaContainers = [];
220
                foreach ($metaContainers as $key => $metaContainer) {
221
                    /** @var MetaContainer $containerClass */
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...
222
                    $containerClass = $metaContainer['class'];
223
                    /**  @var array $metaContainer */
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...
224
                    $this->metaContainers[$key] = $containerClass::create($metaContainer);
225
                }
226
            }
227
            // Restore the $seomaticVariable
228
            Seomatic::$loadingContainers = $oldLoadingContainers;
229
            Seomatic::$seomaticVariable->meta = $oldMeta;
230
            Seomatic::$seomaticVariable->site = $oldSite;
231
            Seomatic::$seomaticVariable = $oldSeomaticVariable;
232
            MetaValueHelper::cache();
233
        }
234
    }
235
236
    /**
237
     * @inheritdoc
238
     */
239
    public function datetimeAttributes(): array
240
    {
241
        $names = parent::datetimeAttributes();
242
        $names[] = 'sourceDateUpdated';
243
244
        return $names;
245
    }
246
247
    /**
248
     * Validation rules
249
     * @return array the validation rules
0 ignored issues
show
Coding Style introduced by
There must be exactly one blank line before the tags in a doc comment
Loading history...
250
     */
251
    public function rules(): array
252
    {
253
        $rules = [
254
            [
255
                [
256
                    'bundleVersion',
257
                    'sourceType',
258
                    'sourceName',
259
                    'sourceHandle',
260
                    'sourceTemplate',
261
                    'sourceType',
262
                ],
263
                'string',
264
            ],
265
            [['sourceId', 'sourceSiteId'], 'number', 'min' => 1],
266
            [['sourceDateUpdated'], DateTimeValidator::class],
267
            [
268
                [
269
                    'sourceTemplate',
270
                    'sourceAltSiteSettings',
271
                ],
272
                'safe'
273
            ],
274
            [
275
                [
276
                    'metaContainers',
277
                    'redirectsContainer',
278
                ],
279
                ArrayValidator::class
280
            ],
281
            [
282
                [
283
                    'metaGlobalVars',
284
                    'metaSiteVars',
285
                    'metaSitemapVars',
286
                    'metaBundleSettings',
287
                    'frontendTemplatesContainer',
288
                ],
289
                'safe'
290
            ],
291
        ];
292
293
        return $rules;
294
    }
295
296
    /**
297
     * @return array
298
     */
299
    public function behaviors()
300
    {
301
        $craft31Behaviors = [];
302
        if (Seomatic::$craft31) {
303
            $craft31Behaviors = [
304
                'parser' => [
305
                    'class' => EnvAttributeParserBehavior::class,
306
                    'attributes' => [
307
                    ],
308
                ]
309
            ];
310
        }
311
312
        return array_merge($craft31Behaviors, [
313
            'typecast' => [
314
                'class' => AttributeTypecastBehavior::class,
315
                // 'attributeTypes' will be composed automatically according to `rules()`
316
            ],
317
        ]);
318
    }
319
}
320