Completed
Push — master ( 8756c0...bbe0e7 )
by jelmer
28:03 queued 22:05
created

MetaData::merge()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 5
nc 3
nop 1
dl 0
loc 11
ccs 6
cts 6
cp 1
crap 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Frontend\Core\Header;
4
5
use InvalidArgumentException;
6
7
final class MetaData
8
{
9
    /** @var array */
10
    private $attributes;
11
12
    /** @var string */
13
    private $uniqueKey;
14
15
    /**
16
     * @param string $content since we always need content we've added it as a separate parameter
17
     * @param string[] $attributes
18
     * @param string[] $uniqueAttributeKeys
19
     * @param string|null $uniqueKeySuffix
20
     *
21
     * @throws InvalidArgumentException when the content is empty
22
     */
23 24
    public function __construct(
24
        string $content,
25
        array $attributes,
26
        array $uniqueAttributeKeys = ['content'],
27
        string $uniqueKeySuffix = null
28
    ) {
29 24
        if (empty($content)) {
30
            throw new InvalidArgumentException('The content can not be empty');
31
        }
32
33 24
        $this->attributes = ['content' => $content] + $attributes;
34 24
        $this->createUniqueKey($uniqueAttributeKeys, $uniqueKeySuffix);
35 24
    }
36
37
    /**
38
     * @param string[] $uniqueAttributeKeys
39
     * @param string|null $uniqueKeySuffix
40
     */
41 24
    private function createUniqueKey(array $uniqueAttributeKeys, string $uniqueKeySuffix = null): void
42
    {
43
        // make sure the keys are sorted alphabetically
44 24
        sort($uniqueAttributeKeys);
45
46 24
        $this->uniqueKey = implode(
47 24
            '|',
48 24
            array_filter(
49 24
                array_map(
50 24
                    function (string $attributeKey) {
51 24
                        return $this->attributes[$attributeKey] ?? '';
52 24
                    },
53 24
                    $uniqueAttributeKeys
54
                )
55
            )
56
        );
57
58 24
        if ($uniqueKeySuffix !== null) {
59
            $this->uniqueKey .= '|' . $uniqueKeySuffix;
60
        }
61 24
    }
62
63 24
    public function getUniqueKey(): string
64
    {
65 24
        return $this->uniqueKey;
66
    }
67
68
    public function hasAttributeWithValue(string $attributeKey, string $attributeValue): bool
69
    {
70
        return isset($this->attributes[$attributeKey]) && $this->attributes[$attributeKey] === $attributeValue;
71
    }
72
73
    /**
74
     * Some things should be appended instead of ignored when the meta data is already set instead of ignored.
75
     *
76
     * @return bool
77
     */
78 12
    public function shouldMergeOnDuplicateKey(): bool
79
    {
80 12
        return in_array($this->uniqueKey, ['description', 'keywords', 'robots'], true);
81
    }
82
83 12
    public function merge(self $metaData): void
84
    {
85 12
        foreach ($metaData->attributes as $attributeKey => $attributeValue) {
86
            // the content should be appended, the rest of the attributes gets overwritten or added
87 12
            if ($attributeKey === 'content' && isset($this->attributes[$attributeKey])) {
88 12
                $this->attributes[$attributeKey] .= ', ' . $attributeValue;
89
90 12
                continue;
91
            }
92
93 12
            $this->attributes[$attributeKey] = $attributeValue;
94
        }
95 12
    }
96
97 24
    public static function forName(
98
        string $name,
99
        string $content
100
    ): self {
101 24
        return new self($content, ['name' => $name], ['name']);
102
    }
103
104 2
    public static function forProperty(
105
        string $property,
106
        string $content,
107
        array $uniqueAttributeKeys = ['property']
108
    ): self {
109 2
        return new self($content, ['property' => $property], $uniqueAttributeKeys);
110
    }
111
112 24
    public function __toString(): string
113
    {
114 24
        $html = '<meta ';
115 24
        $html .= implode(
116 24
            ' ',
117 24
            array_map(
118 24
                function (string $parameterKey, string $parameterValue) {
119 24
                    return $parameterKey . '="' . $parameterValue . '"';
120 24
                },
121
                array_keys($this->attributes),
122
                $this->attributes
123
            )
124
        );
125
        $html .= '>';
126
127
        return $html;
128
    }
129
}
130