Routes   F
last analyzed

Complexity

Total Complexity 67

Size/Duplication

Total Lines 583
Duplicated Lines 0 %

Importance

Changes 13
Bugs 1 Features 0
Metric Value
eloc 214
c 13
b 1
f 0
dl 0
loc 583
rs 3.04
wmc 67

17 Methods

Rating   Name   Duplication   Size   Complexity  
A getSectionUrls() 0 8 1
A getDbRoutes() 0 3 1
A normalizeFormat() 0 24 4
B getElementUrls() 0 46 7
A getAllRouteRules() 0 11 1
A invalidateCache() 0 7 1
B getCategoryRouteRules() 0 62 11
C getUrlAssetUrls() 0 65 13
A getAllSectionRouteRules() 0 13 3
A normalizeUri() 0 8 2
A getAllUrls() 0 11 2
A getCategoryUrls() 0 7 1
B getCacheKey() 0 21 7
A getRouteRules() 0 10 1
B getSectionRouteRules() 0 50 8
A getElementQuery() 0 6 1
A getAllCategoryRouteRules() 0 13 3

How to fix   Complexity   

Complex Class

Complex classes like Routes often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Routes, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Route Map plugin for Craft CMS
4
 *
5
 * Returns a list of public routes for elements with URLs
6
 *
7
 * @link      https://nystudio107.com/
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @copyright tag
Loading history...
8
 * @copyright Copyright (c) 2017 nystudio107
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
9
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
Coding Style introduced by
Missing @package tag in file comment
Loading history...
Coding Style introduced by
Missing @author tag in file comment
Loading history...
Coding Style introduced by
Missing @license tag in file comment
Loading history...
10
11
namespace nystudio107\routemap\services;
12
13
use Craft;
14
use craft\base\Component;
15
use craft\base\Element;
16
use craft\base\ElementInterface;
0 ignored issues
show
Bug introduced by
The type craft\base\ElementInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
use craft\elements\Asset;
0 ignored issues
show
Bug introduced by
The type craft\elements\Asset was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
use craft\elements\Category;
19
use craft\elements\db\ElementQueryInterface;
20
use craft\elements\Entry;
21
use craft\fields\Assets as AssetsField;
22
use craft\fields\Matrix as MatrixField;
23
use nystudio107\routemap\helpers\Field as FieldHelper;
24
use yii\caching\TagDependency;
25
use function count;
26
use function in_array;
27
use function is_array;
28
use function is_int;
29
use function is_object;
30
use function is_string;
31
32
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
33
 * @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...
Coding Style introduced by
Tag value for @author tag indented incorrectly; expected 2 spaces but found 4
Loading history...
34
 * @package   RouteMap
0 ignored issues
show
Coding Style introduced by
Tag value for @package tag indented incorrectly; expected 1 spaces but found 3
Loading history...
35
 * @since     1.0.0
0 ignored issues
show
Coding Style introduced by
The tag in position 3 should be the @author tag
Loading history...
Coding Style introduced by
Tag value for @since tag indented incorrectly; expected 3 spaces but found 5
Loading history...
36
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
37
class Routes extends Component
38
{
39
    // Constants
40
    // =========================================================================
41
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
42
     * @var string
43
     */
44
    public const ROUTE_FORMAT_CRAFT = 'Craft';
45
46
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
47
     * @var string
48
     */
49
    public const ROUTE_FORMAT_REACT = 'React';
50
51
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
52
     * @var string
53
     */
54
    public const ROUTE_FORMAT_VUE = 'Vue';
55
56
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
57
     * @var null
58
     */
59
    public const ROUTEMAP_CACHE_DURATION = null;
60
61
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
62
     * @var int
63
     */
64
    public const DEVMODE_ROUTEMAP_CACHE_DURATION = 30;
65
66
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
67
     * @var string
68
     */
69
    public const ROUTEMAP_CACHE_TAG = 'RouteMap';
70
71
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
72
     * @var string
73
     */
74
    public const ROUTEMAP_SECTION_RULES = 'Sections';
75
76
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
77
     * @var string
78
     */
79
    public const ROUTEMAP_CATEGORY_RULES = 'Categories';
80
81
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
82
     * @var string
83
     */
84
    public const ROUTEMAP_ELEMENT_URLS = 'ElementUrls';
85
86
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
87
     * @var string
88
     */
89
    public const ROUTEMAP_ASSET_URLS = 'AssetUrls';
90
91
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
92
     * @var string
93
     */
94
    public const ROUTEMAP_ALL_URLS = 'AllUrls';
95
96
    // Public Methods
97
    // =========================================================================
98
    /**
99
     * Return the public URLs for all elements that have URLs
100
     *
101
     * @param array $criteria
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
102
     * @param ?int $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
103
     * @return array
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
104
     */
105
    public function getAllUrls(array $criteria = [], ?int $siteId = null): array
106
    {
107
        $urls = [];
108
        $elements = Craft::$app->getElements();
109
        $elementTypes = $elements->getAllElementTypes();
110
        foreach ($elementTypes as $elementType) {
111
            /** @noinspection SlowArrayOperationsInLoopInspection */
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
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
112
            $urls = array_merge($urls, $this->getElementUrls($elementType, $criteria, $siteId));
113
        }
114
115
        return $urls;
116
    }
117
118
    /**
119
     * Return all the section route rules
120
     *
121
     * @param string $format 'Craft'|'React'|'Vue'
0 ignored issues
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
122
     * @param ?int $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
123
     * @return array
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
124
     */
125
    public function getAllRouteRules(string $format = 'Craft', ?int $siteId = null): array
126
    {
127
        // Get all the sections
128
        $sections = $this->getAllSectionRouteRules($format, $siteId);
129
        $categories = $this->getAllCategoryRouteRules($format, $siteId);
130
        $rules = $this->getRouteRules($siteId);
131
132
        return [
133
            'sections' => $sections,
134
            'categories' => $categories,
135
            'rules' => $rules,
136
        ];
137
    }
138
139
    /**
140
     * Return the public URLs for a section
141
     *
142
     * @param string $section
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
143
     * @param array $criteria
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
144
     * @param ?int $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
145
     * @return array
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
146
     */
147
    public function getSectionUrls(string $section, array $criteria = [], ?int $siteId = null): array
148
    {
149
        $criteria = array_merge([
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
150
            'section' => $section,
151
            'status' => 'enabled',
152
        ], $criteria);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
153
154
        return $this->getElementUrls(Entry::class, $criteria, $siteId);
155
    }
156
157
    /**
158
     * Return all the section route rules
159
     *
160
     * @param string $format 'Craft'|'React'|'Vue'
0 ignored issues
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
161
     * @param ?int $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
162
     * @return array
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
163
     */
164
    public function getAllSectionRouteRules(string $format = 'Craft', ?int $siteId = null): array
165
    {
166
        $routeRules = [];
167
        // Get all the sections
168
        $sections = Craft::$app->getEntries()->getAllSections();
169
        foreach ($sections as $section) {
170
            $routes = $this->getSectionRouteRules($section->handle, $format, $siteId);
171
            if (!empty($routes)) {
172
                $routeRules[$section->handle] = $routes;
173
            }
174
        }
175
176
        return $routeRules;
177
    }
178
179
    /**
180
     * Return the route rules for a specific section
181
     *
182
     * @param string $section
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
183
     * @param string $format 'Craft'|'React'|'Vue'
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
184
     * @param ?int $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
185
     * @return array
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
186
     */
187
    public function getSectionRouteRules(string $section, string $format = 'Craft', ?int $siteId = null): array
188
    {
189
        $devMode = Craft::$app->getConfig()->getGeneral()->devMode;
190
        $cache = Craft::$app->getCache();
191
192
        // Set up our cache criteria
193
        $cacheKey = $this->getCacheKey($this::ROUTEMAP_SECTION_RULES, [$section, $format, $siteId]);
194
        $duration = $devMode ? $this::DEVMODE_ROUTEMAP_CACHE_DURATION : $this::ROUTEMAP_CACHE_DURATION;
195
        $dependency = new TagDependency([
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
196
            'tags' => [
197
                $this::ROUTEMAP_CACHE_TAG,
198
            ],
199
        ]);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
200
201
        // Just return the data if it's already cached
202
        return $cache->getOrSet($cacheKey, function() use ($section, $format, $siteId): array {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
203
            Craft::info(
204
                'Route Map cache miss: ' . $section,
205
                __METHOD__
206
            );
207
            $resultingRoutes = [];
208
209
            $section = Craft::$app->getEntries()->getSectionByHandle($section);
210
            if ($section) {
211
                $sites = $section->getSiteSettings();
212
213
                foreach ($sites as $site) {
214
                    if ($site->hasUrls && ($siteId === null || (int)$site->siteId === $siteId)) {
215
                        // Get section data to return
216
                        $route = [
217
                            'handle' => $section->handle,
218
                            'siteId' => $site->siteId,
219
                            'type' => $section->type,
220
                            'url' => $site->uriFormat,
221
                            'template' => $site->template,
222
                        ];
223
224
                        // Normalize the routes based on the format
225
                        $resultingRoutes[$site->siteId] = $this->normalizeFormat($format, $route);
226
                    }
227
                }
228
            }
229
230
            // If there's only one siteId for this section, just return it
231
            if (count($resultingRoutes) === 1) {
232
                $resultingRoutes = reset($resultingRoutes);
233
            }
234
235
            return $resultingRoutes;
236
        }, $duration, $dependency);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
237
    }
238
239
    /**
240
     * Return the public URLs for a category
241
     *
242
     * @param string $category
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
243
     * @param array $criteria
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
244
     * @param ?int $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
245
     *
246
     * @return array
247
     */
248
    public function getCategoryUrls(string $category, array $criteria = [], ?int $siteId = null): array
249
    {
250
        $criteria = array_merge([
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
251
            'group' => $category,
252
        ], $criteria);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
253
254
        return $this->getElementUrls(Category::class, $criteria, $siteId);
255
    }
256
257
    /**
258
     * Return all the cateogry group route rules
259
     *
260
     * @param string $format 'Craft'|'React'|'Vue'
0 ignored issues
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
261
     * @param ?int $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
262
     * @return array
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
263
     */
264
    public function getAllCategoryRouteRules(string $format = 'Craft', ?int $siteId = null): array
265
    {
266
        $routeRules = [];
267
        // Get all the sections
268
        $groups = Craft::$app->getCategories()->getAllGroups();
269
        foreach ($groups as $group) {
270
            $routes = $this->getCategoryRouteRules($group->handle, $format, $siteId);
271
            if (!empty($routes)) {
272
                $routeRules[$group->handle] = $routes;
273
            }
274
        }
275
276
        return $routeRules;
277
    }
278
279
    /**
280
     * Return the route rules for a specific category
281
     *
282
     * @param int|string $category
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
283
     * @param string $format 'Craft'|'React'|'Vue'
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
284
     * @param ?int $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 7 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
285
     * @return array
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
286
     */
287
    public function getCategoryRouteRules(int|string $category, string $format = 'Craft', ?int $siteId = null): array
288
    {
289
        $devMode = Craft::$app->getConfig()->getGeneral()->devMode;
290
        $cache = Craft::$app->getCache();
291
292
        if (is_int($category)) {
293
            $categoryGroup = Craft::$app->getCategories()->getGroupById($category);
294
            if ($categoryGroup === null) {
295
                return [];
296
            }
297
298
            $handle = $categoryGroup->handle;
299
        } else {
300
            $handle = $category;
301
        }
302
303
        if ($handle === null) {
304
            return [];
305
        }
306
307
        // Set up our cache criteria
308
        $cacheKey = $this->getCacheKey($this::ROUTEMAP_CATEGORY_RULES, [$category, $handle, $format, $siteId]);
309
        $duration = $devMode ? $this::DEVMODE_ROUTEMAP_CACHE_DURATION : $this::ROUTEMAP_CACHE_DURATION;
310
        $dependency = new TagDependency([
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
311
            'tags' => [
312
                $this::ROUTEMAP_CACHE_TAG,
313
            ],
314
        ]);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
315
        // Just return the data if it's already cached
316
        return $cache->getOrSet($cacheKey, function() use ($category, $handle, $format, $siteId): array {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
317
            Craft::info(
318
                'Route Map cache miss: ' . $category,
319
                __METHOD__
320
            );
321
            $resultingRoutes = [];
322
            $category = Craft::$app->getCategories()->getGroupByHandle($handle);
323
            if ($category) {
324
                $sites = $category->getSiteSettings();
325
326
                foreach ($sites as $site) {
327
                    if ($site->hasUrls && ($siteId === null || (int)$site->siteId === $siteId)) {
328
                        // Get section data to return
329
                        $route = [
330
                            'handle' => $category->handle,
331
                            'siteId' => $site->siteId,
332
                            'url' => $site->uriFormat,
333
                            'template' => $site->template,
334
                        ];
335
336
                        // Normalize the routes based on the format
337
                        $resultingRoutes[$site->siteId] = $this->normalizeFormat($format, $route);
338
                    }
339
                }
340
            }
341
342
            // If there's only one siteId for this section, just return it
343
            if (count($resultingRoutes) === 1) {
344
                $resultingRoutes = reset($resultingRoutes);
345
            }
346
347
            return $resultingRoutes;
348
        }, $duration, $dependency);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
349
    }
350
351
    /**
352
     * Get all the assets of the type $assetTypes that are used in the Entry
353
     * that matches the $url
354
     *
355
     * @param string $url
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
356
     * @param array $assetTypes
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
357
     * @param ?int $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
358
     * @return array
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
359
     */
360
    public function getUrlAssetUrls(string $url, array $assetTypes = ['image'], ?int $siteId = null): array
361
    {
362
        $devMode = Craft::$app->getConfig()->getGeneral()->devMode;
363
        $cache = Craft::$app->getCache();
364
365
        // Extract a URI from the URL
366
        $uri = parse_url($url, PHP_URL_PATH);
367
        $uri = ltrim($uri, '/');
368
        // Set up our cache criteria
369
        $cacheKey = $this->getCacheKey($this::ROUTEMAP_ASSET_URLS, [$uri, $assetTypes, $siteId]);
370
        $duration = $devMode ? $this::DEVMODE_ROUTEMAP_CACHE_DURATION : $this::ROUTEMAP_CACHE_DURATION;
371
        $dependency = new TagDependency([
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
372
            'tags' => [
373
                $this::ROUTEMAP_CACHE_TAG,
374
            ],
375
        ]);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
376
377
        // Just return the data if it's already cached
378
        return $cache->getOrSet($cacheKey, function() use ($uri, $assetTypes, $siteId): array {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
379
            Craft::info(
380
                'Route Map cache miss: ' . $uri,
381
                __METHOD__
382
            );
383
            $resultingAssetUrls = [];
384
385
            // Find the element that matches this URI
386
            /** @var ?Entry $element */
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
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
387
            $element = Craft::$app->getElements()->getElementByUri($uri, $siteId, true);
388
            if ($element) {
389
                // Iterate any Assets fields for this entry
390
                $assetFields = FieldHelper::fieldsOfType($element, AssetsField::class);
391
                foreach ($assetFields as $assetField) {
392
                    /** @var Asset[] $assets */
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
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
393
                    $assets = $element[$assetField]->all();
394
                    foreach ($assets as $asset) {
395
                        /** @var $asset Asset */
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
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
396
                        if (in_array($asset->kind, $assetTypes, true)
397
                            && !in_array($asset->getUrl(), $resultingAssetUrls, true)) {
0 ignored issues
show
Coding Style introduced by
Closing parenthesis of a multi-line IF statement must be on a new line
Loading history...
398
                            $resultingAssetUrls[] = $asset->getUrl();
399
                        }
400
                    }
401
                }
402
403
                // Iterate through any Assets embedded in Matrix fields
404
                $matrixFields = FieldHelper::fieldsOfType($element, MatrixField::class);
405
                foreach ($matrixFields as $matrixField) {
406
                    /** @var Entry[] $matrixEntries */
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
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
407
                    $matrixEntries = $element[$matrixField]->all();
408
                    foreach ($matrixEntries as $matrixEntry) {
409
                        $assetFields = FieldHelper::matrixFieldsOfType($matrixEntry, AssetsField::class);
410
                        foreach ($assetFields as $assetField) {
411
                            foreach ($matrixEntry[$assetField] as $asset) {
412
                                /** @var $asset Asset */
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
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
413
                                if (in_array($asset->kind, $assetTypes, true)
414
                                    && !in_array($asset->getUrl(), $resultingAssetUrls, true)) {
0 ignored issues
show
Coding Style introduced by
Closing parenthesis of a multi-line IF statement must be on a new line
Loading history...
415
                                    $resultingAssetUrls[] = $asset->getUrl();
416
                                }
417
                            }
418
                        }
419
                    }
420
                }
421
            }
422
423
            return $resultingAssetUrls;
424
        }, $duration, $dependency);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
425
    }
426
427
    /**
428
     * Returns all the URLs for the given $elementType based on the passed in
429
     * $criteria and $siteId
430
     *
431
     * @param string|ElementInterface $elementType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
432
     * @param array $criteria
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 19 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
433
     * @param ?int $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 20 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
434
     * @return array
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
435
     */
436
    public function getElementUrls(string|ElementInterface $elementType, array $criteria = [], ?int $siteId = null): array
437
    {
438
        $devMode = Craft::$app->getConfig()->getGeneral()->devMode;
439
        $cache = Craft::$app->getCache();
440
441
        // Merge in the $criteria passed in
442
        $criteria = array_merge([
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
443
            'siteId' => $siteId,
444
            'limit' => null,
445
        ], $criteria);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
446
        // Set up our cache criteria
447
        /* @var ElementInterface $elementInterface */
448
        $elementInterface = is_object($elementType) ? $elementType : new $elementType();
449
        $cacheKey = $this->getCacheKey($this::ROUTEMAP_ELEMENT_URLS, [$elementInterface, $criteria, $siteId]);
450
        $duration = $devMode ? $this::DEVMODE_ROUTEMAP_CACHE_DURATION : $this::ROUTEMAP_CACHE_DURATION;
451
        $dependency = new TagDependency([
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
452
            'tags' => [
453
                $this::ROUTEMAP_CACHE_TAG,
454
            ],
455
        ]);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
456
457
        // Just return the data if it's already cached
458
        return $cache->getOrSet($cacheKey, function() use ($elementInterface, $criteria): array {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
459
            Craft::info(
460
                'Route Map cache miss: ' . $elementInterface::class,
461
                __METHOD__
462
            );
463
            $resultingUrls = [];
464
465
            // Get all of the entries in the section
466
            $query = $this->getElementQuery($elementInterface, $criteria);
467
            $elements = $query->all();
468
469
            // Iterate through the elements and grab their URLs
470
            foreach ($elements as $element) {
471
                if ($element instanceof Element
472
                    && $element->uri !== null
473
                    && !in_array($element->uri, $resultingUrls, true)
474
                ) {
475
                    $uri = $this->normalizeUri($element->uri);
476
                    $resultingUrls[] = $uri;
477
                }
478
            }
479
480
            return $resultingUrls;
481
        }, $duration, $dependency);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
482
    }
483
484
    /**
485
     * Invalidate the RouteMap caches
486
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
487
    public function invalidateCache(): void
488
    {
489
        $cache = Craft::$app->getCache();
490
        TagDependency::invalidate($cache, self::ROUTEMAP_CACHE_TAG);
491
        Craft::info(
492
            'Route Map cache cleared',
493
            __METHOD__
494
        );
495
    }
496
497
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $siteId should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $includeGlobal should have a doc-comment as per coding-style.
Loading history...
498
     * Get all routes rules defined in the config/routes.php file and CMS
499
     *
500
     * @return array
0 ignored issues
show
Coding Style introduced by
Tag value for @return tag indented incorrectly; expected 3 spaces but found 1
Loading history...
501
     * @property ?int $siteId
502
     *
503
     * @property bool $includeGlobal - merge global routes with the site rules
504
     */
505
    public function getRouteRules(?int $siteId = null, bool $includeGlobal = true): array
506
    {
507
        $globalRules = [];
508
509
        $siteRoutes = $this->getDbRoutes($siteId);
510
511
        return array_merge(
512
            Craft::$app->getRoutes()->getConfigFileRoutes(),
513
            $globalRules,
514
            $siteRoutes
515
        );
516
    }
517
518
    // Protected Methods
519
    // =========================================================================
520
    /**
521
     * Query the database for db routes
522
     *
523
     * @param ?int $siteId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
524
     * @return array
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
525
     */
526
    protected function getDbRoutes(?int $siteId = null): array
527
    {
528
        return Craft::$app->getRoutes()->getProjectConfigRoutes();
529
    }
530
531
    /**
532
     * Normalize the routes based on the format
533
     *
534
     * @param string $format 'Craft'|'React'|'Vue'
0 ignored issues
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
535
     * @param array $route
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
536
     * @return array
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
537
     */
538
    protected function normalizeFormat(string $format, array $route): array
539
    {
540
        // Normalize the URL
541
        $route['url'] = $this->normalizeUri($route['url']);
542
        // Transform the URLs depending on the format requested
543
        switch ($format) {
544
            // React & Vue routes have a leading / and {slug} -> :slug
545
            case $this::ROUTE_FORMAT_REACT:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
546
            case $this::ROUTE_FORMAT_VUE:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
547
                $matchRegEx = '`{(.*?)}`';
548
                $replaceRegEx = ':$1';
549
                $route['url'] = preg_replace($matchRegEx, $replaceRegEx, $route['url']);
550
                // Add a leading /
551
                $route['url'] = '/' . ltrim($route['url'], '/');
552
                break;
553
554
            // Craft-style URLs don't need to be changed
555
            case $this::ROUTE_FORMAT_CRAFT:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
556
            default:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
557
                // Do nothing
558
                break;
559
        }
560
561
        return $route;
562
    }
563
564
    /**
565
     * Normalize the URI
566
     *
567
     * @param string $url
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
568
     * @return string
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
569
     */
570
    protected function normalizeUri(string $url): string
571
    {
572
        // Handle the special '__home__' URI
573
        if ($url === '__home__') {
574
            $url = '/';
575
        }
576
577
        return $url;
578
    }
579
580
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $prefix should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $args should have a doc-comment as per coding-style.
Loading history...
581
     * Generate a cache key with the combination of the $prefix and an md5()
582
     * hashed version of the flattened $args array
583
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
584
    protected function getCacheKey(string $prefix, array $args = []): string
585
    {
586
        $cacheKey = $prefix;
587
        $flattenedArgs = '';
588
        // If an array of $args is passed in, flatten it into a concatenated string
589
        if (!empty($args)) {
590
            foreach ($args as $arg) {
591
                if ((is_object($arg) || is_array($arg)) && !empty($arg)) {
592
                    $flattenedArgs .= http_build_query($arg);
593
                }
594
595
                if (is_string($arg)) {
596
                    $flattenedArgs .= $arg;
597
                }
598
            }
599
600
            // Make an md5 hash out of it
601
            $flattenedArgs = md5($flattenedArgs);
602
        }
603
604
        return $cacheKey . $flattenedArgs;
605
    }
606
607
    /**
608
     * Returns the element query based on $elementType and $criteria
609
     *
610
     * @param array $criteria
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Doc comment for parameter $criteria does not match actual variable name $elementType
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
611
     * @param ElementInterface $elementType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $elementType does not match actual variable name $criteria
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
612
     * @return ElementQueryInterface
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
613
     */
614
    protected function getElementQuery(ElementInterface $elementType, array $criteria): ElementQueryInterface
615
    {
616
        $query = $elementType::find();
617
        Craft::configure($query, $criteria);
618
619
        return $query;
620
    }
621
}
622