WebComponentsHelper::props()   A
last analyzed

Complexity

Conditions 6
Paths 7

Size

Total Lines 33
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 19
c 1
b 0
f 0
nc 7
nop 1
dl 0
loc 33
rs 9.0111
1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * BEdita, API-first content management framework
6
 * Copyright 2020 ChannelWeb Srl, Chialab Srl
7
 *
8
 * This file is part of BEdita: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published
10
 * by the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
14
 */
15
16
namespace BEdita\WebTools\View\Helper;
17
18
use Cake\View\Helper;
19
20
/**
21
 * Helper to handle Web Components initialization with properties.
22
 */
23
class WebComponentsHelper extends Helper
24
{
25
    /**
26
     * @inheritDoc
27
     **/
28
    public array $helpers = ['Html'];
29
30
    /**
31
     * A list of used identifiers.
32
     *
33
     * @var array
34
     **/
35
    private array $ids = [];
36
37
    /**
38
     * Pass properties to an HTMLElement using attributes for plain values and inline scripts for array.
39
     *
40
     * @param array $properties A list of properties to set.
41
     * @return array An array of attributes.
42
     */
43
    public function props(array $properties): array
44
    {
45
        if (empty($properties)) {
46
            return [];
47
        }
48
49
        $id = count($this->ids);
50
        $this->ids[] = $id;
51
52
        $attributes = [
53
            'data-wc' => $id,
54
        ];
55
        $statements = [];
56
        foreach ($properties as $key => $value) {
57
            if (is_string($value) || is_numeric($value)) {
58
                $attributes[$key] = $value;
59
            } else {
60
                $statements[] = sprintf('elem[\'%s\'] = %s;', $key, json_encode($value));
61
            }
62
        }
63
64
        if (!empty($statements)) {
65
            // @codingStandardsIgnoreStart
66
            $content = sprintf(
67
                '(function(){var elem = document.querySelector(\'[data-wc="%s"]\');%s}());if(document.currentScript)document.currentScript.parentNode.removeChild(document.currentScript);',
68
                $id,
69
                join('', $statements)
70
            );
71
            // @codingStandardsIgnoreEnd
72
            $this->Html->scriptBlock($content, [ 'block' => 'scriptsComponents' ]);
73
        }
74
75
        return $attributes;
76
    }
77
78
    /**
79
     * Initialize a Custom Element which extends a native node.
80
     *
81
     * @param string $tagName The defined Custom Element name to set as `is` attribute.
82
     * @param array $properties A list of properties to set.
83
     * @param string $scriptPath The path of the definition script to import.
84
     * @return string An attributes string list like `is="my-element" data-wc="0"`.
85
     */
86
    public function is(string $tagName, array $properties = [], string $scriptPath = ''): string
87
    {
88
        if (!empty($scriptPath)) {
89
            $this->Html->script($scriptPath, [ 'block' => 'scriptsComponents' ]);
90
        }
91
92
        $options = ['is' => $tagName] + $this->props($properties);
93
94
        return trim($this->Html->templater()->formatAttributes($options));
95
    }
96
97
    /**
98
     * Initialize a Custom Element.
99
     *
100
     * @param string $tagName The defined Custom Element name to use as tag name.
101
     * @param array $properties A list of properties to set.
102
     * @param string $scriptPath The path of the definition script to import.
103
     * @return string An HTML node string like `<my-element data-wc="0"></my-element>`.
104
     */
105
    public function element(string $tagName, array $properties = [], string $scriptPath = ''): string
106
    {
107
        if (!empty($scriptPath)) {
108
            $this->Html->script($scriptPath, [ 'block' => 'scriptsComponents' ]);
109
        }
110
111
        return $this->Html->tag($tagName, '', $this->props($properties));
112
    }
113
}
114