Passed
Push — develop ( e3ad9f...5a99f0 )
by Andrew
11:10
created

SettingsController::uriFromSourceBundle()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
eloc 10
nc 6
nop 3
dl 0
loc 18
ccs 0
cts 15
cp 0
crap 30
rs 9.6111
c 0
b 0
f 0
1
<?php
2
/**
3
 * SEOmatic plugin for Craft CMS 3.x
4
 *
5
 * @link      https://nystudio107.com/
6
 * @copyright Copyright (c) 2017 nystudio107
7
 * @license   https://nystudio107.com/license
0 ignored issues
show
Coding Style introduced by
@license tag must contain a URL and a license name
Loading history...
8
 */
9
10
namespace nystudio107\seomatic\controllers;
11
12
use nystudio107\seomatic\Seomatic;
13
use nystudio107\seomatic\assetbundles\seomatic\SeomaticAsset;
14
use nystudio107\seomatic\helpers\Field as FieldHelper;
15
use nystudio107\seomatic\helpers\PullField as PullFieldHelper;
16
use nystudio107\seomatic\helpers\Schema as SchemaHelper;
17
use nystudio107\seomatic\helpers\ArrayHelper;
18
use nystudio107\seomatic\helpers\DynamicMeta as DynamicMetaHelper;
19
use nystudio107\seomatic\helpers\ImageTransform as ImageTransformHelper;
20
use nystudio107\seomatic\helpers\PluginTemplate;
21
use nystudio107\seomatic\models\MetaBundle;
22
use nystudio107\seomatic\models\MetaScript;
23
use nystudio107\seomatic\models\MetaScriptContainer;
24
use nystudio107\seomatic\services\FrontendTemplates;
25
use nystudio107\seomatic\services\MetaBundles;
26
27
use Craft;
28
use craft\elements\Asset;
29
use craft\helpers\UrlHelper;
30
use craft\models\Site;
31
use craft\web\Controller;
32
33
use yii\base\InvalidConfigException;
34
use yii\web\NotFoundHttpException;
35
use yii\web\Response;
36
37
/**
38
 * @author    nystudio107
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
Coding Style introduced by
The tag in position 1 should be the @package tag
Loading history...
39
 * @package   Seomatic
40
 * @since     3.0.0
41
 */
42
class SettingsController extends Controller
43
{
44
    // Constants
45
    // =========================================================================
46
47
    const DOCUMENTATION_URL = 'https://github.com/nystudio107/craft-seomatic';
48
49
    const SETUP_GRADES = [
50
        ['id' => 'data1', 'name' => 'A', 'color' => '#008002'],
51
        ['id' => 'data2', 'name' => 'B', 'color' => '#9ACD31'],
52
        ['id' => 'data4', 'name' => 'C', 'color' => '#FFA500'],
53
        ['id' => 'data5', 'name' => 'D', 'color' => '#8B0100'],
54
    ];
55
56
    const SEO_SETUP_FIELDS = [
57
        'mainEntityOfPage' => 'Main Entity of Page',
58
        'seoTitle' => 'SEO Title',
59
        'seoDescription' => 'SEO Description',
60
        'seoKeywords' => 'SEO Keywords',
61
        'seoImage' => 'SEO Image',
62
        'seoImageDescription' => 'SEO Image Description',
63
    ];
64
65
    const SITE_SETUP_FIELDS = [
66
        'siteName' => 'Site Name',
67
        'twitterHandle' => 'Twitter Handle',
68
        'facebookProfileId' => 'Facebook Profile ID',
69
    ];
70
71
    const IDENTITY_SETUP_FIELDS = [
72
        'computedType' => 'Identity Entity Type',
73
        'genericName' => 'Identity Entity Name',
74
        'genericDescription' => 'Identity Entity Description',
75
        'genericUrl' => 'Identity Entity URL',
76
        'genericImage' => 'Identity Entity Brand',
77
    ];
78
79
    // Protected Properties
80
    // =========================================================================
81
82
    /**
83
     * @inheritdoc
84
     */
85
    protected $allowAnonymous = [
86
    ];
87
88
    // Public Methods
89
    // =========================================================================
90
91
    /**
92
     * Dashboard display
93
     *
94
     * @param string|null $siteHandle
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
95
     * @param bool        $showWelcome
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
96
     *
97
     * @return Response The rendered result
98
     * @throws NotFoundHttpException
99
     * @throws \yii\web\ForbiddenHttpException
100
     */
101
    public function actionDashboard(string $siteHandle = null, bool $showWelcome = false): Response
102
    {
103
        $variables = [];
104
        // Get the site to edit
105
        $siteId = $this->getSiteIdFromHandle($siteHandle);
106
        $pluginName = Seomatic::$settings->pluginName;
107
        $templateTitle = Craft::t('seomatic', 'Dashboard');
108
        // Asset bundle
109
        try {
110
            Seomatic::$view->registerAssetBundle(SeomaticAsset::class);
111
        } catch (InvalidConfigException $e) {
112
            Craft::error($e->getMessage(), __METHOD__);
113
        }
114
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(
115
            '@nystudio107/seomatic/assetbundles/seomatic/dist',
116
            true
0 ignored issues
show
Unused Code introduced by
The call to yii\web\AssetManager::getPublishedUrl() has too many arguments starting with true. ( Ignorable by Annotation )

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

116
        /** @scrutinizer ignore-call */ 
117
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
117
        );
118
        // Enabled sites
119
        $this->setMultiSiteVariables($siteHandle, $siteId, $variables);
120
        $variables['controllerHandle'] = 'dashboard';
121
122
        // Basic variables
123
        $variables['fullPageForm'] = false;
124
        $variables['docsUrl'] = self::DOCUMENTATION_URL;
125
        $variables['pluginName'] = Seomatic::$settings->pluginName;
126
        $variables['title'] = $templateTitle;
127
        $variables['docTitle'] = "{$pluginName} - {$templateTitle}";
128
        $siteHandleUri = Craft::$app->isMultiSite ? '/'.$siteHandle : '';
129
        $variables['crumbs'] = [
130
            [
131
                'label' => $pluginName,
132
                'url' => UrlHelper::cpUrl('seomatic'),
133
            ],
134
            [
135
                'label' => $templateTitle,
136
                'url' => UrlHelper::cpUrl('seomatic/dashboard'.$siteHandleUri),
137
            ],
138
        ];
139
        $variables['selectedSubnavItem'] = 'dashboard';
140
        $variables['showWelcome'] = $showWelcome;
141
        // Calulate the setup grades
142
        $variables['contentSetupStats'] = [];
143
        $variables['setupGrades'] = self::SETUP_GRADES;
144
        $numFields = \count(self::SEO_SETUP_FIELDS);
145
        $numGrades = \count(self::SETUP_GRADES);
146
        while ($numGrades--) {
147
            $variables['contentSetupStats'][] = 0;
148
        }
149
        $numGrades = \count(self::SETUP_GRADES);
150
        // Content SEO grades
151
        $variables['metaBundles'] = Seomatic::$plugin->metaBundles->getContentMetaBundlesForSiteId($siteId);
152
        $variables['contentSetupChecklistCutoff'] = floor(count($variables['metaBundles']) / 2);
153
        $variables['contentSetupChecklist'] = [];
154
        Seomatic::$plugin->metaBundles->pruneVestigialMetaBundles($variables['metaBundles']);
155
        /** @var MetaBundle $metaBundle */
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...
156
        foreach ($variables['metaBundles'] as $metaBundle) {
157
            $stat = 0;
158
            foreach (self::SEO_SETUP_FIELDS as $setupField => $setupLabel) {
159
                $stat += (int)!empty($metaBundle->metaGlobalVars[$setupField]);
160
                $value = $variables['contentSetupChecklist'][$setupField]['value'] ?? 0;
161
                $variables['contentSetupChecklist'][$setupField] = [
162
                    'label' => $setupLabel,
163
                    'value' => $value + (int)!empty($metaBundle->metaGlobalVars[$setupField]),
164
                ];
165
            }
166
            $stat = round($numGrades - (($stat * $numGrades) / $numFields));
167
            if ($stat >= $numGrades) {
168
                $stat = $numGrades - 1;
169
            }
170
            $variables['contentSetupStats'][$stat]++;
171
        }
172
        // Global SEO grades
173
        Seomatic::$previewingMetaContainers = true;
174
        $metaBundle = Seomatic::$plugin->metaBundles->getGlobalMetaBundle((int)$siteId);
175
        Seomatic::$previewingMetaContainers = false;
176
        if ($metaBundle !== null) {
177
            $stat = 0;
178
            $variables['globalSetupChecklist'] = [];
179
            foreach (self::SEO_SETUP_FIELDS as $setupField => $setupLabel) {
180
                $stat += (int)!empty($metaBundle->metaGlobalVars[$setupField]);
181
                $variables['globalSetupChecklist'][$setupField] = [
182
                    'label' => $setupLabel,
183
                    'value' => (int)!empty($metaBundle->metaGlobalVars[$setupField]),
184
                ];
185
            }
186
            $stat = round(($stat / $numFields) * 100);
187
            $variables['globalSetupStat'] = $stat;
188
            // Site Settings grades
189
            $numFields = \count(self::SITE_SETUP_FIELDS) + \count(self::IDENTITY_SETUP_FIELDS);
190
            $stat = 0;
191
            $variables['siteSetupChecklist'] = [];
192
            foreach (self::SITE_SETUP_FIELDS as $setupField => $setupLabel) {
193
                $stat += (int)!empty($metaBundle->metaSiteVars[$setupField]);
194
                $variables['siteSetupChecklist'][$setupField] = [
195
                    'label' => $setupLabel,
196
                    'value' => (int)!empty($metaBundle->metaSiteVars[$setupField]),
197
                ];
198
            }
199
            foreach (self::IDENTITY_SETUP_FIELDS as $setupField => $setupLabel) {
200
                $stat += (int)!empty($metaBundle->metaSiteVars->identity[$setupField]);
201
                $variables['siteSetupChecklist'][$setupField] = [
202
                    'label' => $setupLabel,
203
                    'value' => (int)!empty($metaBundle->metaSiteVars->identity[$setupField]),
204
                ];
205
            }
206
            $stat = round(($stat / $numFields) * 100);
207
            $variables['siteSetupStat'] = $stat;
208
        }
209
210
        // Render the template
211
        return $this->renderTemplate('seomatic/dashboard/index', $variables);
212
    }
213
214
    /**
215
     * Global settings
216
     *
217
     * @param string $subSection
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 6 spaces after parameter type; 1 found
Loading history...
218
     * @param string|null $siteHandle
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
219
     * @param null $loadFromSiteHandle
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 8 spaces after parameter type; 1 found
Loading history...
Documentation Bug introduced by
Are you sure the doc-type for parameter $loadFromSiteHandle is correct as it would always require null to be passed?
Loading history...
220
     *
221
     * @return Response The rendered result
222
     * @throws NotFoundHttpException
223
     * @throws \yii\web\ForbiddenHttpException
224
     */
225
    public function actionGlobal(string $subSection = 'general', string $siteHandle = null, $loadFromSiteHandle = null): Response
226
    {
227
        $variables = [];
228
        $siteId = $this->getSiteIdFromHandle($siteHandle);
229
230
        $pluginName = Seomatic::$settings->pluginName;
231
        $templateTitle = Craft::t('seomatic', 'Global SEO');
232
        $subSectionTitle = Craft::t('seomatic', ucfirst($subSection));
233
        // Asset bundle
234
        try {
235
            Seomatic::$view->registerAssetBundle(SeomaticAsset::class);
236
        } catch (InvalidConfigException $e) {
237
            Craft::error($e->getMessage(), __METHOD__);
238
        }
239
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(
240
            '@nystudio107/seomatic/assetbundles/seomatic/dist',
241
            true
0 ignored issues
show
Unused Code introduced by
The call to yii\web\AssetManager::getPublishedUrl() has too many arguments starting with true. ( Ignorable by Annotation )

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

241
        /** @scrutinizer ignore-call */ 
242
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
242
        );
243
        // Basic variables
244
        $variables['fullPageForm'] = true;
245
        $variables['docsUrl'] = self::DOCUMENTATION_URL;
246
        $variables['pluginName'] = Seomatic::$settings->pluginName;
247
        $variables['title'] = $templateTitle;
248
        $variables['subSectionTitle'] = $subSectionTitle;
249
        $variables['docTitle'] = "{$pluginName} - {$templateTitle} - {$subSectionTitle}";
250
        $siteHandleUri = Craft::$app->isMultiSite ? '/'.$siteHandle : '';
251
        $variables['crumbs'] = [
252
            [
253
                'label' => $pluginName,
254
                'url' => UrlHelper::cpUrl('seomatic'),
255
            ],
256
            [
257
                'label' => $templateTitle,
258
                'url' => UrlHelper::cpUrl('seomatic/global/general'.$siteHandleUri),
259
            ],
260
            [
261
                'label' => $subSectionTitle,
262
                'url' => UrlHelper::cpUrl('seomatic/global/'.$subSection.$siteHandleUri),
263
            ],
264
        ];
265
        $variables['selectedSubnavItem'] = 'global';
266
        // Pass in the pull fields
267
        $this->setGlobalFieldSourceVariables($variables);
268
        // Enabled sites
269
        $this->setMultiSiteVariables($siteHandle, $siteId, $variables);
270
        $variables['controllerHandle'] = 'global'.'/'.$subSection;
271
        $variables['currentSubSection'] = $subSection;
272
        // Meta bundle settings
273
        Seomatic::$previewingMetaContainers = true;
274
        // Get the site to copy the settings from, if any
275
        $variables['loadFromSiteHandle'] = $loadFromSiteHandle;
276
        $loadFromSiteId = $this->getSiteIdFromHandle($loadFromSiteHandle);
277
        $siteIdToLoad = $loadFromSiteHandle === null ? (int)$variables['currentSiteId'] : $loadFromSiteId;
0 ignored issues
show
introduced by
The condition $loadFromSiteHandle === null is always true.
Loading history...
278
        // Load the metabundle
279
        $metaBundle = Seomatic::$plugin->metaBundles->getGlobalMetaBundle($siteIdToLoad);
280
        Seomatic::$previewingMetaContainers = false;
281
        if ($metaBundle !== null) {
282
            $variables['metaGlobalVars'] = clone $metaBundle->metaGlobalVars;
283
            $variables['metaSitemapVars'] = $metaBundle->metaSitemapVars;
284
            $variables['metaBundleSettings'] = $metaBundle->metaBundleSettings;
285
            // Template container settings
286
            $templateContainers = $metaBundle->frontendTemplatesContainer->data;
287
            $variables['robotsTemplate'] = $templateContainers[FrontendTemplates::ROBOTS_TXT_HANDLE];
288
            $variables['humansTemplate'] = $templateContainers[FrontendTemplates::HUMANS_TXT_HANDLE];
289
            // Handle an edge-case where a migration didn't work properly to add ADS_TXT_HANDLE
290
            if (!isset($templateContainers[FrontendTemplates::ADS_TXT_HANDLE])) {
291
                $globalMetaBundle = Seomatic::$plugin->metaBundles->createGlobalMetaBundleForSite($siteId, $metaBundle);
292
                $templateContainers[FrontendTemplates::ADS_TXT_HANDLE] =
0 ignored issues
show
Coding Style introduced by
Multi-line assignments must have the equal sign on the second line
Loading history...
293
                    $globalMetaBundle->frontendTemplatesContainer->data[FrontendTemplates::ADS_TXT_HANDLE];
294
            }
295
            $variables['adsTemplate'] = $templateContainers[FrontendTemplates::ADS_TXT_HANDLE];
296
            // Image selectors
297
            $bundleSettings = $metaBundle->metaBundleSettings;
298
            $variables['elementType'] = Asset::class;
299
            $variables['seoImageElements'] = ImageTransformHelper::assetElementsFromIds(
300
                $bundleSettings->seoImageIds,
301
                $siteId
302
            );
303
            $variables['twitterImageElements'] = ImageTransformHelper::assetElementsFromIds(
304
                $bundleSettings->twitterImageIds,
305
                $siteId
306
            );
307
            $variables['ogImageElements'] = ImageTransformHelper::assetElementsFromIds(
308
                $bundleSettings->ogImageIds,
309
                $siteId
310
            );
311
        }
312
        // Preview the meta containers
313
        Seomatic::$plugin->metaContainers->previewMetaContainers(
314
            MetaBundles::GLOBAL_META_BUNDLE,
315
            (int)$variables['currentSiteId']
316
        );
317
        // Render the template
318
        return $this->renderTemplate('seomatic/settings/global/'.$subSection, $variables);
319
    }
320
321
    /**
322
     * @return Response
323
     * @throws \yii\web\BadRequestHttpException
324
     * @throws \craft\errors\MissingComponentException
325
     */
326
    public function actionSaveGlobal(): Response
327
    {
328
        $this->requirePostRequest();
329
        $request = Craft::$app->getRequest();
330
        $siteId = $request->getParam('siteId');
331
        $globalsSettings = $request->getParam('metaGlobalVars');
332
        $bundleSettings = $request->getParam('metaBundleSettings');
333
        $robotsTemplate = $request->getParam('robotsTemplate');
334
        $humansTemplate = $request->getParam('humansTemplate');
335
        $adsTemplate = $request->getParam('adsTemplate');
336
337
        // Set the element type in the template
338
        $elementName = '';
339
340
        // The site settings for the appropriate meta bundle
341
        Seomatic::$previewingMetaContainers = true;
342
        $metaBundle = Seomatic::$plugin->metaBundles->getGlobalMetaBundle($siteId);
343
        Seomatic::$previewingMetaContainers = false;
344
        if ($metaBundle !== null) {
345
            if (\is_array($globalsSettings) && \is_array($bundleSettings)) {
346
                PullFieldHelper::parseTextSources($elementName, $globalsSettings, $bundleSettings);
347
                PullFieldHelper::parseImageSources($elementName, $globalsSettings, $bundleSettings, $siteId);
348
                if (!empty($bundleSettings['siteType'])) {
349
                    $globalsSettings['mainEntityOfPage'] = SchemaHelper::getSpecificEntityType($bundleSettings);
350
                }
351
                $metaBundle->metaGlobalVars->setAttributes($globalsSettings);
352
                $metaBundle->metaBundleSettings->setAttributes($bundleSettings);
353
            }
354
            $templateContainers = $metaBundle->frontendTemplatesContainer->data;
355
            $robotsContainer = $templateContainers[FrontendTemplates::ROBOTS_TXT_HANDLE];
356
            if ($robotsContainer !== null && \is_array($robotsTemplate)) {
357
                $robotsContainer->setAttributes($robotsTemplate);
358
            }
359
            $humansContainer = $templateContainers[FrontendTemplates::HUMANS_TXT_HANDLE];
360
            if ($humansContainer !== null && \is_array($humansTemplate)) {
361
                $humansContainer->setAttributes($humansTemplate);
362
            }
363
            $adsContainer = $templateContainers[FrontendTemplates::ADS_TXT_HANDLE];
364
            if ($adsContainer !== null && \is_array($adsTemplate)) {
365
                $adsContainer->setAttributes($adsTemplate);
366
            }
367
368
            Seomatic::$plugin->metaBundles->syncBundleWithConfig($metaBundle, true);
369
            Seomatic::$plugin->metaBundles->updateMetaBundle($metaBundle, $siteId);
370
371
            Seomatic::$plugin->clearAllCaches();
372
            Craft::$app->getSession()->setNotice(Craft::t('seomatic', 'SEOmatic global settings saved.'));
373
        }
374
375
        return $this->redirectToPostedUrl();
376
    }
377
378
    /**
379
     * Content settings
380
     *
381
     * @param string|null $siteHandle
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
382
     *
383
     * @return Response The rendered result
384
     * @throws NotFoundHttpException
385
     * @throws \yii\web\ForbiddenHttpException
386
     */
387
    public function actionContent(string $siteHandle = null): Response
388
    {
389
        $variables = [];
390
        // Get the site to edit
391
        $siteId = $this->getSiteIdFromHandle($siteHandle);
392
393
        $pluginName = Seomatic::$settings->pluginName;
394
        $templateTitle = Craft::t('seomatic', 'Content SEO');
395
        // Asset bundle
396
        try {
397
            Seomatic::$view->registerAssetBundle(SeomaticAsset::class);
398
        } catch (InvalidConfigException $e) {
399
            Craft::error($e->getMessage(), __METHOD__);
400
        }
401
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(
402
            '@nystudio107/seomatic/assetbundles/seomatic/dist',
403
            true
0 ignored issues
show
Unused Code introduced by
The call to yii\web\AssetManager::getPublishedUrl() has too many arguments starting with true. ( Ignorable by Annotation )

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

403
        /** @scrutinizer ignore-call */ 
404
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
404
        );
405
        // Basic variables
406
        $variables['fullPageForm'] = false;
407
        $variables['docsUrl'] = self::DOCUMENTATION_URL;
408
        $variables['pluginName'] = Seomatic::$settings->pluginName;
409
        $variables['title'] = $templateTitle;
410
        $variables['docTitle'] = "{$pluginName} - {$templateTitle}";
411
        $siteHandleUri = Craft::$app->isMultiSite ? '/'.$siteHandle : '';
412
        $variables['crumbs'] = [
413
            [
414
                'label' => $pluginName,
415
                'url' => UrlHelper::cpUrl('seomatic'),
416
            ],
417
            [
418
                'label' => $templateTitle,
419
                'url' => UrlHelper::cpUrl('seomatic/content'.$siteHandleUri),
420
            ],
421
        ];
422
        $this->setMultiSiteVariables($siteHandle, $siteId, $variables);
423
        $variables['controllerHandle'] = 'content';
424
        $variables['selectedSubnavItem'] = 'content';
425
        $metaBundles = Seomatic::$plugin->metaBundles->getContentMetaBundlesForSiteId($siteId);
426
        Seomatic::$plugin->metaBundles->deleteVestigialMetaBundles($metaBundles);
427
428
        // Render the template
429
        return $this->renderTemplate('seomatic/settings/content/index', $variables);
430
    }
431
432
    /**
433
     * Global settings
434
     *
435
     * @param string $subSection
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 6 spaces after parameter type; 1 found
Loading history...
436
     * @param string $sourceBundleType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 6 spaces after parameter type; 1 found
Loading history...
437
     * @param string $sourceHandle
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 6 spaces after parameter type; 1 found
Loading history...
438
     * @param string|null $siteHandle
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
439
     * @param int|null $typeId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
440
     * @param null $loadFromSiteHandle
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 8 spaces after parameter type; 1 found
Loading history...
Documentation Bug introduced by
Are you sure the doc-type for parameter $loadFromSiteHandle is correct as it would always require null to be passed?
Loading history...
441
     *
442
     * @return Response The rendered result
443
     * @throws NotFoundHttpException
444
     * @throws \yii\web\ForbiddenHttpException
445
     */
446
    public function actionEditContent(
447
        string $subSection,
448
        string $sourceBundleType,
449
        string $sourceHandle,
450
        string $siteHandle = null,
451
        $typeId = null,
452
        $loadFromSiteHandle = null
453
    ): Response {
454
        $variables = [];
455
        // @TODO: Let people choose an entry/categorygroup/product as the preview
456
        // Get the site to edit
457
        $siteId = $this->getSiteIdFromHandle($siteHandle);
458
        if ($typeId !== null && is_string($typeId)) {
0 ignored issues
show
introduced by
The condition is_string($typeId) is always false.
Loading history...
459
            $typeId = (int)$typeId;
460
        }
461
        // Get the (entry) type menu
462
        $typeMenu = [];
463
        $seoElement = Seomatic::$plugin->seoElements->getSeoElementByMetaBundleType($sourceBundleType);
464
        if ($seoElement !== null) {
465
            $typeMenu = $seoElement::typeMenuFromHandle($sourceHandle);
466
        }
467
        $variables['typeMenu'] = $typeMenu;
468
        $variables['currentTypeId'] = null;
469
        if (!empty($typeMenu)) {
470
            $currentType = reset($typeMenu);
471
            $variables['currentType'] = $typeMenu[$typeId] ?? $currentType;
472
            $variables['currentTypeId'] = $typeId ?? key($typeMenu);
473
            $typeId = (int)$variables['currentTypeId'];
474
        }
475
        $pluginName = Seomatic::$settings->pluginName;
476
        // Asset bundle
477
        try {
478
            Seomatic::$view->registerAssetBundle(SeomaticAsset::class);
479
        } catch (InvalidConfigException $e) {
480
            Craft::error($e->getMessage(), __METHOD__);
481
        }
482
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(
483
            '@nystudio107/seomatic/assetbundles/seomatic/dist',
484
            true
0 ignored issues
show
Unused Code introduced by
The call to yii\web\AssetManager::getPublishedUrl() has too many arguments starting with true. ( Ignorable by Annotation )

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

484
        /** @scrutinizer ignore-call */ 
485
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
485
        );
486
        // Enabled sites
487
        $this->setMultiSiteVariables($siteHandle, $siteId, $variables);
488
        $this->cullDisabledSites($sourceBundleType, $sourceHandle, $variables);
489
        // Meta Bundle settings
490
        Seomatic::$previewingMetaContainers = true;
491
        // Get the site to copy the settings from, if any
492
        $variables['loadFromSiteHandle'] = $loadFromSiteHandle;
493
        $loadFromSiteId = $this->getSiteIdFromHandle($loadFromSiteHandle);
494
        $siteIdToLoad = $loadFromSiteHandle === null ? (int)$variables['currentSiteId'] : $loadFromSiteId;
0 ignored issues
show
introduced by
The condition $loadFromSiteHandle === null is always true.
Loading history...
495
        // Load the metabundle
496
        $metaBundle = Seomatic::$plugin->metaBundles->getMetaBundleBySourceHandle(
497
            $sourceBundleType,
498
            $sourceHandle,
499
            $siteIdToLoad,
500
            $typeId
501
        );
502
        Seomatic::$previewingMetaContainers = false;
503
        $templateTitle = '';
504
        if ($metaBundle !== null) {
505
            $variables['metaGlobalVars'] = clone $metaBundle->metaGlobalVars;
506
            $variables['metaSitemapVars'] = $metaBundle->metaSitemapVars;
507
            $variables['metaBundleSettings'] = $metaBundle->metaBundleSettings;
508
            $variables['currentSourceHandle'] = $metaBundle->sourceHandle;
509
            $variables['currentSourceBundleType'] = $metaBundle->sourceBundleType;
510
            $templateTitle = $metaBundle->sourceName;
511
        }
512
        // Basic variables
513
        $subSectionTitle = Craft::t('seomatic', ucfirst($subSection));
514
        $variables['fullPageForm'] = true;
515
        $variables['docsUrl'] = self::DOCUMENTATION_URL;
516
        $variables['pluginName'] = Seomatic::$settings->pluginName;
517
        $variables['title'] = $templateTitle;
518
        $variables['subSectionTitle'] = $subSectionTitle;
519
        $variables['docTitle'] = "{$pluginName} - Content SEO - {$templateTitle} - {$subSectionTitle}";
520
        $siteHandleUri = Craft::$app->isMultiSite ? '/'.$siteHandle : '';
521
        $variables['siteHandleUri'] = $siteHandleUri;
522
        $variables['crumbs'] = [
523
            [
524
                'label' => $pluginName,
525
                'url' => UrlHelper::cpUrl('seomatic'),
526
            ],
527
            [
528
                'label' => 'Content SEO',
529
                'url' => UrlHelper::cpUrl('seomatic/content'.$siteHandleUri),
530
            ],
531
            [
532
                'label' => $metaBundle->sourceName.' · '.$subSectionTitle,
533
                'url' => UrlHelper::cpUrl("seomatic/edit-content/${subSection}/${sourceBundleType}/${sourceHandle}"),
534
            ],
535
        ];
536
        $variables['selectedSubnavItem'] = 'content';
537
        $variables['controllerHandle'] = "edit-content/${subSection}/${sourceBundleType}/${sourceHandle}";
538
        // Image selectors
539
        $variables['currentSubSection'] = $subSection;
540
        $bundleSettings = $metaBundle->metaBundleSettings;
541
        $variables['elementType'] = Asset::class;
542
        $variables['seoImageElements'] = ImageTransformHelper::assetElementsFromIds(
543
            $bundleSettings->seoImageIds,
544
            $siteId
545
        );
546
        $variables['twitterImageElements'] = ImageTransformHelper::assetElementsFromIds(
547
            $bundleSettings->twitterImageIds,
548
            $siteId
549
        );
550
        $variables['ogImageElements'] = ImageTransformHelper::assetElementsFromIds(
551
            $bundleSettings->ogImageIds,
552
            $siteId
553
        );
554
        $variables['sourceType'] = $metaBundle->sourceType;
555
        // Pass in the pull fields
556
        $groupName = ucfirst($metaBundle->sourceType);
557
        $this->setContentFieldSourceVariables($sourceBundleType, $sourceHandle, $groupName, $variables);
558
        $uri = $this->uriFromSourceBundle($sourceBundleType, $sourceHandle, $siteId);
559
        // Preview the meta containers
560
        Seomatic::$plugin->metaContainers->previewMetaContainers(
561
            $uri,
562
            (int)$variables['currentSiteId'],
563
            false,
564
            false
565
        );
566
567
        // Render the template
568
        return $this->renderTemplate('seomatic/settings/content/'.$subSection, $variables);
569
    }
570
571
572
    /**
573
     * @return Response
574
     * @throws \yii\web\BadRequestHttpException
575
     * @throws \craft\errors\MissingComponentException
576
     */
577
    public function actionSaveContent(): Response
578
    {
579
        $this->requirePostRequest();
580
        $request = Craft::$app->getRequest();
581
        $sourceBundleType = $request->getParam('sourceBundleType');
582
        $sourceHandle = $request->getParam('sourceHandle');
583
        $siteId = $request->getParam('siteId');
584
        $typeId = $request->getParam('typeId') ?? null;
585
        $globalsSettings = $request->getParam('metaGlobalVars');
586
        $bundleSettings = $request->getParam('metaBundleSettings');
587
        $sitemapSettings = $request->getParam('metaSitemapVars');
588
        // Set the element type in the template
589
        $elementName = '';
590
        $seoElement = Seomatic::$plugin->seoElements->getSeoElementByMetaBundleType($sourceBundleType);
591
        if ($seoElement !== null) {
592
            $elementName = $seoElement::getElementRefHandle();
593
        }
594
        // The site settings for the appropriate meta bundle
595
        Seomatic::$previewingMetaContainers = true;
596
        $metaBundle = Seomatic::$plugin->metaBundles->getMetaBundleBySourceHandle(
597
            $sourceBundleType,
598
            $sourceHandle,
599
            $siteId,
600
            $typeId
601
        );
602
        Seomatic::$previewingMetaContainers = false;
603
        if ($metaBundle) {
604
            if (\is_array($globalsSettings) && \is_array($bundleSettings)) {
605
                PullFieldHelper::parseTextSources($elementName, $globalsSettings, $bundleSettings);
606
                PullFieldHelper::parseImageSources($elementName, $globalsSettings, $bundleSettings, $siteId);
607
                if (!empty($bundleSettings['siteType'])) {
608
                    $globalsSettings['mainEntityOfPage'] = SchemaHelper::getSpecificEntityType($bundleSettings);
609
                }
610
                $metaBundle->metaGlobalVars->setAttributes($globalsSettings);
611
                $metaBundle->metaBundleSettings->setAttributes($bundleSettings);
612
            }
613
            if (\is_array($sitemapSettings)) {
614
                $metaBundle->metaSitemapVars->setAttributes($sitemapSettings);
615
            }
616
617
            Seomatic::$plugin->metaBundles->syncBundleWithConfig($metaBundle, true);
618
            $metaBundle->typeId = $typeId;
619
            Seomatic::$plugin->metaBundles->updateMetaBundle($metaBundle, $siteId);
620
621
            Seomatic::$plugin->clearAllCaches();
622
            Craft::$app->getSession()->setNotice(Craft::t('seomatic', 'SEOmatic content settings saved.'));
623
        }
624
625
        return $this->redirectToPostedUrl();
626
    }
627
628
    /**
629
     * Site settings
630
     *
631
     * @param string $subSection
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
632
     * @param string $siteHandle
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
633
     * @param null $loadFromSiteHandle
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $loadFromSiteHandle is correct as it would always require null to be passed?
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
634
     *
635
     * @return Response The rendered result
636
     * @throws NotFoundHttpException
637
     * @throws \yii\web\ForbiddenHttpException
638
     */
639
    public function actionSite(string $subSection = 'identity', string $siteHandle = null, $loadFromSiteHandle = null): Response
640
    {
641
        $variables = [];
642
        // Get the site to edit
643
        $siteId = $this->getSiteIdFromHandle($siteHandle);
644
645
        $pluginName = Seomatic::$settings->pluginName;
646
        $templateTitle = Craft::t('seomatic', 'Site Settings');
647
        $subSectionSuffix = '';
648
        if ($subSection === 'social') {
649
            $subSectionSuffix = ' Media';
650
        }
651
        $subSectionTitle = Craft::t('seomatic', ucfirst($subSection).$subSectionSuffix);
652
        // Asset bundle
653
        try {
654
            Seomatic::$view->registerAssetBundle(SeomaticAsset::class);
655
        } catch (InvalidConfigException $e) {
656
            Craft::error($e->getMessage(), __METHOD__);
657
        }
658
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(
659
            '@nystudio107/seomatic/assetbundles/seomatic/dist',
660
            true
0 ignored issues
show
Unused Code introduced by
The call to yii\web\AssetManager::getPublishedUrl() has too many arguments starting with true. ( Ignorable by Annotation )

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

660
        /** @scrutinizer ignore-call */ 
661
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
661
        );
662
        // Basic variables
663
        $variables['fullPageForm'] = true;
664
        $variables['docsUrl'] = self::DOCUMENTATION_URL;
665
        $variables['pluginName'] = Seomatic::$settings->pluginName;
666
        $variables['title'] = $templateTitle;
667
        $variables['subSectionTitle'] = $subSectionTitle;
668
        $variables['docTitle'] = "{$pluginName} - {$templateTitle} - {$subSectionTitle}";
669
        $siteHandleUri = Craft::$app->isMultiSite ? '/'.$siteHandle : '';
670
        $variables['crumbs'] = [
671
            [
672
                'label' => $pluginName,
673
                'url' => UrlHelper::cpUrl('seomatic'),
674
            ],
675
            [
676
                'label' => $templateTitle,
677
                'url' => UrlHelper::cpUrl('seomatic/site/identity'.$siteHandleUri),
678
            ],
679
            [
680
                'label' => $subSectionTitle,
681
                'url' => UrlHelper::cpUrl('seomatic/site/'.$subSection.$siteHandleUri),
682
            ],
683
        ];
684
        $variables['selectedSubnavItem'] = 'site';
685
        $variables['currentSubSection'] = $subSection;
686
687
        // Enabled sites
688
        $this->setMultiSiteVariables($siteHandle, $siteId, $variables);
689
        $variables['controllerHandle'] = 'site'.'/'.$subSection;
690
691
        // The site settings for the appropriate meta bundle
692
        Seomatic::$previewingMetaContainers = true;
693
        // Get the site to copy the settings from, if any
694
        $variables['loadFromSiteHandle'] = $loadFromSiteHandle;
695
        $loadFromSiteId = $this->getSiteIdFromHandle($loadFromSiteHandle);
696
        $siteIdToLoad = $loadFromSiteHandle === null ? (int)$variables['currentSiteId'] : $loadFromSiteId;
0 ignored issues
show
introduced by
The condition $loadFromSiteHandle === null is always true.
Loading history...
697
        // Load the metabundle
698
        $metaBundle = Seomatic::$plugin->metaBundles->getGlobalMetaBundle($siteIdToLoad);
699
        Seomatic::$previewingMetaContainers = false;
700
        if ($metaBundle !== null) {
701
            $variables['site'] = $metaBundle->metaSiteVars;
702
            $variables['identityImageElements'] = ImageTransformHelper::assetElementsFromIds(
703
                $variables['site']->identity->genericImageIds,
704
                $siteId
705
            );
706
            $variables['creatorImageElements'] = ImageTransformHelper::assetElementsFromIds(
707
                $variables['site']->creator->genericImageIds,
708
                $siteId
709
            );
710
        }
711
        $variables['elementType'] = Asset::class;
712
713
        // Render the template
714
        return $this->renderTemplate('seomatic/settings/site/'.$subSection, $variables);
715
    }
716
717
    /**
718
     * @return Response
719
     * @throws \yii\web\BadRequestHttpException
720
     * @throws \craft\errors\MissingComponentException
721
     */
722
    public function actionSaveSite(): Response
723
    {
724
        $this->requirePostRequest();
725
        $request = Craft::$app->getRequest();
726
        $siteId = $request->getParam('siteId');
727
        $siteSettings = $request->getParam('site');
728
729
        // Make sure the twitter handle isn't prefixed with an @
730
        if (!empty($siteSettings['twitterHandle'])) {
731
            $siteSettings['twitterHandle'] = ltrim($siteSettings['twitterHandle'], '@');
732
        }
733
        // Make sure the sameAsLinks are indexed by the handle
734
        if (!empty($siteSettings['sameAsLinks'])) {
735
            $siteSettings['sameAsLinks'] = ArrayHelper::index($siteSettings['sameAsLinks'], 'handle');
736
        }
737
        // The site settings for the appropriate meta bundle
738
        Seomatic::$previewingMetaContainers = true;
739
        $metaBundle = Seomatic::$plugin->metaBundles->getGlobalMetaBundle($siteId);
740
        Seomatic::$previewingMetaContainers = false;
741
        if ($metaBundle) {
742
            if (\is_array($siteSettings)) {
743
                if (!empty($siteSettings['identity'])) {
744
                    $settings = $siteSettings['identity'];
745
                    $this->prepEntitySettings($settings);
746
                    $metaBundle->metaSiteVars->identity->setAttributes($settings);
747
                    $siteSettings['identity'] = $metaBundle->metaSiteVars->identity;
748
                }
749
                if (!empty($siteSettings['creator'])) {
750
                    $settings = $siteSettings['creator'];
751
                    $this->prepEntitySettings($settings);
752
                    $metaBundle->metaSiteVars->creator->setAttributes($settings);
753
                    $siteSettings['creator'] = $metaBundle->metaSiteVars->creator;
754
                }
755
                if (!empty($siteSettings['additionalSitemapUrls'])) {
756
                    $siteSettings['additionalSitemapUrlsDateUpdated'] = new \DateTime;
757
                    Seomatic::$plugin->sitemaps->submitCustomSitemap($siteId);
758
                }
759
                $metaBundle->metaSiteVars->setAttributes($siteSettings);
760
            }
761
            Seomatic::$plugin->metaBundles->syncBundleWithConfig($metaBundle, true);
762
            Seomatic::$plugin->metaBundles->updateMetaBundle($metaBundle, $siteId);
763
764
            Seomatic::$plugin->clearAllCaches();
765
            Craft::$app->getSession()->setNotice(Craft::t('seomatic', 'SEOmatic site settings saved.'));
766
        }
767
768
        return $this->redirectToPostedUrl();
769
    }
770
771
    /**
772
     * Plugin settings
773
     *
774
     * @return Response The rendered result
775
     */
776
    public function actionPlugin(): Response
777
    {
778
        $variables = [];
779
        $pluginName = Seomatic::$settings->pluginName;
780
        $templateTitle = Craft::t('seomatic', 'Plugin Settings');
781
        // Asset bundle
782
        try {
783
            Seomatic::$view->registerAssetBundle(SeomaticAsset::class);
784
        } catch (InvalidConfigException $e) {
785
            Craft::error($e->getMessage(), __METHOD__);
786
        }
787
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(
788
            '@nystudio107/seomatic/assetbundles/seomatic/dist',
789
            true
0 ignored issues
show
Unused Code introduced by
The call to yii\web\AssetManager::getPublishedUrl() has too many arguments starting with true. ( Ignorable by Annotation )

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

789
        /** @scrutinizer ignore-call */ 
790
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
790
        );
791
        // Basic variables
792
        $variables['fullPageForm'] = true;
793
        $variables['docsUrl'] = self::DOCUMENTATION_URL;
794
        $variables['pluginName'] = Seomatic::$settings->pluginName;
795
        $variables['title'] = $templateTitle;
796
        $variables['docTitle'] = "{$pluginName} - {$templateTitle}";
797
        $variables['crumbs'] = [
798
            [
799
                'label' => $pluginName,
800
                'url' => UrlHelper::cpUrl('seomatic'),
801
            ],
802
            [
803
                'label' => $templateTitle,
804
                'url' => UrlHelper::cpUrl('seomatic/plugin'),
805
            ],
806
        ];
807
        $variables['selectedSubnavItem'] = 'plugin';
808
        $variables['settings'] = Seomatic::$settings;
809
810
        // Render the template
811
        return $this->renderTemplate('seomatic/settings/plugin/_edit', $variables);
812
    }
813
814
815
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $editedMetaBundle should have a doc-comment as per coding-style.
Loading history...
816
     * Tracking settings
817
     *
818
     * @param string $subSection
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
819
     * @param string $siteHandle
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
820
     * @param null $loadFromSiteHandle
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
Documentation Bug introduced by
Are you sure the doc-type for parameter $loadFromSiteHandle is correct as it would always require null to be passed?
Loading history...
821
     *
822
     * @return Response The rendered result
823
     * @throws NotFoundHttpException
824
     * @throws \yii\web\ForbiddenHttpException
825
     */
826
    public function actionTracking(string $subSection = 'gtag', string $siteHandle = null, $loadFromSiteHandle = null, $editedMetaBundle = null): Response
827
    {
828
        $variables = [];
829
        // Get the site to edit
830
        $siteId = $this->getSiteIdFromHandle($siteHandle);
831
        // Enabled sites
832
        $this->setMultiSiteVariables($siteHandle, $siteId, $variables);
833
        $variables['controllerHandle'] = 'tracking'.'/'.$subSection;
834
        $variables['currentSubSection'] = $subSection;
835
836
        // The script meta containers for the global meta bundle
837
        Seomatic::$previewingMetaContainers = true;
838
        // Get the site to copy the settings from, if any
839
        $variables['loadFromSiteHandle'] = $loadFromSiteHandle;
840
        $loadFromSiteId = $this->getSiteIdFromHandle($loadFromSiteHandle);
841
        $siteIdToLoad = $loadFromSiteHandle === null ? (int)$variables['currentSiteId'] : $loadFromSiteId;
0 ignored issues
show
introduced by
The condition $loadFromSiteHandle === null is always true.
Loading history...
842
        // Load the metabundle
843
        $metaBundle = Seomatic::$plugin->metaBundles->getGlobalMetaBundle($siteIdToLoad);
844
        if ($editedMetaBundle) {
845
            $metaBundle = $editedMetaBundle;
846
        }
847
        Seomatic::$previewingMetaContainers = false;
848
        if ($metaBundle !== null) {
849
            $variables['scripts'] = Seomatic::$plugin->metaBundles->getContainerDataFromBundle(
850
                $metaBundle,
851
                MetaScriptContainer::CONTAINER_TYPE
852
            );
853
        }
854
        // Plugin and section settings
855
        $pluginName = Seomatic::$settings->pluginName;
856
        $templateTitle = Craft::t('seomatic', 'Tracking Scripts');
857
        $subSectionTitle = $variables['scripts'][$subSection]->name;
858
        $subSectionTitle = Craft::t('seomatic', $subSectionTitle);
859
        // Asset bundle
860
        try {
861
            Seomatic::$view->registerAssetBundle(SeomaticAsset::class);
862
        } catch (InvalidConfigException $e) {
863
            Craft::error($e->getMessage(), __METHOD__);
864
        }
865
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(
866
            '@nystudio107/seomatic/assetbundles/seomatic/dist',
867
            true
0 ignored issues
show
Unused Code introduced by
The call to yii\web\AssetManager::getPublishedUrl() has too many arguments starting with true. ( Ignorable by Annotation )

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

867
        /** @scrutinizer ignore-call */ 
868
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
868
        );
869
        // Basic variables
870
        $variables['fullPageForm'] = true;
871
        $variables['docsUrl'] = self::DOCUMENTATION_URL;
872
        $variables['pluginName'] = Seomatic::$settings->pluginName;
873
        $variables['title'] = $templateTitle;
874
        $variables['subSectionTitle'] = $subSectionTitle;
875
        $variables['docTitle'] = "{$pluginName} - {$templateTitle} - {$subSectionTitle}";
876
        $siteHandleUri = Craft::$app->isMultiSite ? '/'.$siteHandle : '';
877
        $variables['crumbs'] = [
878
            [
879
                'label' => $pluginName,
880
                'url' => UrlHelper::cpUrl('seomatic'),
881
            ],
882
            [
883
                'label' => $templateTitle,
884
                'url' => UrlHelper::cpUrl('seomatic/tracking'),
885
            ],
886
            [
887
                'label' => $subSectionTitle,
888
                'url' => UrlHelper::cpUrl('seomatic/tracking/'.$subSection.$siteHandleUri),
889
            ],
890
        ];
891
        $variables['selectedSubnavItem'] = 'tracking';
892
893
        // Render the template
894
        return $this->renderTemplate('seomatic/settings/tracking/_edit', $variables);
895
    }
896
897
    /**
898
     * @return Response
899
     * @throws \yii\web\BadRequestHttpException
900
     * @throws \craft\errors\MissingComponentException
901
     */
902
    public function actionSaveTracking()
903
    {
904
        $this->requirePostRequest();
905
        $request = Craft::$app->getRequest();
906
        $siteId = $request->getParam('siteId');
907
        $scriptSettings = $request->getParam('scripts');
908
909
        // The site settings for the appropriate meta bundle
910
        Seomatic::$previewingMetaContainers = true;
911
        $metaBundle = Seomatic::$plugin->metaBundles->getGlobalMetaBundle($siteId);
912
        Seomatic::$previewingMetaContainers = false;
913
        $hasErrors = false;
914
        if ($metaBundle) {
915
            /** @var array $scriptSettings */
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...
916
            foreach ($scriptSettings as $scriptHandle => $scriptData) {
917
                foreach ($metaBundle->metaContainers as $metaContainer) {
918
                    if ($metaContainer::CONTAINER_TYPE === MetaScriptContainer::CONTAINER_TYPE) {
919
                        $data = $metaContainer->getData($scriptHandle);
920
                        /** @var MetaScript $data */
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...
921
                        if ($data) {
922
                            /** @var array $scriptData */
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...
923
                            foreach ($scriptData as $key => $value) {
924
                                if (\is_array($value)) {
925
                                    foreach ($value as $varsKey => $varsValue) {
926
                                        $data->$key[$varsKey]['value'] = $varsValue;
927
                                    }
928
                                } else {
929
                                    $data->$key = $value;
930
                                }
931
                            }
932
                            if (!$data->validate()) {
933
                                $hasErrors = true;
934
                            }
935
                        }
936
                    }
937
                }
938
            }
939
            if ($hasErrors) {
940
                Craft::$app->getSession()->setError(Craft::t('app', "Couldn't save tracking settings due to a Twig error."));
941
                // Send the redirect back to the template
942
                Craft::$app->getUrlManager()->setRouteParams([
943
                    'editedMetaBundle' => $metaBundle,
944
                ]);
945
946
                return null;
947
            }
948
949
            Seomatic::$plugin->metaBundles->updateMetaBundle($metaBundle, $siteId);
950
951
            Seomatic::$plugin->clearAllCaches();
952
            Craft::$app->getSession()->setNotice(Craft::t('seomatic', 'SEOmatic site settings saved.'));
953
        }
954
955
        return $this->redirectToPostedUrl();
956
    }
957
958
    /**
959
     * Saves a plugin’s settings.
960
     *
961
     * @return Response|null
962
     * @throws NotFoundHttpException if the requested plugin cannot be found
963
     * @throws \yii\web\BadRequestHttpException
964
     * @throws \craft\errors\MissingComponentException
965
     */
966
    public function actionSavePluginSettings()
967
    {
968
        $this->requirePostRequest();
969
        $pluginHandle = Craft::$app->getRequest()->getRequiredBodyParam('pluginHandle');
970
        $settings = Craft::$app->getRequest()->getBodyParam('settings', []);
971
        $plugin = Craft::$app->getPlugins()->getPlugin($pluginHandle);
972
973
        if ($plugin === null) {
974
            throw new NotFoundHttpException('Plugin not found');
975
        }
976
977
        if (!Craft::$app->getPlugins()->savePluginSettings($plugin, $settings)) {
978
            Craft::$app->getSession()->setError(Craft::t('app', "Couldn't save plugin settings."));
979
980
            // Send the plugin back to the template
981
            Craft::$app->getUrlManager()->setRouteParams([
982
                'plugin' => $plugin,
983
            ]);
984
985
            return null;
986
        }
987
988
        Seomatic::$plugin->clearAllCaches();
989
        Craft::$app->getSession()->setNotice(Craft::t('app', 'Plugin settings saved.'));
990
991
        return $this->redirectToPostedUrl();
992
    }
993
994
    // Protected Methods
995
    // =========================================================================
996
997
    /**
998
     * @param array $variables
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
999
     */
1000
    protected function setGlobalFieldSourceVariables(array &$variables)
1001
    {
1002
        $variables['textFieldSources'] = array_merge(
1003
            ['globalsGroup' => ['optgroup' => 'Globals Fields']],
1004
            FieldHelper::fieldsOfTypeFromGlobals(
1005
                FieldHelper::TEXT_FIELD_CLASS_KEY,
1006
                false
1007
            )
1008
        );
1009
        $variables['assetFieldSources'] = array_merge(
1010
            ['globalsGroup' => ['optgroup' => 'Globals Fields']],
1011
            FieldHelper::fieldsOfTypeFromGlobals(
1012
                FieldHelper::ASSET_FIELD_CLASS_KEY,
1013
                false
1014
            )
1015
        );
1016
    }
1017
1018
    /**
1019
     * @param string $sourceBundleType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
1020
     * @param string $sourceHandle
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
1021
     * @param string $groupName
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
1022
     * @param array  $variables
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
1023
     */
1024
    protected function setContentFieldSourceVariables(
1025
        string $sourceBundleType,
1026
        string $sourceHandle,
1027
        string $groupName,
1028
        array &$variables
1029
    ) {
1030
        $variables['textFieldSources'] = array_merge(
1031
            ['entryGroup' => ['optgroup' => $groupName.' Fields'], 'title' => 'Title'],
1032
            FieldHelper::fieldsOfTypeFromSource(
1033
                $sourceBundleType,
1034
                $sourceHandle,
1035
                FieldHelper::TEXT_FIELD_CLASS_KEY,
1036
                false
1037
            )
1038
        );
1039
        $variables['assetFieldSources'] = array_merge(
1040
            ['entryGroup' => ['optgroup' => $groupName.' Fields']],
1041
            FieldHelper::fieldsOfTypeFromSource(
1042
                $sourceBundleType,
1043
                $sourceHandle,
1044
                FieldHelper::ASSET_FIELD_CLASS_KEY,
1045
                false
1046
            )
1047
        );
1048
        $variables['assetVolumeTextFieldSources'] = array_merge(
1049
            ['entryGroup' => ['optgroup' => 'Asset Volume Fields'], '' => '--', 'title' => 'Title'],
1050
            array_merge(
1051
                FieldHelper::fieldsOfTypeFromAssetVolumes(
1052
                    FieldHelper::TEXT_FIELD_CLASS_KEY,
1053
                    false
1054
                )
1055
            )
1056
        );
1057
        $variables['userFieldSources'] = array_merge(
1058
            ['entryGroup' => ['optgroup' => 'User Fields']],
1059
            FieldHelper::fieldsOfTypeFromUsers(
1060
                FieldHelper::TEXT_FIELD_CLASS_KEY,
1061
                false
1062
            )
1063
        );
1064
    }
1065
1066
    /**
1067
     * @param string   $sourceBundleType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
1068
     * @param string   $sourceHandle
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
1069
     * @param null|int $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
1070
     *
1071
     * @return string
1072
     */
1073
    protected function uriFromSourceBundle(string $sourceBundleType, string $sourceHandle, $siteId): string
1074
    {
1075
        $uri = null;
1076
        // Pick an Element to be used for the preview
1077
        if ($sourceBundleType === MetaBundles::GLOBAL_META_BUNDLE) {
1078
            $uri = MetaBundles::GLOBAL_META_BUNDLE;
1079
        } else {
1080
            $seoElement = Seomatic::$plugin->seoElements->getSeoElementByMetaBundleType($sourceBundleType);
1081
            if ($seoElement !== null) {
1082
                $uri = $seoElement::previewUri($sourceHandle, $siteId);
1083
            }
1084
        }
1085
        // Special-case for the __home__ slug, and default to /
1086
        if (($uri === '__home__') || ($uri === null)) {
1087
            $uri = '/';
1088
        }
1089
1090
        return $uri;
1091
    }
1092
1093
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $element should have a doc-comment as per coding-style.
Loading history...
1094
     * @param string $siteHandle
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
1095
     * @param        $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
1096
     * @param        $variables
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
1097
     *
1098
     * @throws \yii\web\ForbiddenHttpException
1099
     */
1100
    protected function setMultiSiteVariables($siteHandle, &$siteId, array &$variables, $element = null)
0 ignored issues
show
Unused Code introduced by
The parameter $element is not used and could be removed. ( Ignorable by Annotation )

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

1100
    protected function setMultiSiteVariables($siteHandle, &$siteId, array &$variables, /** @scrutinizer ignore-unused */ $element = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1101
    {
1102
        // Enabled sites
1103
        $sites = Craft::$app->getSites();
1104
        if (Craft::$app->getIsMultiSite()) {
1105
            // Set defaults based on the section settings
1106
            $variables['enabledSiteIds'] = [];
1107
            $variables['siteIds'] = [];
1108
1109
            /** @var Site $site */
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...
1110
            foreach ($sites->getEditableSiteIds() as $editableSiteId) {
1111
                $variables['enabledSiteIds'][] = $editableSiteId;
1112
                $variables['siteIds'][] = $editableSiteId;
1113
            }
1114
1115
            // Make sure the $siteId they are trying to edit is in our array of editable sites
1116
            if (!\in_array($siteId, $variables['enabledSiteIds'], false)) {
1117
                if (!empty($variables['enabledSiteIds'])) {
1118
                    $siteId = reset($variables['enabledSiteIds']);
1119
                } else {
1120
                    $this->requirePermission('editSite:'.$siteId);
1121
                }
1122
            }
1123
        }
1124
1125
        // Set the currentSiteId and currentSiteHandle
1126
        $variables['currentSiteId'] = empty($siteId) ? Craft::$app->getSites()->currentSite->id : $siteId;
1127
        $variables['currentSiteHandle'] = empty($siteHandle)
1128
            ? Craft::$app->getSites()->currentSite->handle
1129
            : $siteHandle;
1130
1131
        // Page title
1132
        $variables['showSites'] = (
1133
            Craft::$app->getIsMultiSite() &&
1134
            \count($variables['enabledSiteIds'])
1135
        );
1136
1137
        if ($variables['showSites']) {
1138
            $variables['sitesMenuLabel'] = Craft::t(
1139
                'site',
1140
                $sites->getSiteById((int)$variables['currentSiteId'])->name
1141
            );
1142
        } else {
1143
            $variables['sitesMenuLabel'] = '';
1144
        }
1145
    }
1146
1147
    /**
1148
     * Remove any sites for which meta bundles do not exist (they may be
1149
     * disabled for this section)
1150
     *
1151
     * @param string $sourceBundleType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
1152
     * @param string $sourceHandle
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
1153
     * @param array  $variables
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
1154
     */
1155
    protected function cullDisabledSites(string $sourceBundleType, string $sourceHandle, array &$variables)
1156
    {
1157
        if (isset($variables['enabledSiteIds'])) {
1158
            foreach ($variables['enabledSiteIds'] as $key => $value) {
1159
                $metaBundle = Seomatic::$plugin->metaBundles->getMetaBundleBySourceHandle(
1160
                    $sourceBundleType,
1161
                    $sourceHandle,
1162
                    $value
1163
                );
1164
                if ($metaBundle === null) {
1165
                    unset($variables['enabledSiteIds'][$key]);
1166
                }
1167
            }
1168
        }
1169
    }
1170
1171
    /**
1172
     * Return a siteId from a siteHandle
1173
     *
1174
     * @param string $siteHandle
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
1175
     *
1176
     * @return int|null
1177
     * @throws NotFoundHttpException
1178
     */
1179
    protected function getSiteIdFromHandle($siteHandle)
1180
    {
1181
        // Get the site to edit
1182
        if ($siteHandle !== null) {
0 ignored issues
show
introduced by
The condition $siteHandle !== null is always true.
Loading history...
1183
            $site = Craft::$app->getSites()->getSiteByHandle($siteHandle);
1184
            if (!$site) {
1185
                throw new NotFoundHttpException('Invalid site handle: '.$siteHandle);
1186
            }
1187
            $siteId = $site->id;
1188
        } else {
1189
            $siteId = Craft::$app->getSites()->currentSite->id;
1190
        }
1191
1192
        return $siteId;
1193
    }
1194
1195
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $settings should have a doc-comment as per coding-style.
Loading history...
1196
     * Prep the entity settings for saving to the db
1197
     *
1198
     * @param array &$settings
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter &$settings does not match actual variable name $settings
Loading history...
1199
     */
1200
    protected function prepEntitySettings(&$settings)
1201
    {
1202
        DynamicMetaHelper::normalizeTimes($settings['localBusinessOpeningHours']);
1203
        if (!empty($settings['siteType'])) {
1204
            $settings['computedType'] = SchemaHelper::getSpecificEntityType($settings);
1205
        } else {
1206
            $settings['computedType'] = 'WebPage';
1207
        }
1208
        // Empty out the entity image settings to ensure the image gets removed if it no longer exists
1209
        $settings['genericImage'] = '';
1210
        $settings['genericImageWidth'] = '';
1211
        $settings['genericImageHeight'] = '';
1212
        if (!empty($settings['genericImageIds'])) {
1213
            $asset = Craft::$app->getAssets()->getAssetById($settings['genericImageIds'][0]);
1214
            if ($asset !== null) {
1215
                $settings['genericImage'] = $asset->getUrl();
1216
                $settings['genericImageWidth'] = $asset->getWidth();
1217
                $settings['genericImageHeight'] = $asset->getHeight();
1218
            }
1219
        }
1220
    }
1221
}
1222