Passed
Push — main ( 766fea...b9eea3 )
by Sammy
07:20 queued 14s
created

Element::__get()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace HexMakina\Marker;
6
7
/**
8
 * The Element class provides a simple and useful implementation for creating,  and generating valid HTML elements using PHP
9
 * The __toString() method of the Element class generates the HTML code for the element based on its tag, attributes, and inner content
10
 *
11
 * Additionally, the Element class provides a static shorthand syntax, using __callStatic() matching the name of the HTML Element to create
12
 *
13
 * The first argument is the inner content and the second, the attributes
14
 *
15
 * $abbr = Element::abbr('RTFM', ['title' => 'read the file manual']);
16
 * $p = Element:p('You reading this means you know about '.$abbr);
17
 * echo $p; // <p>You reading this means you know about <abbr title="read the file manual">RTFM</abbr></p>
18
 *
19
 * ::span('inner text', ['class' => 'd-block'])
20
 * ::p('lorem ipsum')
21
 * ::img(null, ['src' => 'path/to/jpeg.png', alt='hyper descriptive', 'width' => 100, 'height'=>100])
22
 * ::a('click here', ['href' => 'url/to/destination', 'class' => 'nav-link'])
23
 * ::a('anchor title', ['name' => 'anchor_name'])
24
 *
25
 * Regarding the attributes array, the keys represent the attribute names, and the values represent the attribute values.
26
 * If an attribute key is an integer, the corresponding attribute name and value are treated as a boolean attribute.
27
 *
28
 *
29
 * Example usage:
30
 *
31
 * ```
32
 * $element = new Element('section', 'Hello World!', [
33
 *     'id' => 'publication',
34
 *     'class' => 'container',
35
 *     'data-toggle' => 'modal',
36
 *     'data-target' => '#myModal',
37
 * ]);
38
 *
39
 * <section id="publication" class="container" data-toggle="modal" "data-target"="#myModal">Hello World!</section>
40
 * ```
41
 *
42
 * Or, with void element and boolean attributes:
43
 *
44
 * $element = new Element('input', null, [
45
 *      'type' => 'checkbox',
46
 *      'checked',
47
 *      'disabled',
48
 *      'class' => ['button', 'checkbutton']
49
 * ]);
50
 *
51
 * <input type="checkbox" checked="checked" disabled="disabled" class="button checkbutton"/>
52
 *
53
 */
54
55
class Element
56
{
57
    protected string $tag;
58
    protected ?string $inner;
59
    protected array $attributes = [];
60
61
    // shorthand syntax for creating elements
62
    public static function __callStatic(string $tag, array $arguments): Element
63
    {
64
        return new Element($tag, $arguments[0] ?? null, $arguments[1] ?? []);
65
    }
66
67
    /**
68
     * Creates a new Element instance.
69
     * A null $inner means that the HTML element is a void element, ie br, hr, img, etc.
70
     * 
71
     * @param string $tag HTML tag, ie span, div, p, etc.
72
     * @param string|null $inner what will be inside the tag (null means void element)
73
     * @param mixed[] $attributes An array of attributes for the element (optional).
74
     * 
75
     */
76
    public function __construct(string $tag, string $inner = null, array $attributes = [])
77
    {
78
        $this->tag = $tag;
79
        $this->inner = $inner;
80
        foreach ($attributes as $name => $value) {
81
            if (is_int($name)) {
82
                $name = $value;
83
            }
84
            $this->$name = $value;
85
        }
86
    }
87
88
    /**
89
     * Magic method to set element attributes.
90
     *
91
     * If the value is null, empty string or empty array, the attribute is removed.
92
     * If the value is an array, it is imploded using a space character.
93
     * 
94
     * @param string $name The name of the attribute.
95
     * @param mixed $value The value of the attribute.
96
     * @return void
97
     */
98
    public function __set(string $name, $value = null)
99
    {
100
        // for class="class1 class2" syntax
101
        if (is_array($value)) 
102
        {
103
            // sets value to null to trigger unset() later
104
            $value = empty($value) ? null : implode(' ', $value);
105
        }
106
107
        // remove empty attributes
108
        if ($value === null || $value === '') 
109
        {
110
            unset($this->attributes[$name]);
111
        } 
112
        else 
113
        {
114
            $this->attributes[$name] = $value;
115
        }
116
    }
117
118
    /**
119
     * Magic method to get the value of an attribute.
120
     *
121
     * @param string $name The name of the attribute.
122
     * @return string|null The value of the attribute, or null if it doesn't exist.
123
     */
124
125
    public function __get(string $name)
126
    {
127
        return $this->attributes[$name] ?? '';
128
    }
129
130
    /**
131
     * This method returns the string representation of the Element object by formatting the tag, attributes, and inner
132
     * of the element based on whether it is a void element or not. If the element is a void element, it returns the tag and
133
     * attributes only. Otherwise, it returns the tag, attributes, inner, and closing tag.
134
     *
135
     * @return string The string representation of the Element object.
136
     */
137
    public function __toString(): string
138
    {
139
        $attributes = '';
140
141
        if(!empty($this->attributes))
142
        {
143
            $attributes = array_walk($this->attributes, function(&$value, $key){
0 ignored issues
show
Unused Code introduced by
The assignment to $attributes is dead and can be removed.
Loading history...
144
                $value = sprintf('%s="%s"', $key, $value);
145
            });
146
147
            $attributes = ' ' . implode(' ', $this->attributes);
148
        }
149
150
        return is_null($this->inner)
151
            ? sprintf('<%s%s/>', $this->tag, $attributes)
152
            : sprintf('<%s%s>%s</%s>', $this->tag, $attributes, $this->inner, $this->tag);
153
    }
154
}
155