Passed
Push — master ( 32dd3a...b6a4c4 )
by Caen
03:02 queued 12s
created

SitemapService::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 5
c 2
b 0
f 0
dl 0
loc 10
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
/** @noinspection PhpComposerExtensionStubsInspection */
4
5
declare(strict_types=1);
6
7
namespace Hyde\Framework\Services;
8
9
use function config;
10
use function date;
11
use Exception;
12
use function extension_loaded;
13
use function filemtime;
14
use Hyde\Hyde;
15
use Hyde\Pages\BladePage;
16
use Hyde\Pages\DocumentationPage;
17
use Hyde\Pages\MarkdownPage;
18
use Hyde\Pages\MarkdownPost;
19
use Hyde\Support\Helpers\XML;
20
use Hyde\Support\Models\Route;
21
use function in_array;
22
use function microtime;
23
use function round;
24
use SimpleXMLElement;
25
use function throw_unless;
26
27
/**
28
 * @see \Hyde\Framework\Testing\Feature\Services\SitemapServiceTest
29
 * @see https://www.sitemaps.org/protocol.html
30
 * @phpstan-consistent-constructor
31
 */
32
class SitemapService
33
{
34
    public SimpleXMLElement $xmlElement;
35
    protected float $timeStart;
36
37
    public static function generateSitemap(): string
38
    {
39
        return (new static)->generate()->getXML();
40
    }
41
42
    public function __construct()
43
    {
44
        throw_unless(extension_loaded('simplexml'),
45
            new Exception('The ext-simplexml extension is not installed, but is required to generate sitemaps.')
46
        );
47
48
        $this->timeStart = microtime(true);
49
50
        $this->xmlElement = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9"></urlset>');
51
        $this->xmlElement->addAttribute('generator', 'HydePHP '.Hyde::version());
52
    }
53
54
    public function generate(): static
55
    {
56
        Route::all()->each(function (Route $route): void {
57
            $this->addRoute($route);
58
        });
59
60
        return $this;
61
    }
62
63
    public function getXML(): string
64
    {
65
        $this->xmlElement->addAttribute('processing_time_ms', $this->getFormattedProcessingTime());
66
67
        return (string) $this->xmlElement->asXML();
68
    }
69
70
    public function addRoute(Route $route): void
71
    {
72
        $urlItem = $this->xmlElement->addChild('url');
73
74
        $urlItem->addChild('loc', XML::escape(Hyde::url($route->getOutputPath())));
75
        $urlItem->addChild('lastmod', XML::escape($this->getLastModDate($route->getSourcePath())));
76
        $urlItem->addChild('changefreq', 'daily');
77
78
        if (config('hyde.sitemap.dynamic_priority', true)) {
79
            $urlItem->addChild('priority', $this->getPriority(
80
                $route->getPageClass(), $route->getPage()->getIdentifier()
81
            ));
82
        }
83
    }
84
85
    protected function getLastModDate(string $file): string
86
    {
87
        return date('c', filemtime($file));
88
    }
89
90
    protected function getPriority(string $pageClass, string $slug): string
91
    {
92
        $priority = 0.5;
93
94
        if (in_array($pageClass, [BladePage::class, MarkdownPage::class])) {
95
            $priority = 0.9;
96
            if ($slug === 'index') {
97
                $priority = 1;
98
            }
99
            if ($slug === '404') {
100
                $priority = 0.5;
101
            }
102
        }
103
104
        if ($pageClass === DocumentationPage::class) {
105
            $priority = 0.9;
106
        }
107
108
        if ($pageClass === MarkdownPost::class) {
109
            $priority = 0.75;
110
        }
111
112
        return (string) $priority;
113
    }
114
115
    protected function getFormattedProcessingTime(): string
116
    {
117
        return (string) round((microtime(true) - $this->timeStart) * 1000, 2);
118
    }
119
}
120