Passed
Push — main ( 7ee73e...ea7c68 )
by Thierry
08:09
created

HtmlBuilder::__toString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
/*
4
 * This file is part of the PhpHtmlBuilder package.
5
 *
6
 * (c) Andrew Polupanov <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Lagdo\UiBuilder\Html;
13
14
use AvpLab\Element\Comment;
15
use AvpLab\Element\Element;
16
use AvpLab\Element\Text;
17
use AvpLab\Element\Tag;
18
use LogicException;
19
use RuntimeException;
20
21
use function strtolower;
22
use function preg_replace;
23
use function stripos;
24
use function substr;
25
use function implode;
26
27
/**
28
 * Provides API for easy building of HTML code in php
29
 */
30
class HtmlBuilder
31
{
32
    /**
33
     * @var Element[]
34
     */
35
    protected $elements = [];
36
37
    /**
38
     * @var Scope
39
     */
40
    protected $scope;
41
42
    /**
43
     * @param string $method
44
     * @param array $arguments
45
     * @return void
46
     * @throws LogicException When element is not initialized yet
47
     */
48
    public function __call(string $method, array $arguments)
49
    {
50
        $tagName = strtolower(preg_replace('/(?<!^)([A-Z])/', '-$1', $method));
51
        if (stripos($tagName, 'set-') === 0) {
52
            if ($this->scope === null) {
53
                throw new LogicException('Attributes can be set for elements only');
54
            }
55
            $this->scope->attributes[substr($tagName, 4)] = isset($arguments[0]) ? $arguments[0] : null;
56
            return;
57
        }
58
        $this->createScope($tagName, $arguments);
59
    }
60
61
    /**
62
     * @return void
63
     */
64
    public function clear()
65
    {
66
        $this->elements = [];
67
        $this->scope = null;
68
    }
69
70
    /**
71
     * @param string $name
72
     * @param array $arguments
73
     * @return void
74
     */
75
    protected function createScope(string $name, array $arguments = [])
76
    {
77
        $this->scope = new Scope($name, $arguments, $this->scope);
78
    }
79
80
    /**
81
     * @param Element $element
82
     * @return void
83
     */
84
    protected function addElementToScope(Element $element)
85
    {
86
        if ($this->scope === null) {
87
            $this->elements[] = $element;
88
            return;
89
        }
90
        $this->scope->elements[] = $element;
91
    }
92
93
    /**
94
     * @param string $name
95
     * @return void
96
     */
97
    public function tag(string $name, ...$arguments)
98
    {
99
        $this->createScope($name, $arguments);
100
    }
101
102
    /**
103
     * @param string $text
104
     * @return void
105
     */
106
    public function addText(string $text)
107
    {
108
        $this->addElementToScope(new Text($text));
109
    }
110
111
    /**
112
     * @param string $html
113
     * @return void
114
     */
115
    public function addHtml(string $html)
116
    {
117
        $this->addElementToScope(new Text($html, false));
118
    }
119
120
    /**
121
     * @param string $comment
122
     * @return void
123
     */
124
    public function addComment($comment)
125
    {
126
        $this->addElementToScope(new Comment($comment));
127
    }
128
129
    /**
130
     * @return void
131
     * @throws RuntimeException When element is not initialized yet.
132
     */
133
    public function end()
134
    {
135
        if ($this->scope === null) {
136
            throw new RuntimeException('Abnormal element completion');
137
        }
138
        $element = new Tag($this->scope->name, $this->scope->attributes, $this->scope->elements);
139
        $this->scope = $this->scope->parent;
140
        $this->addElementToScope($element);
141
    }
142
143
    /**
144
     * @return void
145
     * @throws RuntimeException When element is not initialized yet.
146
     */
147
    public function endShorted()
148
    {
149
        if ($this->scope === null) {
150
            throw new RuntimeException('Abnormal element completion');
151
        }
152
        $element = new Tag($this->scope->name, $this->scope->attributes);
153
        $element->setShort(true);
154
        $this->scope = $this->scope->parent;
155
        $this->addElementToScope($element);
156
    }
157
158
    /**
159
     * @return void
160
     * @throws RuntimeException When element is not initialized yet.
161
     */
162
    public function endOpened()
163
    {
164
        if ($this->scope === null) {
165
            throw new RuntimeException('Abnormal element completion');
166
        }
167
        $element = new Tag($this->scope->name, $this->scope->attributes);
168
        $element->setOpened(true);
169
        $this->scope = $this->scope->parent;
170
        $this->addElementToScope($element);
171
    }
172
173
    /**
174
     * @return string
175
     */
176
    public function build(): string
177
    {
178
        return implode('', $this->elements);
179
    }
180
}
181