Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
8 / 8
CRAP
100.00% covered (success)
100.00%
1 / 1
SitemapService
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
8 / 8
21
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 generate
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
5
 getXML
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 addPageModelUrls
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 getLastModDate
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getPriority
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
6
 generateSitemap
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 canGenerateSitemap
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3namespace Hyde\Framework\Services;
4
5use Hyde\Framework\Helpers\Features;
6use Hyde\Framework\Hyde;
7use Hyde\Framework\Models\BladePage;
8use Hyde\Framework\Models\DocumentationPage;
9use Hyde\Framework\Models\MarkdownPage;
10use Hyde\Framework\Models\MarkdownPost;
11use SimpleXMLElement;
12
13/**
14 * @see \Tests\Feature\Services\SitemapServiceTest
15 * @see https://www.sitemaps.org/protocol.html
16 */
17class SitemapService
18{
19    public SimpleXMLElement $xmlElement;
20    protected float $time_start;
21
22    public function __construct()
23    {
24        $this->time_start = microtime(true);
25
26        $this->xmlElement = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9"></urlset>');
27        $this->xmlElement->addAttribute('generator', 'HydePHP '.Hyde::version());
28    }
29
30    public function generate(): self
31    {
32        if (Features::hasBladePages()) {
33            $this->addPageModelUrls(
34                BladePage::class
35            );
36        }
37
38        if (Features::hasMarkdownPages()) {
39            $this->addPageModelUrls(
40                MarkdownPage::class
41            );
42        }
43
44        if (Features::hasBlogPosts()) {
45            $this->addPageModelUrls(
46                MarkdownPost::class,
47                'posts/'
48            );
49        }
50
51        if (Features::hasDocumentationPages()) {
52            $this->addPageModelUrls(
53                DocumentationPage::class,
54                Hyde::docsDirectory().'/'
55            );
56        }
57
58        return $this;
59    }
60
61    public function getXML(): string
62    {
63        $this->xmlElement->addAttribute('processing_time_ms', (string) round((microtime(true) - $this->time_start) * 1000, 2));
64
65        return $this->xmlElement->asXML();
66    }
67
68    public function addPageModelUrls(string $pageClass, string $routePrefix = ''): void
69    {
70        $collection = CollectionService::getSourceFileListForModel($pageClass);
71
72        foreach ($collection as $slug) {
73            $urlItem = $this->xmlElement->addChild('url');
74            $urlItem->addChild('loc', htmlentities(Hyde::uriPath(Hyde::pageLink($routePrefix.$slug.'.html'))));
75            $urlItem->addChild('lastmod', htmlentities($this->getLastModDate($pageClass, $slug)));
76            $urlItem->addChild('changefreq', 'daily');
77            if (config('hyde.sitemap.dynamic_priority', true)) {
78                $urlItem->addChild('priority', $this->getPriority($pageClass, $slug));
79            }
80        }
81    }
82
83    protected function getLastModDate(string $pageClass, string $slug): string
84    {
85        return date('c', filemtime(
86            /** @var \Hyde\Framework\Contracts\AbstractPage $pageClass */
87            Hyde::path($pageClass::$sourceDirectory.DIRECTORY_SEPARATOR.$slug.$pageClass::$fileExtension)
88        ));
89    }
90
91    protected function getPriority(string $pageClass, string $slug): string
92    {
93        $priority = 0.5;
94
95        if (in_array($pageClass, [BladePage::class, MarkdownPage::class])) {
96            $priority = 0.9;
97            if ($slug === 'index') {
98                $priority = 1;
99            }
100            if ($slug === '404') {
101                $priority = 0.5;
102            }
103        }
104
105        if ($pageClass === DocumentationPage::class) {
106            $priority = 0.9;
107        }
108
109        if ($pageClass === MarkdownPost::class) {
110            $priority = 0.75;
111        }
112
113        return (string) $priority;
114    }
115
116    public static function generateSitemap(): string
117    {
118        return (new static)->generate()->getXML();
119    }
120
121    public static function canGenerateSitemap(): bool
122    {
123        return (Hyde::uriPath() !== false)
124            && config('hyde.generate_sitemap', true)
125            && extension_loaded('simplexml');
126    }
127}