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\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 | * Get all the sitemaps. |
||||||||||
39 | */ |
||||||||||
40 | 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. ![]() |
|||||||||||
41 | { |
||||||||||
42 | // If there's a filename provided, return the sitemap. |
||||||||||
43 | if (!empty($arguments['filename'])) { |
||||||||||
44 | return [ |
||||||||||
45 | self::getSitemapItemByFilename($arguments['filename']), |
||||||||||
46 | ]; |
||||||||||
47 | } |
||||||||||
48 | $siteId = GqlHelper::getSiteIdFromGqlArguments($arguments); |
||||||||||
49 | $site = Craft::$app->getSites()->getSiteById($siteId); |
||||||||||
50 | |||||||||||
51 | if (!$site) { |
||||||||||
52 | return []; |
||||||||||
53 | } |
||||||||||
54 | |||||||||||
55 | $sitemapList = []; |
||||||||||
56 | // If either of the source bundle arguments are present, get the sitemap |
||||||||||
57 | if (!empty($arguments['sourceBundleType']) || !empty($arguments['sourceBundleHandle'])) { |
||||||||||
58 | $filenames = self::createSitemapFilenamesFromComponents($site->groupId, $arguments['sourceBundleType'] ?? '', $arguments['sourceBundleHandle'] ?? '', $siteId); |
||||||||||
59 | |||||||||||
60 | foreach ($filenames as $filename) { |
||||||||||
61 | $sitemapList[] = self::getSitemapItemByFilename($filename); |
||||||||||
62 | } |
||||||||||
63 | |||||||||||
64 | return $sitemapList; |
||||||||||
65 | } |
||||||||||
66 | |||||||||||
67 | $sitemapIndexItems = [self::getSitemapIndexListEntry($siteId, $site->groupId)]; |
||||||||||
68 | |||||||||||
69 | $sitemapList = []; |
||||||||||
70 | // Scrape each index for individual entries |
||||||||||
71 | foreach ($sitemapIndexItems as $sitemapIndexItem) { |
||||||||||
72 | $contents = $sitemapIndexItem['contents']; |
||||||||||
73 | if (preg_match_all('/<loc>(.*?)<\/loc>/m', $contents, $matches)) { |
||||||||||
74 | foreach ($matches[1] as $url) { |
||||||||||
75 | $parts = explode('/', $url); |
||||||||||
76 | $filename = end($parts); |
||||||||||
77 | |||||||||||
78 | // Get individual sitemaps |
||||||||||
79 | $item = self::getSitemapItemByFilename($filename); |
||||||||||
80 | |||||||||||
81 | if ($item) { |
||||||||||
82 | $sitemapList[] = $item; |
||||||||||
83 | } |
||||||||||
84 | } |
||||||||||
85 | } |
||||||||||
86 | } |
||||||||||
87 | |||||||||||
88 | return $sitemapList; |
||||||||||
89 | } |
||||||||||
90 | |||||||||||
91 | /** |
||||||||||
92 | * Get all the sitemap index items by params. |
||||||||||
93 | * |
||||||||||
94 | * @return array |
||||||||||
95 | * @throws NotFoundHttpException |
||||||||||
96 | */ |
||||||||||
97 | 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
$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. ![]() 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. ![]() |
|||||||||||
98 | { |
||||||||||
99 | $siteId = GqlHelper::getSiteIdFromGqlArguments($arguments); |
||||||||||
100 | $groupId = Craft::$app->getSites()->getSiteById($siteId)->groupId; |
||||||||||
101 | |||||||||||
102 | $sitemapIndexListEntry = self::getSitemapIndexListEntry($siteId, $groupId); |
||||||||||
103 | |||||||||||
104 | return [ |
||||||||||
105 | $sitemapIndexListEntry, |
||||||||||
106 | ]; |
||||||||||
107 | } |
||||||||||
108 | |||||||||||
109 | /** |
||||||||||
110 | * @param $source |
||||||||||
111 | * @param $arguments |
||||||||||
112 | * @param $context |
||||||||||
113 | * @param ResolveInfo $resolveInfo |
||||||||||
114 | * @return array |
||||||||||
115 | */ |
||||||||||
116 | 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
$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. ![]() 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. ![]() |
|||||||||||
117 | { |
||||||||||
118 | return [ |
||||||||||
119 | 'filename' => 'sitemap.xsl', |
||||||||||
120 | 'contents' => $xml = PluginTemplate::renderPluginTemplate('_frontend/pages/sitemap-styles.twig', []), |
||||||||||
0 ignored issues
–
show
|
|||||||||||
121 | ]; |
||||||||||
122 | } |
||||||||||
123 | |||||||||||
124 | /** |
||||||||||
125 | * @param $siteId |
||||||||||
126 | * @param $groupId |
||||||||||
127 | * @return array |
||||||||||
128 | * @throws NotFoundHttpException |
||||||||||
129 | */ |
||||||||||
130 | protected static function getSitemapIndexListEntry($siteId, $groupId): array |
||||||||||
131 | { |
||||||||||
132 | $sitemapIndex = SitemapIndexTemplate::create(); |
||||||||||
133 | $sitemapIndexItem = [ |
||||||||||
134 | 'filename' => $sitemapIndex->getFilename($groupId), |
||||||||||
135 | 'contents' => $sitemapIndex->render([ |
||||||||||
136 | 'siteId' => $siteId, |
||||||||||
137 | 'groupId' => $groupId, |
||||||||||
138 | ]), |
||||||||||
139 | ]; |
||||||||||
140 | |||||||||||
141 | return $sitemapIndexItem; |
||||||||||
142 | } |
||||||||||
143 | |||||||||||
144 | /** |
||||||||||
145 | * @param $filename |
||||||||||
146 | * @return array|null |
||||||||||
147 | * @throws NotFoundHttpException |
||||||||||
148 | */ |
||||||||||
149 | protected static function getSitemapItemByFilename($filename) |
||||||||||
150 | { |
||||||||||
151 | if (!preg_match('/sitemaps-(?P<groupId>\d+)-(?P<type>[\w\.*]+)-(?P<handle>[\w\.*]+)-(?P<siteId>\d+)-sitemap(-p(?P<page>\d+))?/i', $filename, $matches)) { |
||||||||||
152 | return null; |
||||||||||
153 | } |
||||||||||
154 | |||||||||||
155 | $isCustom = $matches['type'] == 'global' && $matches['handle'] == 'custom'; |
||||||||||
156 | $sitemap = $isCustom ? SitemapCustomTemplate::create() : SitemapTemplate::create(); |
||||||||||
157 | |||||||||||
158 | return [ |
||||||||||
159 | 'filename' => $filename, |
||||||||||
160 | 'contents' => $sitemap->render(array_merge($matches, ['immediately' => true])), |
||||||||||
161 | ]; |
||||||||||
162 | } |
||||||||||
163 | |||||||||||
164 | /** |
||||||||||
165 | * Construct the expected sitemap filename from the components |
||||||||||
166 | * |
||||||||||
167 | * @param int $groupId |
||||||||||
168 | * @param string $bundleType |
||||||||||
169 | * @param string $bundleHandle |
||||||||||
170 | * @param int $siteId |
||||||||||
171 | * @return array |
||||||||||
172 | */ |
||||||||||
173 | protected static function createSitemapFilenamesFromComponents(int $groupId, string $bundleType, string $bundleHandle, int $siteId): array |
||||||||||
174 | { |
||||||||||
175 | $metaBundle = Seomatic::$plugin->metaBundles->getMetaBundleBySourceHandle($bundleType, $bundleHandle, $siteId); |
||||||||||
176 | if (!$metaBundle) { |
||||||||||
177 | return []; |
||||||||||
178 | } |
||||||||||
179 | |||||||||||
180 | $pageSize = $metaBundle->metaSitemapVars->sitemapPageSize ?? null; |
||||||||||
181 | 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
![]() |
|||||||||||
182 | return ["sitemaps-$groupId-$bundleType-$bundleHandle-$siteId-sitemap.xml"]; |
||||||||||
183 | } |
||||||||||
184 | |||||||||||
185 | $sitemapFilenames = []; |
||||||||||
186 | $seoElement = Seomatic::$plugin->seoElements->getSeoElementByMetaBundleType($metaBundle->sourceBundleType); |
||||||||||
187 | if ($seoElement) { |
||||||||||
188 | $totalElements = Sitemap::getTotalElementsInSitemap($seoElement, $metaBundle); |
||||||||||
189 | $pageCount = $pageSize > 0 ? ceil($totalElements / $pageSize) : 1; |
||||||||||
190 | |||||||||||
191 | for ($page = 1; $page <= $pageCount; $page++) { |
||||||||||
192 | $sitemapFilenames[] = sprintf('sitemaps-%d-%s-%s-%d-sitemap-p%d.xml', $groupId, $bundleType, $bundleHandle, $siteId, $page); |
||||||||||
193 | } |
||||||||||
194 | } |
||||||||||
195 | |||||||||||
196 | return $sitemapFilenames; |
||||||||||
197 | } |
||||||||||
198 | } |
||||||||||
199 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.