Issues (257)

src/gql/resolvers/SitemapResolver.php (12 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\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 $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 ignore-unused  annotation

40
    public static function getSitemaps(/** @scrutinizer ignore-unused */ $source, array $arguments, $context, ResolveInfo $resolveInfo)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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 ignore-unused  annotation

40
    public static function getSitemaps($source, array $arguments, $context, /** @scrutinizer ignore-unused */ ResolveInfo $resolveInfo)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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 ignore-unused  annotation

40
    public static function getSitemaps($source, array $arguments, /** @scrutinizer ignore-unused */ $context, ResolveInfo $resolveInfo)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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 ignore-unused  annotation

97
    public static function getSitemapIndexes(/** @scrutinizer ignore-unused */ $source, $arguments, $context, ResolveInfo $resolveInfo): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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 ignore-unused  annotation

97
    public static function getSitemapIndexes($source, $arguments, /** @scrutinizer ignore-unused */ $context, ResolveInfo $resolveInfo): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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 ignore-unused  annotation

97
    public static function getSitemapIndexes($source, $arguments, $context, /** @scrutinizer ignore-unused */ ResolveInfo $resolveInfo): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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 ignore-unused  annotation

116
    public static function getSitemapStyles(/** @scrutinizer ignore-unused */ $source, $arguments, $context, ResolveInfo $resolveInfo): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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 ignore-unused  annotation

116
    public static function getSitemapStyles($source, $arguments, $context, /** @scrutinizer ignore-unused */ ResolveInfo $resolveInfo): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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 ignore-unused  annotation

116
    public static function getSitemapStyles($source, $arguments, /** @scrutinizer ignore-unused */ $context, ResolveInfo $resolveInfo): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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 ignore-unused  annotation

116
    public static function getSitemapStyles($source, /** @scrutinizer ignore-unused */ $arguments, $context, ResolveInfo $resolveInfo): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
117
    {
118
        return [
119
            'filename' => 'sitemap.xsl',
120
            'contents' => $xml = PluginTemplate::renderPluginTemplate('_frontend/pages/sitemap-styles.twig', []),
0 ignored issues
show
The assignment to $xml is dead and can be removed.
Loading history...
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
Bug Best Practice introduced by
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 ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

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
Loading history...
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