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

UiBuilder::endShorted()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 3
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 7
rs 10
1
<?php
2
3
namespace Lagdo\UiBuilder\Scope;
4
5
use Closure;
6
use Lagdo\UiBuilder\BuilderInterface;
7
use Lagdo\UiBuilder\Html\HtmlBuilder;
8
use Lagdo\UiBuilder\Scope\Scope;
9
use LogicException;
10
11
use function preg_replace;
12
use function stripos;
13
use function strlen;
14
use function strtolower;
15
use function substr;
16
use function trim;
17
18
class UiBuilder extends HtmlBuilder
19
{
20
    /**
21
     * @var array<string, Closure>
22
     */
23
    protected $tagBuilders = [];
24
25
    /**
26
     * @var Scope
27
     */
28
    protected $scope;
29
30
    /**
31
     * The constructor
32
     */
33
    public function __construct()
34
    {
35
        $this->addTagBuilder('set', function(BuilderInterface $builder, string $tagName, string $method, array $arguments) {
36
            if ($this->scope === null) {
37
                throw new LogicException('Attributes can be set for elements only');
38
            }
39
            $this->scope->attributes[$tagName] = $arguments[0] ?? null;
40
        });
41
        $this->addTagBuilder('form', function(BuilderInterface $builder, string $tagName, string $method, array $arguments) {
42
            $this->createScope($tagName, $arguments);
43
            // Prepend the UI framework class to the tag.
44
            $this->prependClass($this->_formTagClass($tagName));
0 ignored issues
show
Bug introduced by
$this->_formTagClass($tagName) of type void is incompatible with the type string expected by parameter $class of Lagdo\UiBuilder\Scope\UiBuilder::prependClass(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

44
            $this->prependClass(/** @scrutinizer ignore-type */ $this->_formTagClass($tagName));
Loading history...
Bug introduced by
The method _formTagClass() does not exist on Lagdo\UiBuilder\Scope\UiBuilder. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

44
            $this->prependClass($this->/** @scrutinizer ignore-call */ _formTagClass($tagName));
Loading history...
Bug introduced by
Are you sure the usage of $this->_formTagClass($tagName) targeting Lagdo\UiBuilder\Scope\UiBuilder::__call() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
45
        });
46
    }
47
48
    /**
49
     * @param string $tagPrefix
50
     * @param Closure $tagBuilder
51
     *
52
     * @return void
53
     */
54
    public function addTagBuilder(string $tagPrefix, Closure $tagBuilder)
55
    {
56
        // Do not overwrite existing builders.
57
        if(!isset($this->tagBuilders[$tagPrefix]))
58
        {
59
            $this->tagBuilders[$tagPrefix] = $tagBuilder;
60
        }
61
    }
62
63
    /**
64
     * @param string $method
65
     * @param array $arguments
66
     *
67
     * @return void
68
     * @throws LogicException When element is not initialized yet
69
     */
70
    public function make(string $method, array $arguments)
71
    {
72
        $tagName = strtolower(preg_replace('/(?<!^)([A-Z])/', '-$1', $method));
73
        foreach($this->tagBuilders as $tagPrefix => $tagBuilder)
74
        {
75
            if (stripos($tagName, $tagPrefix . '-') === 0) {
76
                $tagName = substr($tagName, strlen($tagPrefix) + 1);
77
                $tagBuilder($this, $tagName, $method, $arguments);
78
                return;
79
            }
80
        }
81
        $this->createScope($tagName, $arguments);
82
    }
83
84
    /**
85
     * @param string $name
86
     * @param string $value
87
     *
88
     * @return void
89
     */
90
    public function setAttribute(string $name, string $value)
91
    {
92
        $this->scope->attributes[$name] = $value;
93
    }
94
95
    /**
96
     * @param array $attributes
97
     *
98
     * @return self
99
     */
100
    public function setAttributes(array $attributes): self
101
    {
102
        foreach ($attributes as $name => $value) {
103
            $this->scope->attributes[$name] = $value;
104
        }
105
        return $this;
106
    }
107
108
    /**
109
     * @param string $name
110
     * @param array $arguments
111
     *
112
     * @return void
113
     */
114
    public function createScope(string $name, array $arguments = [])
115
    {
116
        $this->scope = new Scope($name, $arguments, $this->scope);
117
    }
118
119
    /**
120
     * @param string $name
121
     * @param array $arguments
122
     *
123
     * @return void
124
     */
125
    public function createWrapper(string $name, array $arguments = [])
126
    {
127
        $this->createScope($name, [$arguments]);
128
        $this->scope->isWrapper = true;
129
    }
130
131
    /**
132
     * Append a class to the existing one.
133
     *
134
     * @param string $class
135
     *
136
     * @return void
137
     */
138
    public function appendClass(string $class)
139
    {
140
        if ($this->scope === null) {
141
            throw new LogicException('Attributes can be set for elements only');
142
        }
143
        $class = ($this->scope->attributes['class'] ?? '') . ' ' . $class;
144
        $this->scope->attributes['class'] = trim($class);
145
    }
146
147
    /**
148
     * Prepend a class to the existing one.
149
     *
150
     * @param string $class
151
     *
152
     * @return void
153
     */
154
    public function prependClass(string $class)
155
    {
156
        if ($this->scope === null) {
157
            throw new LogicException('Attributes can be set for elements only');
158
        }
159
        $class .= ' ' . ($this->scope->attributes['class'] ?? '');
160
        $this->scope->attributes['class'] = trim($class);
161
    }
162
163
    /**
164
     * @return void
165
     */
166
    public function end()
167
    {
168
        parent::end();
169
        // Wrappers are scopes that were automatically added.
170
        // They also need to be automatically ended.
171
        while ($this->scope !== null && $this->scope->isWrapper) {
172
            parent::end();
173
        }
174
    }
175
176
    /**
177
     * @return void
178
     */
179
    public function endShorted()
180
    {
181
        parent::endShorted();
182
        // Wrappers are scopes that were automatically added.
183
        // They also need to be automatically ended.
184
        while ($this->scope !== null && $this->scope->isWrapper) {
185
            parent::end();
186
        }
187
    }
188
189
    /**
190
     * @return bool
191
     */
192
    public function isInputGroup(): bool
193
    {
194
        return $this->scope !== null && $this->scope->isInputGroup;
195
    }
196
}
197