Passed
Branch code-quality (49e886)
by Caen
02:56
created

Metadata::generate()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 0 Features 2
Metric Value
cc 4
eloc 9
c 6
b 0
f 2
nc 8
nop 0
dl 0
loc 19
rs 9.9666
1
<?php
2
3
namespace Hyde\Framework\Models\Metadata;
4
5
use Hyde\Framework\Contracts\AbstractPage;
6
use Hyde\Framework\Contracts\MetadataItemContract;
7
use Hyde\Framework\Helpers\Features;
8
use Hyde\Framework\Helpers\Meta;
9
use Hyde\Framework\Hyde;
10
use Hyde\Framework\Models\Pages\MarkdownPost;
11
use Hyde\Framework\Services\RssFeedService;
12
13
/**
14
 * @see \Hyde\Framework\Testing\Feature\MetadataTest
15
 */
16
class Metadata
17
{
18
    protected AbstractPage $page;
19
20
    public array $links = [];
21
    public array $metadata = [];
22
    public array $properties = [];
23
    public array $generics = [];
24
25
    public function __construct(AbstractPage $page)
26
    {
27
        $this->page = $page;
28
        $this->generate();
29
    }
30
31
    public function render(): string
32
    {
33
        return implode("\n", $this->get());
34
    }
35
36
    public function get(): array
37
    {
38
        return array_merge(
39
            $this->getPrefixedArray('links'),
40
            $this->getPrefixedArray('metadata'),
41
            $this->getPrefixedArray('properties'),
42
            $this->getPrefixedArray('generics')
43
        );
44
    }
45
46
    public function add(MetadataItemContract|string $item): static
47
    {
48
        if ($item instanceof LinkItem) {
49
            $this->links[$item->uniqueKey()] = $item;
50
        } elseif ($item instanceof MetadataItem) {
51
            $this->metadata[$item->uniqueKey()] = $item;
52
        } elseif ($item instanceof OpenGraphItem) {
53
            $this->properties[$item->uniqueKey()] = $item;
54
        } else {
55
            $this->generics[] = $item;
56
        }
57
58
        return $this;
59
    }
60
61
    protected function generate(): void
62
    {
63
        foreach (config('hyde.meta', []) as $item) {
64
            $this->add($item);
65
        }
66
67
        if (Features::sitemap()) {
68
            $this->add(Meta::link('sitemap', Hyde::url('sitemap.xml'), [
69
                'type' => 'application/xml', 'title' => 'Sitemap',
70
            ]));
71
        }
72
73
        if (Features::rss()) {
74
            $this->add(Meta::link('alternate', Hyde::url(RssFeedService::getDefaultOutputFilename()), [
75
                'type' => 'application/rss+xml', 'title' => RssFeedService::getDescription(),
76
            ]));
77
        }
78
79
        $this->addDynamicPageMetadata($this->page);
80
    }
81
82
    protected function addDynamicPageMetadata(AbstractPage $page): void
83
    {
84
        if ($page->has('canonicalUrl')) {
85
            $this->add(Meta::link('canonical', $page->get('canonicalUrl')));
86
        }
87
88
        if ($page->has('title')) {
89
            $this->add(Meta::name('twitter:title', $page->htmlTitle()));
90
            $this->add(Meta::property('title', $page->htmlTitle()));
91
        }
92
93
        if ($page instanceof MarkdownPost) {
94
            $this->addMetadataForMarkdownPost($page);
95
        }
96
    }
97
98
    protected function addMetadataForMarkdownPost(MarkdownPost $page): void
99
    {
100
        $this->addPostMetadataIfExists($page, 'description');
101
        $this->addPostMetadataIfExists($page, 'author');
102
        $this->addPostMetadataIfExists($page, 'category', 'keywords');
103
        $this->addPostMetadataIfExists($page, 'canonicalUrl', 'url');
104
105
        if ($page->has('canonicalUrl')) {
106
            $this->add(Meta::property('url', $page->get('canonicalUrl')));
107
        }
108
109
        if ($page->has('date')) {
110
            $this->add(Meta::property('og:article:published_time', $page->date->datetime));
111
        }
112
113
        if ($page->has('image')) {
114
            $this->add(Meta::property('image', $this->resolveImageLink($page->get('image'))));
115
        }
116
117
        $this->add(Meta::property('type', 'article'));
118
    }
119
120
    protected function addPostMetadataIfExists(MarkdownPost $page, string $property, ?string $name = null): void
121
    {
122
        if ($page->has($property)) {
123
            $this->add(Meta::name($name ?? $property, $page->get($property)));
124
        }
125
    }
126
127
    protected function getPrefixedArray(string $group): array
128
    {
129
        $array = [];
130
        foreach ($this->{$group} as $key => $value) {
131
            $array[$group.':'.$key] = $value;
132
        }
133
134
        return $array;
135
    }
136
137
    protected function resolveImageLink(string $image): string
138
    {
139
        // Since this is run before the page is rendered, we don't have the currentPage property
140
        // but since we know that this is for a blog post we know what the property will be
141
        // since Hyde does not currently support custom Blog post output directories.
142
        return str_starts_with($image, 'http') ? $image : "../$image";
143
    }
144
}
145