Issues (257)

src/models/MetaJsonLdContainer.php (2 issues)

1
<?php
2
/**
3
 * SEOmatic plugin for Craft CMS
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 craft\helpers\Html;
16
use nystudio107\seomatic\base\NonceContainer;
17
use nystudio107\seomatic\helpers\ImageTransform as ImageTransformHelper;
18
use nystudio107\seomatic\helpers\MetaValue as MetaValueHelper;
19
use nystudio107\seomatic\Seomatic;
20
use yii\caching\TagDependency;
21
use yii\web\View;
22
23
/**
24
 * @author    nystudio107
25
 * @package   Seomatic
26
 * @since     3.0.0
27
 */
28
class MetaJsonLdContainer extends NonceContainer
29
{
30
    // Constants
31
    // =========================================================================
32
33
    public const CONTAINER_TYPE = 'MetaJsonLdContainer';
34
35
    // Public Properties
36
    // =========================================================================
37
38
    /**
39
     * The data in this container
40
     *
41
     * @var MetaJsonLd[] $data
42
     */
43
    public $data = [];
44
45
    // Public Methods
46
    // =========================================================================
47
48
    /**
49
     * @inheritdoc
50
     */
51
    public function includeMetaData($dependency)
52
    {
53
        Craft::beginProfile('MetaJsonLdContainer::includeMetaData', __METHOD__);
54
        $uniqueKey = $this->handle . $dependency->tags[3] . '-v2';
55
        $cache = Craft::$app->getCache();
56
        if ($this->clearCache) {
57
            TagDependency::invalidate($cache, $dependency->tags[3]);
58
        }
59
        [$jsonLd, $attrs] = $cache->getOrSet(
60
            self::CONTAINER_TYPE . $uniqueKey,
61
            function() use ($uniqueKey) {
62
                Craft::info(
63
                    self::CONTAINER_TYPE . ' cache miss: ' . $uniqueKey,
64
                    __METHOD__
65
                );
66
67
                return $this->renderInternal();
68
            },
69
            Seomatic::$cacheDuration,
70
            $dependency
71
        );
72
        // Invalidate the cache we just created if there were pending image transforms in it
73
        // or we were asked to clear the cache for this container (because it's a preview request, etc.)
74
        if ($this->clearCache || ImageTransformHelper::$pendingImageTransforms) {
75
            TagDependency::invalidate($cache, $dependency->tags[3]);
76
        }
77
        Seomatic::$view->registerScript(
0 ignored issues
show
The method registerScript() 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

77
        Seomatic::$view->/** @scrutinizer ignore-call */ 
78
                         registerScript(

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...
78
            $jsonLd,
79
            View::POS_END,
80
            $attrs
81
        );
82
        Craft::endProfile('MetaJsonLdContainer::includeMetaData', __METHOD__);
83
    }
84
85
    /**
86
     * @inheritdoc
87
     */
88
    public function render(array $params = []): string
89
    {
90
        [$jsonLd, $attrs] = $this->renderInternal();
91
92
        return trim(Html::script($jsonLd, $attrs));
93
    }
94
95
    /**
96
     * @inheritdoc
97
     */
98
    public function normalizeContainerData()
99
    {
100
        parent::normalizeContainerData();
101
102
        /** @var array $config */
103
        foreach ($this->data as $key => $config) {
104
            $schemaType = $config['type'] ?? $config['@type'];
105
            $config['key'] = $key;
106
            $schemaType = MetaValueHelper::parseString($schemaType);
107
            $jsonLd = MetaJsonLd::create($schemaType, $config);
0 ignored issues
show
$config of type nystudio107\seomatic\models\MetaJsonLd is incompatible with the type array expected by parameter $config of nystudio107\seomatic\models\MetaJsonLd::create(). ( Ignorable by Annotation )

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

107
            $jsonLd = MetaJsonLd::create($schemaType, /** @scrutinizer ignore-type */ $config);
Loading history...
108
            // Retain the intended type
109
            $jsonLd->type = $config['type'] ?? $config['@type'];
110
            $this->data[$key] = $jsonLd;
111
        }
112
    }
113
114
    // Protected Methods
115
    // =========================================================================
116
117
    /**
118
     * Render the JSON-LD as a graph
119
     *
120
     * @return array
121
     */
122
    protected function renderInternal(): array
123
    {
124
        $tagData = [];
125
        if ($this->prepForInclusion()) {
126
            foreach ($this->data as $metaJsonLdModel) {
127
                if ($metaJsonLdModel->include) {
128
                    $options = $metaJsonLdModel->tagAttributes();
129
                    if ($metaJsonLdModel->prepForRender($options)) {
130
                        $tagData[] = [
131
                            'jsonLd' => $metaJsonLdModel,
132
                            'position' => View::POS_END,
133
                        ];
134
                        // If `devMode` is enabled, validate the JSON-LD and output any model errors
135
                        if (Seomatic::$devMode) {
136
                            $metaJsonLdModel->debugMetaItem(
137
                                'JSON-LD property: ',
138
                                [
139
                                    'default' => 'error',
140
                                    'google' => 'warning',
141
                                ]
142
                            );
143
                        }
144
                    }
145
                }
146
            }
147
        }
148
149
        // Create a root JSON-LD object
150
        $jsonLdGraph = MetaJsonLd::create('jsonLd', [
151
            'graph' => [],
152
        ]);
153
        $jsonLdGraph->type = null;
154
        // Add the JSON-LD objects to our root JSON-LD's graph
155
        $cspNonce = null;
156
        foreach ($tagData as $config) {
157
            $jsonLdGraph->graph[] = $config['jsonLd'];
158
            if (!empty($config['jsonLd']->nonce)) {
159
                $cspNonce = $config['jsonLd']->nonce;
160
            }
161
        }
162
        // Render the JSON-LD object
163
        $jsonLd = $jsonLdGraph->render([
164
            'renderRaw' => true,
165
            'renderScriptTags' => false,
166
            'array' => false,
167
        ]);
168
169
        // Register the tags
170
        $attrs = ['type' => 'application/ld+json'];
171
        if (!empty($cspNonce)) {
172
            $attrs = array_merge($attrs, [
173
                'nonce' => $cspNonce,
174
            ]);
175
        }
176
177
        return [$jsonLd, $attrs];
178
    }
179
}
180