Issues (257)

src/models/SitemapTemplate.php (1 issue)

Labels
Severity
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\console\Application as ConsoleApplication;
16
use nystudio107\fastcgicachebust\FastcgiCacheBust;
17
use nystudio107\seomatic\base\FrontendTemplate;
18
use nystudio107\seomatic\base\SitemapInterface;
19
use nystudio107\seomatic\helpers\SiteHelper;
20
use nystudio107\seomatic\helpers\Sitemap;
21
use nystudio107\seomatic\Seomatic;
22
use yii\caching\TagDependency;
23
use yii\web\NotFoundHttpException;
24
25
/**
26
 * @author    nystudio107
27
 * @package   Seomatic
28
 * @since     3.0.0
29
 */
30
class SitemapTemplate extends FrontendTemplate implements SitemapInterface
31
{
32
    // Constants
33
    // =========================================================================
34
35
    public const TEMPLATE_TYPE = 'SitemapTemplate';
36
37
    public const CACHE_KEY = 'seomatic_sitemap_';
38
39
    public const QUEUE_JOB_CACHE_KEY = 'seomatic_sitemap_queue_job_';
40
41
    public const SITEMAP_CACHE_TAG = 'seomatic_sitemap_';
42
43
    public const FILE_TYPES = [
44
        'excel',
45
        'pdf',
46
        'illustrator',
47
        'powerpoint',
48
        'text',
49
        'word',
50
        'xml',
51
    ];
52
53
    // Static Methods
54
    // =========================================================================
55
56
    /**
57
     * @param array $config
58
     *
59
     * @return null|SitemapTemplate
60
     */
61
    public static function create(array $config = [])
62
    {
63
        $defaults = [
64
            'path' => 'sitemaps-<groupId:\d+>-<type:[\w\.*]+>-<handle:[\w\.*]+>-<siteId:\d+>-<file:[-\w\.*]+>',
65
            'template' => '',
66
            'controller' => 'sitemap',
67
            'action' => 'sitemap',
68
        ];
69
        $config = array_merge($config, $defaults);
70
71
        return new SitemapTemplate($config);
72
    }
73
74
    // Public Properties
75
    // =========================================================================
76
77
    // Public Methods
78
    // =========================================================================
79
80
    /**
81
     * @inheritdoc
82
     */
83
    public function rules(): array
84
    {
85
        $rules = parent::rules();
86
        $rules = array_merge($rules, [
87
        ]);
88
89
        return $rules;
90
    }
91
92
    /**
93
     * @inheritdoc
94
     */
95
    public function fields(): array
96
    {
97
        return parent::fields();
98
    }
99
100
    /**
101
     * @inheritdoc
102
     */
103
    public function render(array $params = []): string
104
    {
105
        $groupId = $params['groupId'];
106
        $type = $params['type'];
107
        $handle = $params['handle'];
108
        $siteId = $params['siteId'];
109
        $page = $params['page'] ?? 0;
110
111
        $request = Craft::$app->getRequest();
112
        $metaBundle = Seomatic::$plugin->metaBundles->getMetaBundleBySourceHandle($type, $handle, $siteId);
113
        // If it doesn't exist, throw a 404
114
        if ($metaBundle === null) {
115
            if ($request->isCpRequest || $request->isConsoleRequest) {
116
                return '';
117
            }
118
            throw new NotFoundHttpException(Craft::t('seomatic', 'Page not found.'));
119
        }
120
        // Check to see if robots is `none` or `no index`
121
        $robotsEnabled = true;
122
        if (!empty($metaBundle->metaGlobalVars->robots)) {
123
            $robotsEnabled = $metaBundle->metaGlobalVars->robots !== 'none' &&
124
                $metaBundle->metaGlobalVars->robots !== 'noindex';
125
        }
126
        $sitemapUrls = $metaBundle->metaSitemapVars->sitemapUrls;
127
        if (Seomatic::$plugin->sitemaps->anyEntryTypeHasSitemapUrls($metaBundle)) {
128
            $robotsEnabled = true;
129
            $sitemapUrls = true;
130
        }
131
        if ($sitemapUrls && !SiteHelper::siteEnabledWithUrls($siteId)) {
132
            $sitemapUrls = false;
133
        }
134
        // If it's disabled, just throw a 404
135
        if (!$sitemapUrls || !$robotsEnabled) {
136
            if ($request->isCpRequest || $request->isConsoleRequest) {
137
                return '';
138
            }
139
            throw new NotFoundHttpException(Craft::t('seomatic', 'Page not found.'));
140
        }
141
142
        $cache = Craft::$app->getCache();
143
        $pageCacheSuffix = 's' . (int)$metaBundle->metaSitemapVars->sitemapPageSize . 'p' . $page;
144
145
        $uniqueKey = $groupId . $type . $handle . $siteId . $pageCacheSuffix;
146
        $cacheKey = self::CACHE_KEY . $uniqueKey;
147
        $result = $cache->get($cacheKey);
148
149
        // If the sitemap isn't cached, render it immediately
150
        if ($result === false) {
151
            $sitemap = Sitemap::generateSitemap([
152
                'groupId' => $groupId,
153
                'type' => $type,
154
                'handle' => $handle,
155
                'siteId' => $siteId,
156
                'page' => $page,
157
            ]);
158
159
            if ($sitemap) {
160
                $dependency = new TagDependency([
161
                    'tags' => [
162
                        self::GLOBAL_SITEMAP_CACHE_TAG,
163
                        self::SITEMAP_CACHE_TAG . $handle . $siteId,
164
                        self::SITEMAP_CACHE_TAG . $handle . $siteId . $pageCacheSuffix,
165
                    ],
166
                ]);
167
168
                $cacheDuration = Seomatic::$devMode
169
                    ? Seomatic::DEVMODE_CACHE_DURATION
170
                    : null;
171
172
                $result = $cache->set($cacheKey, $sitemap, $cacheDuration, $dependency);
173
174
                // Output some info if this is a console app
175
                if (Craft::$app instanceof ConsoleApplication) {
176
                    echo 'Sitemap cache result: ' . print_r($result, true) . ' for cache key: ' . $cacheKey . PHP_EOL;
0 ignored issues
show
Are you sure print_r($result, true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

176
                    echo 'Sitemap cache result: ' . /** @scrutinizer ignore-type */ print_r($result, true) . ' for cache key: ' . $cacheKey . PHP_EOL;
Loading history...
177
                }
178
179
                // If the FastCGI Cache Bust plugin is installed, clear its caches too
180
                /** @var FastcgiCacheBust $plugin */
181
                $plugin = Craft::$app->getPlugins()->getPlugin('fastcgi-cache-bust');
182
                if ($plugin !== null) {
183
                    $plugin->cache->clearAll();
184
                }
185
186
                return $sitemap;
187
            }
188
        } else {
189
            if (Craft::$app instanceof ConsoleApplication) {
190
                echo 'Found in cache' . PHP_EOL;
191
            }
192
        }
193
194
        return $result;
195
    }
196
197
    /**
198
     * Invalidate a sitemap cache
199
     *
200
     * @param string $handle
201
     * @param int $siteId
202
     */
203
    public function invalidateCache(string $handle, int $siteId)
204
    {
205
        $cache = Craft::$app->getCache();
206
        TagDependency::invalidate($cache, self::SITEMAP_CACHE_TAG . $handle . $siteId);
207
        Craft::info(
208
            'Sitemap cache cleared: ' . $handle,
209
            __METHOD__
210
        );
211
    }
212
}
213