Passed
Push — master ( 9e7cad...7929d2 )
by Caen
03:29 queued 12s
created

MetadataBag::get()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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