Passed
Push — main ( 1402e3...cedac2 )
by Thierry
18:03
created

UiBuilder::make()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 7
c 0
b 0
f 0
nc 3
nop 2
dl 0
loc 12
rs 10
1
<?php
2
3
namespace Lagdo\UiBuilder\Html;
4
5
use Closure;
6
use LogicException;
7
8
use function preg_replace;
9
use function stripos;
10
use function strlen;
11
use function strtolower;
12
use function substr;
13
use function trim;
14
15
class UiBuilder extends Support\HtmlBuilder
16
{
17
    /**
18
     * @var array<string, Closure>
19
     */
20
    protected $tagBuilders = [];
21
22
    /**
23
     * @var Scope
24
     */
25
    protected $scope;
26
27
    /**
28
     * The constructor
29
     */
30
    public function __construct()
31
    {
32
        $this->addTagBuilder('set', function(UiBuilder $builder,
33
            string $tagName, string $method, array $arguments) {
34
            if ($this->scope === null) {
35
                throw new LogicException('Attributes can be set for elements only');
36
            }
37
            $this->scope->attributes[$tagName] = $arguments[0] ?? null;
38
        });
39
    }
40
41
    /**
42
     * @return Scope|null
43
     */
44
    public function scope(): ?Scope
45
    {
46
        return $this->scope;
47
    }
48
49
    /**
50
     * @param string $tagPrefix
51
     * @param Closure $tagBuilder
52
     *
53
     * @return void
54
     */
55
    public function addTagBuilder(string $tagPrefix, Closure $tagBuilder)
56
    {
57
        // Do not overwrite existing builders.
58
        if(!isset($this->tagBuilders[$tagPrefix]))
59
        {
60
            $this->tagBuilders[$tagPrefix] = $tagBuilder;
61
        }
62
    }
63
64
    /**
65
     * @param string $method
66
     * @param array $arguments
67
     *
68
     * @return void
69
     * @throws LogicException When element is not initialized yet
70
     */
71
    public function make(string $method, array $arguments)
72
    {
73
        $tagName = strtolower(preg_replace('/(?<!^)([A-Z])/', '-$1', $method));
74
        foreach($this->tagBuilders as $tagPrefix => $tagBuilder)
75
        {
76
            if (stripos($tagName, $tagPrefix . '-') === 0) {
77
                $tagName = substr($tagName, strlen($tagPrefix) + 1);
78
                $tagBuilder($this, $tagName, $method, $arguments);
79
                return;
80
            }
81
        }
82
        $this->createScope($tagName, $arguments);
83
    }
84
85
    /**
86
     * @param string $name
87
     * @param string $value
88
     * @param bool $escape
89
     *
90
     * @return void
91
     */
92
    public function setAttribute(string $name, string $value, bool $escape = true)
93
    {
94
        $this->scope->attributes[$name] = $value;
95
        $this->scope->escapes[$name] = $escape;
96
    }
97
98
    /**
99
     * @param array $attributes
100
     * @param bool $escape
101
     *
102
     * @return self
103
     */
104
    public function setAttributes(array $attributes, bool $escape = true): self
105
    {
106
        foreach ($attributes as $name => $value) {
107
            $this->scope->attributes[$name] = $value;
108
            $this->scope->escapes[$name] = $escape;
109
        }
110
        return $this;
111
    }
112
113
    /**
114
     * @param string $name
115
     * @param array $arguments
116
     *
117
     * @return void
118
     */
119
    public function createScope(string $name, array $arguments = [])
120
    {
121
        $this->scope = new Scope($name, $arguments, $this->scope);
122
    }
123
124
    /**
125
     * @param string $name
126
     * @param array $arguments
127
     *
128
     * @return void
129
     */
130
    public function createWrapper(string $name, array $arguments = [])
131
    {
132
        $this->createScope($name, [$arguments]);
133
        $this->scope->isWrapper = true;
134
    }
135
136
    /**
137
     * Append a class to the existing one.
138
     *
139
     * @param string $class
140
     *
141
     * @return void
142
     */
143
    public function appendClass(string $class)
144
    {
145
        if ($this->scope === null) {
146
            throw new LogicException('Attributes can be set for elements only');
147
        }
148
        $class = ($this->scope->attributes['class'] ?? '') . ' ' . $class;
149
        $this->scope->attributes['class'] = trim($class);
150
    }
151
152
    /**
153
     * Prepend a class to the existing one.
154
     *
155
     * @param string $class
156
     *
157
     * @return void
158
     */
159
    public function prependClass(string $class)
160
    {
161
        if ($this->scope === null) {
162
            throw new LogicException('Attributes can be set for elements only');
163
        }
164
        $class .= ' ' . ($this->scope->attributes['class'] ?? '');
165
        $this->scope->attributes['class'] = trim($class);
166
    }
167
168
    /**
169
     * @return void
170
     */
171
    public function end()
172
    {
173
        parent::end();
174
        // Wrappers are scopes that were automatically added.
175
        // They also need to be automatically ended.
176
        // while ($this->scope !== null && $this->scope->isWrapper) {
177
        //     parent::end();
178
        // }
179
    }
180
181
    /**
182
     * @return void
183
     */
184
    public function endShorted()
185
    {
186
        parent::endShorted();
187
        // Wrappers are scopes that were automatically added.
188
        // They also need to be automatically ended.
189
        // while ($this->scope !== null && $this->scope->isWrapper) {
190
        //     parent::end();
191
        // }
192
    }
193
194
    /**
195
     * @return bool
196
     */
197
    public function isInputGroup(): bool
198
    {
199
        return $this->scope !== null && $this->scope->isInputGroup;
200
    }
201
}
202