Passed
Push — master ( 689ec5...45f08c )
by Sebastian
05:26
created

HTMLTag   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 244
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 34
eloc 68
c 3
b 0
f 0
dl 0
loc 244
rs 9.68

24 Methods

Rating   Name   Duplication   Size   Complexity  
A getAttributes() 0 3 1
A __toString() 0 3 1
A name() 0 4 1
A setSelfClosing() 0 4 1
A id() 0 4 1
A getSelfClosingChar() 0 8 3
A getStyles() 0 3 1
A create() 0 8 2
A addText() 0 4 1
A __construct() 0 5 1
A isEmptyAllowed() 0 8 2
A getGlobalOptions() 0 8 2
A getName() 0 3 1
A setEmptyAllowed() 0 4 1
A setContent() 0 4 1
A renderClose() 0 8 2
A isEmpty() 0 3 2
A render() 0 11 3
A renderContent() 0 8 2
A isSelfClosing() 0 3 1
A src() 0 4 1
A addHTML() 0 4 1
A renderOpen() 0 7 1
A href() 0 4 1
1
<?php
2
/**
3
 * File containing the class {@see \AppUtils\HTMLTag}.
4
 *
5
 * @package AppUtils
6
 * @subpackage HTML
7
 * @see \AppUtils\HTMLTag
8
 */
9
10
declare(strict_types=1);
11
12
namespace AppUtils;
13
14
use AppUtils\HTMLTag\GlobalOptions;
15
16
/**
17
 * Helper class for generating individual HTML tags,
18
 * with chainable methods.
19
 *
20
 * @package AppUtils
21
 * @subpackage HTML
22
 * @author Sebastian Mordziol <[email protected]>
23
 *
24
 * @link https://github.com/Mistralys/application-utils/wiki/HTMLTag
25
 */
26
class HTMLTag implements Interface_Stringable, Interface_Stylable, Interface_Attributable, Interface_ClassableViaAttributes
27
{
28
    use Trait_ClassableViaAttributes;
29
    use Traits_Stylable;
30
    use Traits_Attributable;
31
32
    /**
33
     * @var AttributeCollection
34
     */
35
    public $attributes;
36
37
    /**
38
     * @var string
39
     */
40
    private $name;
41
42
    /**
43
     * @var StringBuilder
44
     */
45
    public $content;
46
47
    /**
48
     * @var GlobalOptions|NULL
49
     */
50
    private static $globalOptions;
51
52
    private function __construct(string $name, AttributeCollection $attributes)
53
    {
54
        $this->name = $name;
55
        $this->attributes = $attributes;
56
        $this->content = sb();
57
    }
58
59
    /**
60
     * @return string
61
     */
62
    public function getName() : string
63
    {
64
        return $this->name;
65
    }
66
67
    public function setSelfClosing(bool $selfClosing=true) : HTMLTag
68
    {
69
        $this->selfClosing = $selfClosing;
70
        return $this;
71
    }
72
73
    public function isSelfClosing() : bool
74
    {
75
        return $this->selfClosing;
76
    }
77
78
    public function setEmptyAllowed(bool $allowed=true) : HTMLTag
79
    {
80
        $this->allowEmpty = $allowed;
81
        return $this;
82
    }
83
84
    public function isEmptyAllowed() : bool
85
    {
86
        if($this->isSelfClosing())
87
        {
88
            return true;
89
        }
90
91
        return $this->allowEmpty;
92
    }
93
94
    public static function create(string $name, ?AttributeCollection $attributes=null) : HTMLTag
95
    {
96
        if($attributes === null)
97
        {
98
            $attributes = AttributeCollection::create();
99
        }
100
101
        return new HTMLTag($name, $attributes);
102
    }
103
104
    /**
105
     * Returns true if the tag has no content, and no attributes.
106
     * By default, an empty tag is not rendered.
107
     *
108
     * @return bool
109
     */
110
    public function isEmpty() : bool
111
    {
112
        return !$this->hasAttributes() && $this->renderContent() === '';
113
    }
114
115
    // region: Rendering
116
117
    public const SELF_CLOSE_STYLE_SLASH = 'slash';
118
    public const SELF_CLOSE_STYLE_NONE = 'none';
119
120
    /**
121
     * @var bool
122
     */
123
    private $selfClosing = false;
124
125
    /**
126
     * @var bool
127
     */
128
    private $allowEmpty = false;
129
130
    public function render() : string
131
    {
132
        if(!$this->isEmptyAllowed() && $this->isEmpty())
133
        {
134
            return '';
135
        }
136
137
        return
138
            $this->renderOpen().
139
            $this->renderContent().
140
            $this->renderClose();
141
    }
142
143
    public function renderContent() : string
144
    {
145
        if($this->selfClosing)
146
        {
147
            return '';
148
        }
149
150
        return (string)$this->content;
151
    }
152
153
    public function getSelfClosingChar() : string
154
    {
155
        if($this->selfClosing && self::getGlobalOptions()->getSelfCloseStyle() === self::SELF_CLOSE_STYLE_SLASH)
156
        {
157
            return '/';
158
        }
159
160
        return '';
161
    }
162
163
    public function renderOpen() : string
164
    {
165
        return sprintf(
166
            '<%s%s%s>',
167
            $this->name,
168
            $this->attributes,
169
            $this->getSelfClosingChar()
170
        );
171
    }
172
173
    public function renderClose() : string
174
    {
175
        if($this->selfClosing)
176
        {
177
            return '';
178
        }
179
180
        return sprintf('</%s>', $this->name);
181
    }
182
183
    // endregion
184
185
    public static function getGlobalOptions() : GlobalOptions
186
    {
187
        if(!isset(self::$globalOptions))
188
        {
189
            self::$globalOptions = new GlobalOptions();
190
        }
191
192
        return self::$globalOptions;
193
    }
194
195
    public function __toString()
196
    {
197
        return $this->render();
198
    }
199
200
    // region: 2) Setting / adding content
201
202
    /**
203
     * Adds a bit of text to the content (with an automatic space at the end).
204
     *
205
     * @param string|number|StringBuilder_Interface|NULL $content
206
     * @return $this
207
     */
208
    public function addText($content) : HTMLTag
209
    {
210
        $this->content->add($content);
211
        return $this;
212
    }
213
214
    /**
215
     * Adds a bit of HTML at the end of the content.
216
     *
217
     * @param string|number|StringBuilder_Interface|NULL $content
218
     * @return $this
219
     */
220
    public function addHTML($content) : HTMLTag
221
    {
222
        $this->content->html($content);
223
        return $this;
224
    }
225
226
    public function setContent($content) : HTMLTag
227
    {
228
        $this->content = sb()->add($content);
229
        return $this;
230
    }
231
232
    // endregion
233
234
    // region: 1) Setting attributes
235
236
    public function name(string $name) : HTMLTag
237
    {
238
        $this->attributes->name($name);
239
        return $this;
240
    }
241
242
    public function id(string $id) : HTMLTag
243
    {
244
        $this->attributes->id($id);
245
        return $this;
246
    }
247
248
    public function href(string $url) : HTMLTag
249
    {
250
        $this->attributes->href($url);
251
        return $this;
252
    }
253
254
    public function src(string $url) : HTMLTag
255
    {
256
        $this->attributes->attrURL('src', $url);
257
        return $this;
258
    }
259
260
    // endregion
261
262
    public function getAttributes() : AttributeCollection
263
    {
264
        return $this->attributes;
265
    }
266
267
    public function getStyles() : StyleCollection
268
    {
269
        return $this->attributes->getStyles();
270
    }
271
}
272