Element::__construct()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
cc 4
eloc 8
c 5
b 0
f 0
nc 6
nop 4
dl 0
loc 15
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace HexMakina\Marker;
6
7
class Element
8
{
9
    protected string $tag;
10
    protected ?string $inner = null;
11
    protected array $attributes = [];
12
    protected $formatter = null;
13
14
    // magic method to create an instance of Element statically
15
    public static function __callStatic(string $tag, array $arguments): self
16
    {
17
        return new self($tag, $arguments[0] ?? null, $arguments[1] ?? [], $arguments[2] ?? null);
18
    }
19
20
    /**
21
     * Element constructor.
22
     * 
23
     * The attributes array can contain:
24
     *  - boolean attributes ['checked', 'selected', 'disabled'], which are set to their name
25
     *  - string attributes ['id' => 'foo', 'name' => 'bar', 'class' => "foo bar"]
26
     *  - a mix of both ['id' => 'foo', 'checked', 'class' => "foo bar"]
27
     * 
28
     * If not provided, the default callable $formatter uses htmlspecialchars with ENT_QUOTES
29
     * 
30
     * @param string $tag HTML tag name
31
     * @param string $inner inner HTML content
32
     * @param array $attributes HTML attributes
33
     * @param callable|bool $formatter function to format attribute values and inner content
34
     */
35
    public function __construct(string $tag, string $inner = null, array $attributes = [], $formatter = null)
36
    {
37
        $this->tag = $tag;
38
        $this->inner = $inner;
39
        
40
        foreach ($attributes as $name => $value) {
41
            // is boolean attribute ?
42
            if (is_int($name)) {
43
                $this->$value = true;
44
            } else {
45
                $this->$name = $value;
46
            }
47
        }
48
49
        $this->formatter = $formatter === false ? fn($v) => $v : $formatter ?? fn($value) => htmlspecialchars($value ?? '', ENT_QUOTES);
50
    }
51
52
    // magic methods to set, get, check and unset attributes
53
    // for boolean attribute, set to true
54
    public function __set(string $name, $value = null)
55
    {
56
        $this->attributes[$name] = is_array($value) ? implode(' ', $value) : $value;
57
    }
58
59
    public function __get(string $name)
60
    {
61
        return $this->attributes[$name] ?? null;
62
    }
63
64
    public function __isset(string $name): bool
65
    {
66
        return isset($this->attributes[$name]);
67
    }
68
69
    public function __unset(string $name)
70
    {
71
        unset($this->attributes[$name]);
72
    }
73
74
    // magic method to render the HTML element
75
    public function __toString(): string
76
    {
77
        $attributes = '';
78
79
        foreach ($this->attributes as $name => $value) {
80
            $name = ($this->formatter)($name);
81
            $attributes .= ' ' . ($value === true ? $name : sprintf('%s="%s"', $name, ($this->formatter)((string)$value)));
82
        }
83
84
        return $this->inner === null
85
            ? sprintf('<%s%s/>', $this->tag, $attributes)
86
            : sprintf('<%s%s>%s</%s>', $this->tag, $attributes, ($this->formatter)($this->inner), $this->tag);
87
    }
88
}
89