Issues (257)

src/helpers/Container.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) 2019 nystudio107
10
 */
11
12
namespace nystudio107\seomatic\helpers;
13
14
use Craft;
15
use craft\base\Element;
16
use craft\errors\SiteNotFoundException;
17
use nystudio107\seomatic\helpers\ImageTransform as ImageTransformHelper;
18
use nystudio107\seomatic\Seomatic;
19
use yii\caching\TagDependency;
20
use yii\web\BadRequestHttpException;
21
22
/**
23
 * @author    nystudio107
24
 * @package   Seomatic
25
 * @since     3.2.0
26
 */
27
class Container
28
{
29
    // Constants
30
    // =========================================================================
31
32
    public const CACHE_KEY = 'seomatic_metacontroller_';
33
34
    // Static Methods
35
    // =========================================================================
36
37
    /**
38
     * Return an array of meta containers for the given array of keys
39
     *
40
     * @param array $containerKeys
41
     * @param string $uri
42
     * @param int|null $siteId
43
     * @param bool $asArray
44
     *
45
     * @return array
46
     */
47
    public static function getContainerArrays(
48
        array  $containerKeys,
49
        string $uri,
50
        int    $siteId = null,
51
        bool   $asArray = false,
52
    ): array {
53
        // Normalize the incoming URI to account for `__home__`
54
        $uri = ($uri === '__home__') ? '' : $uri;
55
        // Determine the siteId
56
        if ($siteId === null) {
57
            $siteId = Craft::$app->getSites()->currentSite->id
58
                ?? Craft::$app->getSites()->primarySite->id
59
                ?? 1;
60
        }
61
        // Set Craft's current site to the siteId we decided upon, stashing the current site first
62
        $sites = Craft::$app->getSites();
63
        $oldCurrentSite = $siteId;
0 ignored issues
show
The assignment to $oldCurrentSite is dead and can be removed.
Loading history...
64
        try {
65
            $oldCurrentSite = $sites->getCurrentSite();
66
        } catch (SiteNotFoundException $e) {
67
            Craft::error($e->getMessage(), __METHOD__);
68
        }
69
        $sites->setCurrentSite($siteId);
70
        // Trim the URI
71
        $uri = trim($uri, '/');
72
        // Add a caching layer on top of controller requests
73
        $sourceId = '';
74
        /** @var Element $element */
75
        $element = Craft::$app->getElements()->getElementByUri($uri, $siteId, false);
76
        $sourceBundleType = '';
77
        if ($element !== null) {
78
            list($sourceId, $sourceBundleType, $sourceHandle, $sourceSiteId, $typeId)
79
                = Seomatic::$plugin->metaBundles->getMetaSourceFromElement($element);
80
        }
81
        $metaContainers = Seomatic::$plugin->metaContainers;
82
        // Cache requests that have a token associated with them separately
83
        $token = '';
84
        $request = Craft::$app->getRequest();
85
        if (!$request->isConsoleRequest) {
86
            try {
87
                $token = $request->getToken() ?? '';
88
            } catch (BadRequestHttpException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
89
            }
90
        }
91
        // Get our cache key
92
        $asArrayKey = $asArray ? 'true' : 'false';
93
        $cacheKey = $uri . $siteId . implode($containerKeys) . $asArrayKey . Seomatic::$environment . $token;
94
        // Load the meta containers
95
        $dependency = new TagDependency([
96
            'tags' => [
97
                $metaContainers::GLOBAL_METACONTAINER_CACHE_TAG,
98
                $metaContainers::METACONTAINER_CACHE_TAG . $sourceId . $sourceBundleType . $siteId,
99
                $metaContainers::METACONTAINER_CACHE_TAG . $uri . $siteId,
100
                $metaContainers::METACONTAINER_CACHE_TAG . $cacheKey,
101
                $metaContainers::METACONTAINER_CACHE_TAG . $sourceId . $sourceBundleType,
102
            ],
103
        ]);
104
        $cache = Craft::$app->getCache();
105
        $result = $cache->getOrSet(
106
            self::CACHE_KEY . $cacheKey,
107
            function() use ($uri, $siteId, $containerKeys, $asArray) {
108
                $result = [];
109
                Craft::info(
110
                    'Meta controller container cache miss: ' . $uri . '/' . $siteId,
111
                    __METHOD__
112
                );
113
                // Load the meta containers and parse our globals
114
                Seomatic::$headlessRequest = true;
115
                Seomatic::$plugin->metaContainers->previewMetaContainers($uri, $siteId, true);
116
                // Iterate through the desired $containerKeys
117
                foreach ($containerKeys as $containerKey) {
118
                    if ($asArray) {
119
                        $result[$containerKey] = Seomatic::$plugin->metaContainers->renderContainersArrayByType(
120
                            $containerKey
121
                        );
122
                    } else {
123
                        $result[$containerKey] = Seomatic::$plugin->metaContainers->renderContainersByType(
124
                            $containerKey
125
                        );
126
                    }
127
                }
128
129
130
                return $result;
131
            },
132
            Seomatic::$cacheDuration,
133
            $dependency
134
        );
135
        // Restore old current site
136
        $sites->setCurrentSite($oldCurrentSite);
137
        // Invalidate the cache we just created if there were pending image transforms in it
138
        if (ImageTransformHelper::$pendingImageTransforms) {
139
            TagDependency::invalidate($cache, $dependency->tags[3]);
140
        }
141
142
        return $result;
143
    }
144
}
145