Passed
Push — master ( e019f1...cbaf1a )
by Caen
03:07 queued 12s
created

MetadataBag   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 118
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
eloc 51
c 3
b 0
f 1
dl 0
loc 118
rs 10
wmc 24

11 Methods

Rating   Name   Duplication   Size   Complexity  
A get() 0 7 1
A toHtml() 0 3 1
A add() 0 13 4
A render() 0 3 1
A addMetadataForMarkdownPost() 0 20 4
A getPrefixedArray() 0 8 2
A addPostMetadataIfExists() 0 4 2
A addDynamicPageMetadata() 0 13 4
A generate() 0 3 1
A __construct() 0 5 2
A resolveImageLink() 0 6 2
1
<?php
2
3
namespace Hyde\Framework\Models\Metadata;
4
5
use Hyde\Framework\Concerns\HydePage;
6
use Hyde\Framework\Contracts\MetadataItemContract;
7
use Hyde\Framework\Helpers\Meta;
8
use Hyde\Framework\Models\Pages\MarkdownPost;
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(MetadataItemContract|string $item): static
54
    {
55
        if ($item instanceof LinkItem) {
56
            $this->links[$item->uniqueKey()] = $item;
57
        } elseif ($item instanceof MetadataItem) {
58
            $this->metadata[$item->uniqueKey()] = $item;
59
        } elseif ($item instanceof OpenGraphItem) {
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