1 | <?php |
||||||||||
2 | /** |
||||||||||
3 | * SEOmatic plugin for Craft CMS 3.x |
||||||||||
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\gql\resolvers; |
||||||||||
13 | |||||||||||
14 | use Craft; |
||||||||||
15 | use GraphQL\Type\Definition\ResolveInfo; |
||||||||||
16 | use nystudio107\seomatic\helpers\Gql as GqlHelper; |
||||||||||
17 | use nystudio107\seomatic\helpers\PluginTemplate; |
||||||||||
18 | use nystudio107\seomatic\helpers\Sitemap; |
||||||||||
19 | use nystudio107\seomatic\models\SitemapCustomTemplate; |
||||||||||
20 | use nystudio107\seomatic\models\SitemapIndexTemplate; |
||||||||||
21 | use nystudio107\seomatic\models\SitemapTemplate; |
||||||||||
22 | use nystudio107\seomatic\Seomatic; |
||||||||||
23 | use yii\web\NotFoundHttpException; |
||||||||||
24 | |||||||||||
25 | /** |
||||||||||
26 | * Class SitemapResolver |
||||||||||
27 | * |
||||||||||
28 | * @author nystudio107 |
||||||||||
29 | * @package Seomatic |
||||||||||
30 | * @since 3.4.18 |
||||||||||
31 | */ |
||||||||||
32 | class SitemapResolver |
||||||||||
33 | { |
||||||||||
34 | // Public Methods |
||||||||||
35 | // ========================================================================= |
||||||||||
36 | |||||||||||
37 | /** |
||||||||||
38 | * @param $source |
||||||||||
39 | * @param array $arguments |
||||||||||
40 | * @param $context |
||||||||||
41 | * @param ResolveInfo $resolveInfo |
||||||||||
42 | * @return array|array[]|null[] |
||||||||||
43 | * @throws NotFoundHttpException |
||||||||||
44 | */ |
||||||||||
45 | public static function getSitemaps($source, array $arguments, $context, ResolveInfo $resolveInfo) |
||||||||||
0 ignored issues
–
show
The parameter
$resolveInfo 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
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() The parameter
$context 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
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||||||
46 | { |
||||||||||
47 | // If there's a filename provided, return the sitemap. |
||||||||||
48 | if (!empty($arguments['filename'])) { |
||||||||||
49 | return [ |
||||||||||
50 | self::getSitemapItemByFilename($arguments['filename']), |
||||||||||
51 | ]; |
||||||||||
52 | } |
||||||||||
53 | $siteId = GqlHelper::getSiteIdFromGqlArguments($arguments); |
||||||||||
54 | $site = Craft::$app->getSites()->getSiteById($siteId); |
||||||||||
55 | |||||||||||
56 | if (!$site) { |
||||||||||
57 | return []; |
||||||||||
58 | } |
||||||||||
59 | |||||||||||
60 | $sitemapList = []; |
||||||||||
61 | // If either of the source bundle arguments are present, get the sitemap |
||||||||||
62 | if (!empty($arguments['sourceBundleType']) || !empty($arguments['sourceBundleHandle'])) { |
||||||||||
63 | $filenames = self::createSitemapFilenamesFromComponents($site->groupId, $arguments['sourceBundleType'] ?? '', $arguments['sourceBundleHandle'] ?? '', $siteId); |
||||||||||
64 | |||||||||||
65 | foreach ($filenames as $filename) { |
||||||||||
66 | $sitemapList[] = self::getSitemapItemByFilename($filename); |
||||||||||
67 | } |
||||||||||
68 | |||||||||||
69 | return $sitemapList; |
||||||||||
70 | } |
||||||||||
71 | |||||||||||
72 | $sitemapIndexItems = [self::getSitemapIndexListEntry($siteId, $site->groupId)]; |
||||||||||
73 | |||||||||||
74 | // Scrape each index for individual entries |
||||||||||
75 | foreach ($sitemapIndexItems as $sitemapIndexItem) { |
||||||||||
76 | $contents = $sitemapIndexItem['contents']; |
||||||||||
77 | if (preg_match_all('/<loc>(.*?)<\/loc>/m', $contents, $matches)) { |
||||||||||
78 | foreach ($matches[1] as $url) { |
||||||||||
79 | $parts = explode('/', $url); |
||||||||||
80 | $filename = end($parts); |
||||||||||
81 | |||||||||||
82 | // Get individual sitemaps |
||||||||||
83 | $item = self::getSitemapItemByFilename($filename); |
||||||||||
84 | |||||||||||
85 | if ($item) { |
||||||||||
86 | $sitemapList[] = $item; |
||||||||||
87 | } |
||||||||||
88 | } |
||||||||||
89 | } |
||||||||||
90 | } |
||||||||||
91 | |||||||||||
92 | return $sitemapList; |
||||||||||
93 | } |
||||||||||
94 | |||||||||||
95 | /** |
||||||||||
96 | * @param $source |
||||||||||
97 | * @param $arguments |
||||||||||
98 | * @param $context |
||||||||||
99 | * @param ResolveInfo $resolveInfo |
||||||||||
100 | * @return array[] |
||||||||||
101 | * @throws NotFoundHttpException |
||||||||||
102 | */ |
||||||||||
103 | public static function getSitemapIndexes($source, $arguments, $context, ResolveInfo $resolveInfo): array |
||||||||||
0 ignored issues
–
show
The parameter
$source 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
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() The parameter
$resolveInfo 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
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() The parameter
$context 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
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||||||
104 | { |
||||||||||
105 | $siteId = GqlHelper::getSiteIdFromGqlArguments($arguments); |
||||||||||
106 | $groupId = Craft::$app->getSites()->getSiteById($siteId)->groupId; |
||||||||||
107 | |||||||||||
108 | $sitemapIndexListEntry = self::getSitemapIndexListEntry($siteId, $groupId); |
||||||||||
109 | |||||||||||
110 | return [ |
||||||||||
111 | $sitemapIndexListEntry, |
||||||||||
112 | ]; |
||||||||||
113 | } |
||||||||||
114 | |||||||||||
115 | /** |
||||||||||
116 | * @param $source |
||||||||||
117 | * @param $arguments |
||||||||||
118 | * @param $context |
||||||||||
119 | * @param ResolveInfo $resolveInfo |
||||||||||
120 | * @return array |
||||||||||
121 | */ |
||||||||||
122 | public static function getSitemapStyles($source, $arguments, $context, ResolveInfo $resolveInfo): array |
||||||||||
0 ignored issues
–
show
The parameter
$source 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
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() The parameter
$arguments 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
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() The parameter
$resolveInfo 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
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() The parameter
$context 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
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||||||
123 | { |
||||||||||
124 | return [ |
||||||||||
125 | 'filename' => 'sitemap.xsl', |
||||||||||
126 | 'contents' => $xml = PluginTemplate::renderPluginTemplate('_frontend/pages/sitemap-styles.twig', []), |
||||||||||
0 ignored issues
–
show
|
|||||||||||
127 | ]; |
||||||||||
128 | } |
||||||||||
129 | |||||||||||
130 | /** |
||||||||||
131 | * @param $siteId |
||||||||||
132 | * @param $groupId |
||||||||||
133 | * @return array |
||||||||||
134 | * @throws NotFoundHttpException |
||||||||||
135 | */ |
||||||||||
136 | protected static function getSitemapIndexListEntry($siteId, $groupId): array |
||||||||||
137 | { |
||||||||||
138 | $sitemapIndex = SitemapIndexTemplate::create(); |
||||||||||
139 | if ($sitemapIndex) { |
||||||||||
0 ignored issues
–
show
|
|||||||||||
140 | return [ |
||||||||||
141 | 'filename' => $sitemapIndex->getFilename($groupId), |
||||||||||
142 | 'contents' => $sitemapIndex->render([ |
||||||||||
143 | 'siteId' => $siteId, |
||||||||||
144 | 'groupId' => $groupId, |
||||||||||
145 | ]), |
||||||||||
146 | ]; |
||||||||||
147 | } |
||||||||||
148 | |||||||||||
149 | return []; |
||||||||||
150 | } |
||||||||||
151 | |||||||||||
152 | /** |
||||||||||
153 | * @param $filename |
||||||||||
154 | * @return array|null |
||||||||||
155 | * @throws NotFoundHttpException |
||||||||||
156 | */ |
||||||||||
157 | protected static function getSitemapItemByFilename($filename) |
||||||||||
158 | { |
||||||||||
159 | if (!preg_match('/sitemaps-(?P<groupId>\d+)-(?P<type>[\w\.*]+)-(?P<handle>[\w\.*]+)-(?P<siteId>\d+)-sitemap(-p(?P<page>\d+))?/i', $filename, $matches)) { |
||||||||||
160 | return null; |
||||||||||
161 | } |
||||||||||
162 | |||||||||||
163 | $isCustom = $matches['type'] == 'global' && $matches['handle'] == 'custom'; |
||||||||||
164 | $sitemap = $isCustom ? SitemapCustomTemplate::create() : SitemapTemplate::create(); |
||||||||||
165 | |||||||||||
166 | return [ |
||||||||||
167 | 'filename' => $filename, |
||||||||||
168 | 'contents' => $sitemap->render(array_merge($matches, ['immediately' => true])), |
||||||||||
169 | ]; |
||||||||||
170 | } |
||||||||||
171 | |||||||||||
172 | /** |
||||||||||
173 | * Construct the expected sitemap filename from the components |
||||||||||
174 | * |
||||||||||
175 | * @param int $groupId |
||||||||||
176 | * @param string $bundleType |
||||||||||
177 | * @param string $bundleHandle |
||||||||||
178 | * @param int $siteId |
||||||||||
179 | * @return array |
||||||||||
180 | */ |
||||||||||
181 | protected static function createSitemapFilenamesFromComponents(int $groupId, string $bundleType, string $bundleHandle, int $siteId): array |
||||||||||
182 | { |
||||||||||
183 | $metaBundle = Seomatic::$plugin->metaBundles->getMetaBundleBySourceHandle($bundleType, $bundleHandle, $siteId); |
||||||||||
184 | if (!$metaBundle) { |
||||||||||
185 | return []; |
||||||||||
186 | } |
||||||||||
187 | |||||||||||
188 | $pageSize = $metaBundle->metaSitemapVars->sitemapPageSize ?? null; |
||||||||||
189 | if (!$pageSize) { |
||||||||||
0 ignored issues
–
show
The expression
$pageSize of type integer|null is loosely compared to false ; this is ambiguous if the integer can be 0. You might want to explicitly use === null instead.
In PHP, under loose comparison (like For 0 == false // true
0 == null // true
123 == false // false
123 == null // false
// It is often better to use strict comparison
0 === false // false
0 === null // false
![]() |
|||||||||||
190 | return ["sitemaps-$groupId-$bundleType-$bundleHandle-$siteId-sitemap.xml"]; |
||||||||||
191 | } |
||||||||||
192 | |||||||||||
193 | $sitemapFilenames = []; |
||||||||||
194 | $seoElement = Seomatic::$plugin->seoElements->getSeoElementByMetaBundleType($metaBundle->sourceBundleType); |
||||||||||
195 | if ($seoElement) { |
||||||||||
196 | $totalElements = Sitemap::getTotalElementsInSitemap($seoElement, $metaBundle); |
||||||||||
197 | $pageCount = $pageSize > 0 ? ceil($totalElements / $pageSize) : 1; |
||||||||||
198 | |||||||||||
199 | for ($page = 1; $page <= $pageCount; $page++) { |
||||||||||
200 | $sitemapFilenames[] = sprintf('sitemaps-%d-%s-%s-%d-sitemap-p%d.xml', $groupId, $bundleType, $bundleHandle, $siteId, $page); |
||||||||||
201 | } |
||||||||||
202 | } |
||||||||||
203 | |||||||||||
204 | return $sitemapFilenames; |
||||||||||
205 | } |
||||||||||
206 | } |
||||||||||
207 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.