Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
28 / 28
100.00% covered (success)
100.00%
11 / 11
CRAP
100.00% covered (success)
100.00%
1 / 1
Element
100.00% covered (success)
100.00%
28 / 28
100.00% covered (success)
100.00%
11 / 11
17
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isAllowedAttribute
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAttribute
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setAttribute
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 setCustomData
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 removeAttribute
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 generateOpeningTag
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
3
 renderFirstVisit
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 generateClosingTag
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 renderLastVisit
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3/**
4 * @author: Doug Wilbourne (dougwilbourne@gmail.com)
5 */
6
7declare(strict_types=1);
8
9namespace pvc\html\element;
10
11use Psr\Container\ContainerExceptionInterface;
12use Psr\Container\NotFoundExceptionInterface;
13use pvc\html\attribute\GlobalAttributes;
14use pvc\html\attributes\AccesskeyTrait;
15use pvc\html\attributes\ClassTrait;
16use pvc\html\attributes\ContenteditableTrait;
17use pvc\html\attributes\DirTrait;
18use pvc\html\attributes\DraggableTrait;
19use pvc\html\attributes\EnterkeyhintTrait;
20// use pvc\html\attributes\HiddenTrait;
21use pvc\html\attributes\IdTrait;
22// use pvc\html\attributes\InertTrait;
23use pvc\html\attributes\InputmodeTrait;
24use pvc\html\attributes\LangTrait;
25// use pvc\html\attributes\PopoverTrait;
26use pvc\html\attributes\SpellcheckTrait;
27use pvc\html\attributes\TabindexTrait;
28use pvc\html\attributes\TranslateTrait;
29use pvc\html\dom\DomElement;
30use pvc\html\err\InvalidAttributeException;
31use pvc\html\events\OnabortTrait;
32use pvc\html\events\OnauxclickTrait;
33use pvc\html\events\OnbeforeinputTrait;
34use pvc\html\events\OnbeforematchTrait;
35use pvc\html\events\OnbeforetoggleTrait;
36use pvc\html\events\OnblurTrait;
37use pvc\html\events\OncancelTrait;
38use pvc\html\events\OncanplaythroughTrait;
39use pvc\html\events\OncanplayTrait;
40use pvc\html\events\OnchangeTrait;
41use pvc\html\events\OnclickTrait;
42use pvc\html\events\OncloseTrait;
43use pvc\html\events\OncontextlostTrait;
44use pvc\html\events\OncontextmenuTrait;
45use pvc\html\events\OncontextrestoredTrait;
46use pvc\html\events\OncopyTrait;
47use pvc\html\events\OncuechangeTrait;
48use pvc\html\events\OncutTrait;
49use pvc\html\events\OndblclickTrait;
50use pvc\html\events\OndragendTrait;
51use pvc\html\events\OndragenterTrait;
52use pvc\html\events\OndragleaveTrait;
53use pvc\html\events\OndragoverTrait;
54use pvc\html\events\OndragstartTrait;
55use pvc\html\events\OndragTrait;
56use pvc\html\events\OndropTrait;
57use pvc\html\events\OndurationchangeTrait;
58use pvc\html\events\OnemptiedTrait;
59use pvc\html\events\OnendedTrait;
60use pvc\html\events\OnerrorTrait;
61use pvc\html\events\OnfocusTrait;
62use pvc\html\events\OnformdataTrait;
63use pvc\html\events\OninputTrait;
64use pvc\html\events\OninvalidTrait;
65use pvc\html\events\OnkeydownTrait;
66use pvc\html\events\OnkeypressTrait;
67use pvc\html\events\OnkeyupTrait;
68use pvc\html\events\OnloadeddataTrait;
69use pvc\html\events\OnloadedmetadataTrait;
70use pvc\html\events\OnloadstartTrait;
71use pvc\html\events\OnloadTrait;
72use pvc\html\events\OnmousedownTrait;
73use pvc\html\events\OnmouseenterTrait;
74use pvc\html\events\OnmouseleaveTrait;
75use pvc\html\events\OnmousemoveTrait;
76use pvc\html\events\OnmouseoutTrait;
77use pvc\html\events\OnmouseoverTrait;
78use pvc\html\events\OnmouseupTrait;
79use pvc\html\events\OnpasteTrait;
80use pvc\html\events\OnpauseTrait;
81use pvc\html\events\OnplayingTrait;
82use pvc\html\events\OnplayTrait;
83use pvc\html\events\OnprogressTrait;
84use pvc\html\events\OnratechangeTrait;
85use pvc\html\events\OnresetTrait;
86use pvc\html\events\OnresizeTrait;
87use pvc\html\events\OnscrollendTrait;
88use pvc\html\events\OnscrollTrait;
89use pvc\html\events\OnsecuritypolicyviolationTrait;
90use pvc\html\events\OnseekedTrait;
91use pvc\html\events\OnseekingTrait;
92use pvc\html\events\OnselectTrait;
93use pvc\html\events\OnslotchangeTrait;
94use pvc\html\events\OnstalledTrait;
95use pvc\html\events\OnsubmitTrait;
96use pvc\html\events\OnsuspendTrait;
97use pvc\html\events\OntimeupdateTrait;
98use pvc\html\events\OntoggleTrait;
99use pvc\html\events\OnvolumechangeTrait;
100use pvc\html\events\OnwaitingTrait;
101use pvc\html\events\OnwebkitanimationendTrait;
102use pvc\html\events\OnwebkitanimationiterationTrait;
103use pvc\html\events\OnwebkitanimationstartTrait;
104use pvc\html\events\OnwebkittransitionendTrait;
105use pvc\html\events\OnwheelTrait;
106use pvc\html\factory\HtmlFactory;
107use pvc\interfaces\html\attribute\AttributeCustomDataInterface;
108use pvc\interfaces\html\attribute\AttributeInterface;
109use pvc\interfaces\html\attribute\AttributeWithValueInterface;
110use pvc\interfaces\html\element\ElementInterface;
111
112/**
113 *
114 * class Element
115 * @phpstan-import-type ValueType from AttributeWithValueInterface
116 */
117class Element extends DomElement implements ElementInterface
118{
119    /**
120     * @var array<string, AttributeInterface>
121     */
122    public array $attributes = [];
123
124    /**
125     * @param  string  $name
126     * @param  array  $allowedAttributes
127     * @param  HtmlFactory  $htmlFactory
128     */
129    public function __construct(
130        public readonly string $name,
131        /**
132         * @var array<string>
133         */
134        protected array $allowedAttributes,
135        public readonly HtmlFactory $htmlFactory
136    )
137    {
138    }
139
140    public function getName(): string
141    {
142        return $this->name;
143    }
144
145    /**
146     * @param  string  $attribute
147     *
148     * @return bool
149     */
150    private function isAllowedAttribute(string $attribute): bool
151    {
152        return in_array($attribute, array_merge(GlobalAttributes::attributeNames(), $this->allowedAttributes));
153    }
154
155    public function getAttribute(string $name): ?AttributeInterface
156    {
157        return $this->attributes[$name] ?? null;
158    }
159
160    /**
161     * @param  string  $name
162     * @param ValueType ...$values
163     *
164     * @return ElementInterface
165     * @throws InvalidAttributeException
166     * @throws ContainerExceptionInterface
167     * @throws NotFoundExceptionInterface
168     */
169    public function setAttribute(string $name, ...$values): ElementInterface
170    {
171        if (!$this->isAllowedAttribute($name)) {
172            throw new InvalidAttributeException($name);
173        }
174        if (!$attribute = $this->getAttribute($name)) {
175            $attribute = $this->htmlFactory->makeAttribute($name);
176            $this->attributes[$name] = $attribute;
177        }
178        if ($attribute instanceof AttributeWithValueInterface) {
179            $attribute->setValue(...$values);
180        }
181        return $this;
182    }
183
184    /**
185     * @param AttributeCustomDataInterface  $customData
186     * @param ValueType ...$values
187     *
188     * @return void
189     */
190    public function setCustomData(AttributeCustomDataInterface $customData, ...$values): void
191    {
192        $customData->setValue(...$values);
193        $this->attributes[$customData->getName()] = $customData;
194    }
195
196    /**
197     * removeAttribute
198     *
199     * @param string  $name
200     */
201    public function removeAttribute(string $name): void
202    {
203        unset($this->attributes[$name]);
204    }
205
206
207    /**
208     * generateOpeningTag
209     *
210     * @return string
211     */
212    protected function generateOpeningTag(): string
213    {
214        $z = '<' . $this->name;
215
216        $callback = function (AttributeInterface $attribute) {
217            return $attribute->render();
218        };
219
220        $attributes = implode(' ', array_map($callback, $this->attributes));
221
222        $z .= (strlen($attributes) > 0) ? ' ' . $attributes : '';
223
224        /**
225         * if this is a void tag, add the trailing slash
226         */
227        if (VoidElements::isVoid($this->name)) {
228            $z .= '/';
229        }
230
231        $z .= '>';
232        return $z;
233    }
234
235    public function renderFirstVisit(): string
236    {
237        return $this->generateOpeningTag();
238    }
239
240    /**
241     * generateClosingTag
242     * @return string
243     */
244    protected function generateClosingTag(): string
245    {
246        return '</' . $this->name . '>';
247    }
248
249    public function renderLastVisit(): string
250    {
251        return (VoidElements::isVoid($this->name)) ? '' : $this->generateClosingTag();
252    }
253
254    /**
255     * global attributes
256     */
257    use AccesskeyTrait;
258    use ClassTrait;
259    use ContenteditableTrait;
260    use DirTrait;
261    use DraggableTrait;
262    use EnterkeyhintTrait;
263    //use HiddenTrait;
264    use IdTrait;
265    //use InertTrait;
266    use InputmodeTrait;
267    use LangTrait;
268    //use PopoverTrait;
269    use SpellcheckTrait;
270    use TabindexTrait;
271    use TranslateTrait;
272
273    /**
274     * events
275     */
276    use OnabortTrait;
277    use OnauxclickTrait;
278    use OnbeforeinputTrait;
279    use OnbeforematchTrait;
280    use OnbeforetoggleTrait;
281    use OnblurTrait;
282    use OncancelTrait;
283    use OncanplayTrait;
284    use OncanplaythroughTrait;
285    use OnchangeTrait;
286    use OnclickTrait;
287    use OncloseTrait;
288    use OncontextlostTrait;
289    use OncontextmenuTrait;
290    use OncontextrestoredTrait;
291    use OncopyTrait;
292    use OncuechangeTrait;
293    use OncutTrait;
294    use OndblclickTrait;
295    use OndragTrait;
296    use OndragendTrait;
297    use OndragenterTrait;
298    use OndragleaveTrait;
299    use OndragoverTrait;
300    use OndragstartTrait;
301    use OndropTrait;
302    use OndurationchangeTrait;
303    use OnemptiedTrait;
304    use OnendedTrait;
305    use OnerrorTrait;
306    use OnfocusTrait;
307    use OnformdataTrait;
308    use OninputTrait;
309    use OninvalidTrait;
310    use OnkeydownTrait;
311    use OnkeypressTrait;
312    use OnkeyupTrait;
313    use OnloadTrait;
314    use OnloadeddataTrait;
315    use OnloadedmetadataTrait;
316    use OnloadstartTrait;
317    use OnmousedownTrait;
318    use OnmouseenterTrait;
319    use OnmouseleaveTrait;
320    use OnmousemoveTrait;
321    use OnmouseoutTrait;
322    use OnmouseoverTrait;
323    use OnmouseupTrait;
324    use OnpasteTrait;
325    use OnpauseTrait;
326    use OnplayTrait;
327    use OnplayingTrait;
328    use OnprogressTrait;
329    use OnratechangeTrait;
330    use OnresetTrait;
331    use OnresizeTrait;
332    use OnscrollTrait;
333    use OnscrollendTrait;
334    use OnsecuritypolicyviolationTrait;
335    use OnseekedTrait;
336    use OnseekingTrait;
337    use OnselectTrait;
338    use OnslotchangeTrait;
339    use OnstalledTrait;
340    use OnsubmitTrait;
341    use OnsuspendTrait;
342    use OntimeupdateTrait;
343    use OntoggleTrait;
344    use OnvolumechangeTrait;
345    use OnwaitingTrait;
346    use OnwebkitanimationendTrait;
347    use OnwebkitanimationiterationTrait;
348    use OnwebkitanimationstartTrait;
349    use OnwebkittransitionendTrait;
350    use OnwheelTrait;
351}