Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
67 / 67
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
SitemapIndexHandler
100.00% covered (success)
100.00%
67 / 67
100.00% covered (success)
100.00%
5 / 5
8
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 getParamSettings
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 getXml
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
1 / 1
4
 getResponseSchema
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
1 / 1
1
 getResponseExample
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace MediaWiki\Rest\Handler;
4
5use MediaWiki\Config\Config;
6use MediaWiki\Language\Language;
7use MediaWiki\Languages\LanguageConverterFactory;
8use MediaWiki\Permissions\PermissionManager;
9use MediaWiki\Rest\Handler;
10use Wikimedia\Message\MessageValue;
11use Wikimedia\ParamValidator\ParamValidator;
12use Wikimedia\Rdbms\IConnectionProvider;
13
14class SitemapIndexHandler extends SitemapHandlerBase {
15    public function __construct(
16        Config $config,
17        LanguageConverterFactory $languageConverterFactory,
18        Language $contLang,
19        PermissionManager $permissionManager,
20        private IConnectionProvider $connectionProvider,
21    ) {
22        parent::__construct(
23            $config,
24            $languageConverterFactory,
25            $contLang,
26            $permissionManager,
27        );
28    }
29
30    /** @inheritDoc */
31    public function getParamSettings() {
32        return [
33            'indexId' => [
34                self::PARAM_SOURCE => 'path',
35                ParamValidator::PARAM_TYPE => 'integer',
36                ParamValidator::PARAM_REQUIRED => true,
37                Handler::PARAM_DESCRIPTION => new MessageValue( 'rest-param-desc-sitemap-index-id' ),
38            ],
39        ];
40    }
41
42    protected function getXml(): string {
43        $index = $this->getValidatedParams()['indexId'];
44        $dbr = $this->connectionProvider->getReplicaDatabase();
45
46        $maxPageId = (int)$dbr->newSelectQueryBuilder()
47            ->select( 'MAX(page_id)' )
48            ->from( 'page' )
49            ->caller( __METHOD__ )
50            ->fetchField();
51
52        $xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" .
53            "<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n";
54
55        $offset = $this->getOffset( $index, 0 );
56        if ( $offset <= $maxPageId ) {
57            $numPages = $maxPageId - $offset;
58            if ( $numPages > $this->indexSize * $this->sitemapSize ) {
59                $nextUrl = $this->getRouter()->getRouteUrl( "/site/v1/sitemap/" . ( $index + 1 ) );
60                $xml .= "<!-- maximum index size exceeded, make sure your robots.txt has:\n" .
61                    "Sitemap: $nextUrl -->\n";
62                $numPages = $this->indexSize * $this->sitemapSize;
63            }
64
65            $numSitemaps = (int)ceil( $numPages / $this->sitemapSize );
66            for ( $i = 0; $i < $numSitemaps; $i++ ) {
67                $xml .= '<sitemap><loc>' .
68                    htmlspecialchars(
69                        $this->getRouter()->getRouteUrl( "/site/v1/sitemap/$index/page/$i" )
70                    ) .
71                    "</loc></sitemap>\n";
72            }
73        }
74        $xml .= "</sitemapindex>\n";
75        return $xml;
76    }
77
78    protected function getResponseSchema(): array {
79        return [
80            'type' => 'object',
81            'xml' => [
82                'name' => 'sitemapindex',
83                'namespace' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
84            ],
85            'properties' => [
86                'sitemap' => [
87                    'type' => 'array',
88                    'xml' => [ 'wrapped' => false ],
89                    'items' => [
90                        'type' => 'object',
91                        'xml' => [ 'name' => 'sitemap' ],
92                        'properties' => [
93                            'loc' => [
94                                'type' => 'string',
95                                'format' => 'uri',
96                                'xml' => [ 'name' => 'loc' ],
97                                'description' => 'URL of a sitemap page',
98                            ],
99                        ],
100                    ],
101                ],
102            ],
103        ];
104    }
105
106    protected function getResponseExample(): string {
107        return '<?xml version="1.0" encoding="UTF-8"?>
108<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
109  <sitemap><loc>https://example.org/sitemap/0/page/0</loc></sitemap>
110  <sitemap><loc>https://example.org/sitemap/0/page/1</loc></sitemap>
111</sitemapindex>';
112    }
113}