Passed
Pull Request — master (#16)
by
unknown
02:00
created

WebComponentsHelper::props()   A

Complexity

Conditions 6
Paths 7

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 16
c 1
b 0
f 0
nc 7
nop 1
dl 0
loc 27
rs 9.1111
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
    public $helpers = ['Html'];
26
27
    /**
28
     * @var array A list of used identifiers.
29
     **/
30
    private $ids = [];
31
32
    /**
33
     * Pass properties to an HTMLElement using attributes for plain values and inline scripts for array.
34
     *
35
     * @param array $properties A list of properties to set.
36
     * @return array An array of attributes.
37
     */
38
    public function props(array $properties): array
39
    {
40
        if (empty($properties)) {
41
            return [];
42
        }
43
44
        $id = count($this->ids);
45
        $this->ids[] = $id;
46
47
        $attributes = [
48
            'data-wc' => $id,
49
        ];
50
        $statements = [];
51
        foreach ($properties as $key => $value) {
52
            if (is_string($value) || is_numeric($value)) {
53
                $attributes[$key] = $value;
54
            } else {
55
                $statements[] = sprintf('elem[\'%s\'] = %s;', $key, json_encode($value));
56
            }
57
        }
58
59
        if (!empty($statements)) {
60
            $content = sprintf('(function(){var elem = document.querySelector(\'[data-wc="%s"]\');%s}());if(document.currentScript)document.currentScript.parentNode.removeChild(document.currentScript);', $id, join('', $statements));
61
            $this->Html->scriptBlock($content, [ 'block' => 'scriptsComponents' ]);
62
        }
63
64
        return $attributes;
65
    }
66
67
    /**
68
     * Initialize a Custom Element which extends a native node.
69
     *
70
     * @param string $tagName The defined Custom Element name to set as `is` attribute.
71
     * @param array $properties A list of properties to set.
72
     * @param string $scriptPath The path of the definition script to import.
73
     * @return string An attributes string list like `is="my-element" data-wc="0"`.
74
     */
75
    public function is(string $tagName, array $properties = [], string $scriptPath = ''): string
76
    {
77
        if (!empty($scriptPath)) {
78
            $this->Html->script($scriptPath, [ 'block' => 'scriptsComponents' ]);
79
        }
80
81
        $options = ['is' => $tagName] + $this->props($properties);
82
83
        return trim($this->Html->templater()->formatAttributes($options));
84
    }
85
86
    /**
87
     * Initialize a Custom Element.
88
     *
89
     * @param string $tagName The defined Custom Element name to use as tag name.
90
     * @param array $properties A list of properties to set.
91
     * @param string $scriptPath The path of the definition script to import.
92
     * @return string An HTML node string like `<my-element data-wc="0"></my-element>`.
93
     */
94
    public function element(string $tagName, array $properties = [], $scriptPath = ''): string
95
    {
96
        if (!empty($scriptPath)) {
97
            $this->Html->script($scriptPath, [ 'block' => 'scriptsComponents' ]);
98
        }
99
100
        return $this->Html->tag($tagName, '', $this->props($properties));
101
    }
102
}
103