Passed
Push — latest ( 981bad...ca3ef7 )
by Colin
02:16 queued 10s
created

HtmlElement::__toString()   B

Complexity

Conditions 8
Paths 16

Size

Total Lines 25
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 8

Importance

Changes 0
Metric Value
eloc 17
dl 0
loc 25
ccs 16
cts 16
cp 1
rs 8.4444
c 0
b 0
f 0
cc 8
nc 16
nop 0
crap 8
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the league/commonmark package.
7
 *
8
 * (c) Colin O'Dell <[email protected]>
9
 *
10
 * Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
11
 *  - (c) John MacFarlane
12
 *
13
 * For the full copyright and license information, please view the LICENSE
14
 * file that was distributed with this source code.
15
 */
16
17
namespace League\CommonMark\Util;
18
19
class HtmlElement
20
{
21
    /** @var string */
22
    protected $tagName;
23
24
    /** @var array<string, string|bool> */
25
    protected $attributes = [];
26
27
    /** @var HtmlElement|HtmlElement[]|string */
28
    protected $contents;
29
30
    /** @var bool */
31
    protected $selfClosing = false;
32
33
    /**
34
     * @param string                                $tagName     Name of the HTML tag
35
     * @param array<string, string|string[]|bool>   $attributes  Array of attributes (values should be unescaped)
36
     * @param HtmlElement|HtmlElement[]|string|null $contents    Inner contents, pre-escaped if needed
37
     * @param bool                                  $selfClosing Whether the tag is self-closing
38
     */
39 2982
    public function __construct(string $tagName, array $attributes = [], $contents = '', bool $selfClosing = false)
40
    {
41 2982
        $this->tagName     = $tagName;
42 2982
        $this->selfClosing = $selfClosing;
43
44 2982
        foreach ($attributes as $name => $value) {
45 1182
            $this->setAttribute($name, $value);
46
        }
47
48 2982
        $this->setContents($contents ?? '');
49 2982
    }
50
51 102
    public function getTagName(): string
52
    {
53 102
        return $this->tagName;
54
    }
55
56
    /**
57
     * @return array<string, string|bool>
58
     */
59 66
    public function getAllAttributes(): array
60
    {
61 66
        return $this->attributes;
62
    }
63
64
    /**
65
     * @return string|bool|null
66
     */
67 96
    public function getAttribute(string $key)
68
    {
69 96
        if (! isset($this->attributes[$key])) {
70 24
            return null;
71
        }
72
73 90
        return $this->attributes[$key];
74
    }
75
76
    /**
77
     * @param string|string[]|bool $value
78
     */
79 1197
    public function setAttribute(string $key, $value): self
80
    {
81 1197
        if (\is_array($value)) {
82 432
            $this->attributes[$key] = \implode(' ', \array_unique($value));
83
        } else {
84 1176
            $this->attributes[$key] = $value;
85
        }
86
87 1197
        return $this;
88
    }
89
90
    /**
91
     * @return HtmlElement|HtmlElement[]|string
92
     */
93 99
    public function getContents(bool $asString = true)
94
    {
95 99
        if (! $asString) {
96 15
            return $this->contents;
97
        }
98
99 93
        return $this->getContentsAsString();
100
    }
101
102
    /**
103
     * Sets the inner contents of the tag (must be pre-escaped if needed)
104
     *
105
     * @param HtmlElement|HtmlElement[]|string $contents
106
     *
107
     * @return $this
108
     */
109 2982
    public function setContents($contents): self
110
    {
111 2982
        $this->contents = $contents ?? '';
112
113 2982
        return $this;
114
    }
115
116 2835
    public function __toString(): string
117
    {
118 2835
        $result = '<' . $this->tagName;
119
120 2835
        foreach ($this->attributes as $key => $value) {
121 1062
            if ($value === true) {
122 3
                $result .= ' ' . $key;
123 1062
            } elseif ($value === false) {
124 3
                continue;
125
            } else {
126 1062
                $result .= ' ' . $key . '="' . Xml::escape($value) . '"';
127
            }
128
        }
129
130 2835
        if ($this->contents !== '') {
131 2784
            $result .= '>' . $this->getContentsAsString() . '</' . $this->tagName . '>';
132 378
        } elseif ($this->selfClosing && $this->tagName === 'input') {
133 12
            $result .= '>';
134 366
        } elseif ($this->selfClosing) {
135 297
            $result .= ' />';
136
        } else {
137 75
            $result .= '></' . $this->tagName . '>';
138
        }
139
140 2835
        return $result;
141
    }
142
143 2874
    private function getContentsAsString(): string
144
    {
145 2874
        if (\is_string($this->contents)) {
146 2856
            return $this->contents;
147
        }
148
149 372
        if (\is_array($this->contents)) {
150 96
            return \implode('', $this->contents);
151
        }
152
153 366
        return (string) $this->contents;
154
    }
155
}
156