This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Groundskeeper\Tokens; |
||
4 | |||
5 | use Groundskeeper\Configuration; |
||
6 | use Psr\Log\LoggerInterface; |
||
7 | |||
8 | class Element extends AbstractToken implements Cleanable, ContainsChildren, Removable |
||
9 | { |
||
10 | /** @var array */ |
||
11 | protected $attributes; |
||
12 | |||
13 | /** @var Token[] */ |
||
14 | protected $children; |
||
15 | |||
16 | /** @var string */ |
||
17 | private $name; |
||
18 | |||
19 | /** |
||
20 | * Constructor |
||
21 | */ |
||
22 | 185 | public function __construct(Configuration $configuration, |
|
23 | int $line, |
||
24 | int $position, |
||
25 | string $name, |
||
26 | array $attributes = array()) |
||
27 | { |
||
28 | 185 | parent::__construct($configuration, $line, $position); |
|
29 | |||
30 | 185 | $this->attributes = array(); |
|
31 | 185 | foreach ($attributes as $key => $value) { |
|
32 | 99 | $this->addAttribute($key, $value); |
|
33 | } |
||
34 | |||
35 | 185 | $this->children = array(); |
|
36 | |||
37 | 185 | if (!is_string($name)) { |
|
38 | throw new \InvalidArgumentException('Element name must be string type.'); |
||
39 | } |
||
40 | |||
41 | 185 | $this->name = trim(strtolower($name)); |
|
42 | 185 | } |
|
43 | |||
44 | /** |
||
45 | * Getter for 'attributes'. |
||
46 | */ |
||
47 | 2 | public function getAttributes() : array |
|
48 | { |
||
49 | 2 | $attributeArray = array(); |
|
50 | 2 | foreach ($this->attributes as $attribute) { |
|
51 | 1 | $attributeArray[$attribute->getName()] = $attribute->getValue(); |
|
52 | } |
||
53 | |||
54 | 2 | return $attributeArray; |
|
55 | } |
||
56 | |||
57 | 4 | public function getAttribute(string $key) |
|
58 | { |
||
59 | 4 | if (!$this->hasAttribute($key)) { |
|
60 | 1 | throw new \InvalidArgumentException('Invalid attribute key: ' . $key); |
|
61 | } |
||
62 | |||
63 | 3 | $attributeObject = $this->attributes[$key]; |
|
64 | |||
65 | 3 | return $attributeObject->getValue(); |
|
66 | } |
||
67 | |||
68 | /** |
||
69 | * Hasser for 'attributes'. |
||
70 | * |
||
71 | * @param string $key |
||
72 | * |
||
73 | * @return bool True if the attribute is present. |
||
74 | */ |
||
75 | 45 | public function hasAttribute(string $key) : bool |
|
76 | { |
||
77 | 45 | return array_key_exists($key, $this->attributes); |
|
78 | } |
||
79 | |||
80 | 102 | public function addAttribute(string $key, $value) |
|
81 | { |
||
82 | 102 | $key = trim(strtolower($key)); |
|
83 | 102 | if ($key === '') { |
|
84 | 1 | throw new \InvalidArgumentException('Invalid empty attribute key.'); |
|
85 | } |
||
86 | |||
87 | 101 | $attributeParameters = $this->getAttributeParameters($key); |
|
88 | 101 | $isStandard = true; |
|
89 | 101 | View Code Duplication | if (empty($attributeParameters)) { |
0 ignored issues
–
show
|
|||
90 | $attributeParameters = array( |
||
91 | 11 | 'name' => $key, |
|
92 | 11 | 'regex' => '/\S*/i', |
|
93 | 'valueType' => Attribute::CS_STRING |
||
94 | ); |
||
95 | 11 | $isStandard = false; |
|
96 | } |
||
97 | |||
98 | 101 | $this->attributes[$key] = new Attribute( |
|
99 | 101 | $key, |
|
100 | 101 | $value, |
|
101 | 101 | $attributeParameters['valueType'], |
|
0 ignored issues
–
show
The call to
Attribute::__construct() has too many arguments starting with $attributeParameters['valueType'] .
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. In this case you can add the ![]() |
|||
102 | 101 | $isStandard |
|
103 | ); |
||
104 | |||
105 | 101 | return $this; |
|
106 | } |
||
107 | |||
108 | 2 | public function removeAttribute(string $key) |
|
109 | { |
||
110 | 2 | $key = trim(strtolower($key)); |
|
111 | 2 | if (isset($this->attributes[$key])) { |
|
112 | 2 | unset($this->attributes[$key]); |
|
113 | } |
||
114 | 2 | } |
|
115 | |||
116 | /** |
||
117 | * Required by ContainsChildren interface. |
||
118 | */ |
||
119 | 3 | public function getChildren() : array |
|
120 | { |
||
121 | 3 | return $this->children; |
|
122 | } |
||
123 | |||
124 | /** |
||
125 | * Required by ContainsChildren interface. |
||
126 | */ |
||
127 | 1 | public function hasChild(Token $token) : bool |
|
128 | { |
||
129 | 1 | return in_array($token, $this->children, true); |
|
130 | } |
||
131 | |||
132 | /** |
||
133 | * Required by ContainsChildren interface. |
||
134 | */ |
||
135 | 140 | public function appendChild(Token $token) |
|
136 | { |
||
137 | 140 | $token->setParent($this); |
|
138 | 140 | $this->children[] = $token; |
|
139 | 140 | } |
|
140 | |||
141 | /** |
||
142 | * Required by ContainsChildren interface. |
||
143 | */ |
||
144 | 5 | public function prependChild(Token $token) |
|
145 | { |
||
146 | 5 | $token->setParent($this); |
|
147 | 5 | array_unshift($this->children, $token); |
|
148 | 5 | } |
|
149 | |||
150 | /** |
||
151 | * Required by the ContainsChildren interface. |
||
152 | */ |
||
153 | 39 | View Code Duplication | public function removeChild(Token $token) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
154 | { |
||
155 | 39 | $key = array_search($token, $this->children, true); |
|
156 | 39 | if ($key !== false) { |
|
157 | 39 | unset($this->children[$key]); |
|
158 | } |
||
159 | 39 | } |
|
160 | |||
161 | /** |
||
162 | * Getter for 'name'. |
||
163 | */ |
||
164 | 137 | public function getName() : string |
|
165 | { |
||
166 | 137 | return $this->name; |
|
167 | } |
||
168 | |||
169 | /** |
||
170 | * Required by the Cleanable interface. |
||
171 | */ |
||
172 | 140 | public function clean(LoggerInterface $logger) : bool |
|
173 | { |
||
174 | 140 | if ($this->configuration->get('clean-strategy') === Configuration::CLEAN_STRATEGY_NONE) { |
|
175 | 1 | return true; |
|
176 | } |
||
177 | |||
178 | // Assign attributes to the attributes. (Soooo meta ....) |
||
179 | 139 | foreach ($this->attributes as $attribute) { |
|
180 | 92 | $attributeParameters = $this->getAttributeParameters( |
|
181 | 92 | $attribute->getName() |
|
182 | ); |
||
183 | 92 | $isStandard = true; |
|
184 | 92 | View Code Duplication | if (empty($attributeParameters)) { |
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
185 | $attributeParameters = array( |
||
186 | 9 | 'name' => $attribute->getName(), |
|
187 | 9 | 'regex' => '/\S*/i', |
|
188 | 'valueType' => Attribute::UNKNOWN |
||
189 | ); |
||
190 | 9 | $isStandard = false; |
|
191 | } |
||
192 | |||
193 | 92 | $attribute->setType($attributeParameters['valueType']); |
|
194 | 92 | $attribute->setIsStandard($isStandard); |
|
195 | } |
||
196 | |||
197 | // Clean attributes. |
||
198 | 139 | foreach ($this->attributes as $attribute) { |
|
199 | 92 | $attributeCleanResult = $attribute->clean( |
|
200 | 92 | $this->configuration, |
|
201 | 92 | $this, |
|
202 | 92 | $logger |
|
203 | ); |
||
204 | 92 | if (!$attributeCleanResult && $this->configuration->get('clean-strategy') !== Configuration::CLEAN_STRATEGY_LENIENT) { |
|
205 | 92 | unset($this->attributes[$attribute->getName()]); |
|
206 | } |
||
207 | } |
||
208 | |||
209 | // Fix self (if possible) |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
40% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
210 | 139 | $this->fixSelf($logger); |
|
211 | |||
212 | // Remove self or children? |
||
213 | 139 | if ($this->configuration->get('clean-strategy') !== Configuration::CLEAN_STRATEGY_LENIENT) { |
|
214 | // Remove self? |
||
215 | 139 | if ($this->removeInvalidSelf($logger)) { |
|
216 | 32 | return false; |
|
217 | } |
||
218 | |||
219 | // Remove children? |
||
220 | 138 | $this->removeInvalidChildren($logger); |
|
221 | } |
||
222 | |||
223 | // Clean children. |
||
224 | 139 | return AbstractToken::cleanChildTokens( |
|
225 | 139 | $this->configuration, |
|
226 | 139 | $this->children, |
|
227 | 139 | $logger |
|
228 | ); |
||
229 | } |
||
230 | |||
231 | 132 | protected function fixSelf(LoggerInterface $logger) |
|
232 | { |
||
233 | 132 | } |
|
234 | |||
235 | 118 | protected function removeInvalidChildren(LoggerInterface $logger) |
|
236 | { |
||
237 | 118 | } |
|
238 | |||
239 | 129 | protected function removeInvalidSelf(LoggerInterface $logger) : bool |
|
240 | { |
||
241 | 129 | return false; |
|
242 | } |
||
243 | |||
244 | 101 | protected function getAllowedAttributes() |
|
245 | { |
||
246 | return array( |
||
247 | // Global Attributes |
||
248 | 101 | '/^accesskey$/i' => Attribute::CS_STRING, |
|
249 | '/^class$/i' => Attribute::CS_STRING, |
||
250 | '/^contenteditable$/i' => Attribute::CS_STRING, |
||
251 | '/^contextmenu$/i' => Attribute::CS_STRING, |
||
252 | '/^data-\S/i' => Attribute::CS_STRING, |
||
253 | '/^dir$/i' => Attribute::CI_ENUM . '("ltr","rtl"|"ltr")', |
||
254 | '/^draggable$/i' => Attribute::CS_STRING, |
||
255 | '/^dropzone$/i' => Attribute::CS_STRING, |
||
256 | '/^hidden$/i' => Attribute::CS_STRING, |
||
257 | '/^id$/i' => Attribute::CS_STRING, |
||
258 | '/^is$/i' => Attribute::CS_STRING, |
||
259 | '/^itemid$/i' => Attribute::CS_STRING, |
||
260 | '/^itemprop$/i' => Attribute::CS_STRING, |
||
261 | '/^itemref$/i' => Attribute::CS_STRING, |
||
262 | '/^itemscope$/i' => Attribute::CS_STRING, |
||
263 | '/^itemtype$/i' => Attribute::CS_STRING, |
||
264 | '/^lang$/i' => Attribute::CI_STRING, |
||
265 | '/^slot$/i' => Attribute::CS_STRING, |
||
266 | '/^spellcheck$/i' => Attribute::CS_STRING, |
||
267 | '/^style$/i' => Attribute::CS_STRING, |
||
268 | '/^tabindex$/i' => Attribute::CS_STRING, |
||
269 | '/^title$/i' => Attribute::CS_STRING, |
||
270 | '/^translate$/i' => Attribute::CI_ENUM . '("yes","no",""|"yes")', |
||
271 | |||
272 | // Event Handler Content Attributes |
||
273 | // https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-content-attributes |
||
274 | '/^onabort$/i' => Attribute::JS, |
||
275 | '/^onautocomplete$/i' => Attribute::JS, |
||
276 | '/^onautocompleteerror$/i' => Attribute::JS, |
||
277 | '/^onblur$/i' => Attribute::JS, |
||
278 | '/^oncancel$/i' => Attribute::JS, |
||
279 | '/^oncanplay$/i' => Attribute::JS, |
||
280 | '/^oncanplaythrough$/i' => Attribute::JS, |
||
281 | '/^onchange$/i' => Attribute::JS, |
||
282 | '/^onclick$/i' => Attribute::JS, |
||
283 | '/^onclose$/i' => Attribute::JS, |
||
284 | '/^oncontextmenu$/i' => Attribute::JS, |
||
285 | '/^oncuechange$/i' => Attribute::JS, |
||
286 | '/^ondblclick$/i' => Attribute::JS, |
||
287 | '/^ondrag$/i' => Attribute::JS, |
||
288 | '/^ondragend$/i' => Attribute::JS, |
||
289 | '/^ondragenter$/i' => Attribute::JS, |
||
290 | '/^ondragexit$/i' => Attribute::JS, |
||
291 | '/^ondragleave$/i' => Attribute::JS, |
||
292 | '/^ondragover$/i' => Attribute::JS, |
||
293 | '/^ondragstart$/i' => Attribute::JS, |
||
294 | '/^ondrop$/i' => Attribute::JS, |
||
295 | '/^ondurationchange$/i' => Attribute::JS, |
||
296 | '/^onemptied$/i' => Attribute::JS, |
||
297 | '/^onended$/i' => Attribute::JS, |
||
298 | '/^onerror$/i' => Attribute::JS, |
||
299 | '/^onfocus$/i' => Attribute::JS, |
||
300 | '/^oninput$/i' => Attribute::JS, |
||
301 | '/^oninvalid$/i' => Attribute::JS, |
||
302 | '/^onkeydown$/i' => Attribute::JS, |
||
303 | '/^onkeypress$/i' => Attribute::JS, |
||
304 | '/^onkeyup$/i' => Attribute::JS, |
||
305 | '/^onload$/i' => Attribute::JS, |
||
306 | '/^onloadeddata$/i' => Attribute::JS, |
||
307 | '/^onloadedmetadata$/i' => Attribute::JS, |
||
308 | '/^onloadstart$/i' => Attribute::JS, |
||
309 | '/^onmousedown$/i' => Attribute::JS, |
||
310 | '/^onmouseenter$/i' => Attribute::JS, |
||
311 | '/^onmouseleave$/i' => Attribute::JS, |
||
312 | '/^onmousemove$/i' => Attribute::JS, |
||
313 | '/^onmouseout$/i' => Attribute::JS, |
||
314 | '/^onmouseover$/i' => Attribute::JS, |
||
315 | '/^onmouseup$/i' => Attribute::JS, |
||
316 | '/^onwheel$/i' => Attribute::JS, |
||
317 | '/^onpause$/i' => Attribute::JS, |
||
318 | '/^onplay$/i' => Attribute::JS, |
||
319 | '/^onplaying$/i' => Attribute::JS, |
||
320 | '/^onprogress$/i' => Attribute::JS, |
||
321 | '/^onratechange$/i' => Attribute::JS, |
||
322 | '/^onreset$/i' => Attribute::JS, |
||
323 | '/^onresize$/i' => Attribute::JS, |
||
324 | '/^onscroll$/i' => Attribute::JS, |
||
325 | '/^onseeked$/i' => Attribute::JS, |
||
326 | '/^onseeking$/i' => Attribute::JS, |
||
327 | '/^onselect$/i' => Attribute::JS, |
||
328 | '/^onshow$/i' => Attribute::JS, |
||
329 | '/^onstalled$/i' => Attribute::JS, |
||
330 | '/^onsubmit$/i' => Attribute::JS, |
||
331 | '/^onsuspend$/i' => Attribute::JS, |
||
332 | '/^ontimeupdate$/i' => Attribute::JS, |
||
333 | '/^ontoggle$/i' => Attribute::JS, |
||
334 | '/^onvolumechange$/i' => Attribute::JS, |
||
335 | '/^onwaiting$/i' => Attribute::JS, |
||
336 | |||
337 | // WAI-ARIA |
||
338 | // https://w3c.github.io/aria/aria/aria.html |
||
339 | '/^role$/i' => Attribute::CI_STRING, |
||
340 | |||
341 | // ARIA global states and properties |
||
342 | '/^aria-atomic$/i' => Attribute::CS_STRING, |
||
343 | '/^aria-busy$/i' => Attribute::CS_STRING, |
||
344 | '/^aria-controls$/i' => Attribute::CS_STRING, |
||
345 | '/^aria-current$/i' => Attribute::CS_STRING, |
||
346 | '/^aria-describedby$/i' => Attribute::CS_STRING, |
||
347 | '/^aria-details$/i' => Attribute::CS_STRING, |
||
348 | '/^aria-disabled$/i' => Attribute::CS_STRING, |
||
349 | '/^aria-dropeffect$/i' => Attribute::CS_STRING, |
||
350 | '/^aria-errormessage$/i' => Attribute::CS_STRING, |
||
351 | '/^aria-flowto$/i' => Attribute::CS_STRING, |
||
352 | '/^aria-grabbed$/i' => Attribute::CS_STRING, |
||
353 | '/^aria-haspopup$/i' => Attribute::CS_STRING, |
||
354 | '/^aria-hidden$/i' => Attribute::CS_STRING, |
||
355 | '/^aria-invalid$/i' => Attribute::CS_STRING, |
||
356 | '/^aria-label$/i' => Attribute::CS_STRING, |
||
357 | '/^aria-labelledby$/i' => Attribute::CS_STRING, |
||
358 | '/^aria-live$/i' => Attribute::CS_STRING, |
||
359 | '/^aria-owns$/i' => Attribute::CS_STRING, |
||
360 | '/^aria-relevant$/i' => Attribute::CS_STRING, |
||
361 | '/^aria-roledescription$/i' => Attribute::CS_STRING, |
||
362 | |||
363 | // ARIA widget attributes |
||
364 | '/^aria-autocomplete$/i' => Attribute::CS_STRING, |
||
365 | '/^aria-checked$/i' => Attribute::CS_STRING, |
||
366 | '/^aria-expanded$/i' => Attribute::CS_STRING, |
||
367 | '/^aria-level$/i' => Attribute::CS_STRING, |
||
368 | '/^aria-modal$/i' => Attribute::CS_STRING, |
||
369 | '/^aria-multiline$/i' => Attribute::CS_STRING, |
||
370 | '/^aria-multiselectable$/i' => Attribute::CS_STRING, |
||
371 | '/^aria-orientation$/i' => Attribute::CS_STRING, |
||
372 | '/^aria-placeholder$/i' => Attribute::CS_STRING, |
||
373 | '/^aria-pressed$/i' => Attribute::CS_STRING, |
||
374 | '/^aria-readonly$/i' => Attribute::CS_STRING, |
||
375 | '/^aria-required$/i' => Attribute::CS_STRING, |
||
376 | '/^aria-selected$/i' => Attribute::CS_STRING, |
||
377 | '/^aria-sort$/i' => Attribute::CS_STRING, |
||
378 | '/^aria-valuemax$/i' => Attribute::CS_STRING, |
||
379 | '/^aria-valuemin$/i' => Attribute::CS_STRING, |
||
380 | '/^aria-valuenow$/i' => Attribute::CS_STRING, |
||
381 | '/^aria-valuetext$/i' => Attribute::CS_STRING, |
||
382 | |||
383 | // ARIA relationship attributes |
||
384 | '/^aria-activedescendant$/i' => Attribute::CS_STRING, |
||
385 | '/^aria-colcount$/i' => Attribute::CS_STRING, |
||
386 | '/^aria-colindex$/i' => Attribute::CS_STRING, |
||
387 | '/^aria-colspan$/i' => Attribute::CS_STRING, |
||
388 | '/^aria-posinset$/i' => Attribute::CS_STRING, |
||
389 | '/^aria-rowcount$/i' => Attribute::CS_STRING, |
||
390 | '/^aria-rowindex$/i' => Attribute::CS_STRING, |
||
391 | '/^aria-rowspan$/i' => Attribute::CS_STRING, |
||
392 | '/^aria-setsize$/i' => Attribute::CS_STRING |
||
393 | ); |
||
394 | } |
||
395 | |||
396 | 101 | private function getAttributeParameters(string $key) : array |
|
397 | { |
||
398 | 101 | $allowedAttributes = $this->getAllowedAttributes(); |
|
399 | 101 | foreach ($allowedAttributes as $attrRegex => $valueType) { |
|
400 | 101 | if (preg_match($attrRegex, $key) === 1) { |
|
401 | return array( |
||
402 | 100 | 'name' => $key, |
|
403 | 100 | 'regex' => $attrRegex, |
|
404 | 101 | 'valueType' => $valueType |
|
405 | ); |
||
406 | } |
||
407 | } |
||
408 | |||
409 | 11 | return array(); |
|
410 | } |
||
411 | |||
412 | /** |
||
413 | * Required by the Removable interface. |
||
414 | */ |
||
415 | 137 | public function remove(LoggerInterface $logger) |
|
416 | { |
||
417 | 137 | $hasRemovableElements = $this->configuration->get('element-blacklist') !== ''; |
|
418 | 137 | $hasRemovableTypes = $this->configuration->get('type-blacklist') !== ''; |
|
419 | 137 | foreach ($this->children as $child) { |
|
420 | // Check types. |
||
421 | 131 | if ($hasRemovableTypes && |
|
422 | 131 | !$this->configuration->isAllowedType($child->getType())) { |
|
423 | 2 | $logger->debug('Removing ' . $child); |
|
424 | 2 | $this->removeChild($child); |
|
425 | |||
426 | 2 | continue; |
|
427 | } |
||
428 | |||
429 | // Check elements. |
||
430 | 129 | if ($hasRemovableElements && |
|
431 | 129 | $child instanceof self && |
|
432 | 129 | !$this->configuration->isAllowedElement($child->getName())) { |
|
433 | 3 | $logger->debug('Removing ' . $child); |
|
434 | 3 | $this->removeChild($child); |
|
435 | |||
436 | 3 | continue; |
|
437 | } |
||
438 | |||
439 | // Check children. |
||
440 | 129 | if ($child instanceof Removable) { |
|
441 | 129 | $child->remove($logger); |
|
442 | } |
||
443 | } |
||
444 | 137 | } |
|
445 | |||
446 | /** |
||
447 | * Required by the Token interface. |
||
448 | */ |
||
449 | 9 | public function toHtml(string $prefix, string $suffix) : string |
|
450 | { |
||
451 | 9 | $output = $this->buildStartTag($prefix, $suffix); |
|
452 | 9 | if (empty($this->children)) { |
|
453 | 6 | return $output; |
|
454 | } |
||
455 | |||
456 | 7 | $output .= $this->buildChildrenHtml($prefix, $suffix); |
|
457 | |||
458 | 7 | return $output . $prefix . '</' . $this->name . '>' . $suffix; |
|
459 | } |
||
460 | |||
461 | 143 | protected function buildStartTag(string $prefix, string $suffix, bool $forceOpen = false) : string |
|
462 | { |
||
463 | 143 | $output = $prefix . '<' . $this->name; |
|
464 | 143 | foreach ($this->attributes as $attribute) { |
|
465 | 94 | $output .= ' ' . (string) $attribute; |
|
466 | } |
||
467 | |||
468 | 143 | if (!$forceOpen && empty($this->children)) { |
|
469 | 53 | return $output . '/>' . $suffix; |
|
470 | } |
||
471 | |||
472 | 139 | return $output . '>' . $suffix; |
|
473 | } |
||
474 | |||
475 | 139 | protected function buildChildrenHtml(string $prefix, string $suffix) : string |
|
476 | { |
||
477 | 139 | $output = ''; |
|
478 | 139 | foreach ($this->children as $child) { |
|
479 | $newPrefix = $prefix . |
||
480 | 135 | str_repeat( |
|
481 | 135 | ' ', |
|
482 | 135 | $this->configuration->get('indent-spaces') |
|
483 | ); |
||
484 | 135 | $output .= $child->toHtml($newPrefix, $suffix); |
|
485 | } |
||
486 | |||
487 | 139 | return $output; |
|
488 | } |
||
489 | |||
490 | 27 | public function getType() : string |
|
491 | { |
||
492 | 27 | return Token::ELEMENT; |
|
493 | } |
||
494 | |||
495 | 91 | public function __toString() |
|
496 | { |
||
497 | 91 | return '"' . $this->name . '" element (line: ' . $this->getLine() . |
|
498 | 91 | '; position: ' . $this->getPosition() . ')'; |
|
499 | } |
||
500 | } |
||
501 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.