Passed
Pull Request — master (#16)
by
unknown
02:26
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\HtmlHelper as CakeHtmlHelper;
19
20
/**
21
 * Helper to handle Web Components initialization with properties.
22
 */
23
class WebComponentsHelper extends CakeHtmlHelper
24
{
25
    private $ids = [];
26
27
    /**
28
     * Pass properties to an HTMLElement using attributes for plain values and inline scripts for array.
29
     *
30
     * @param array $properties A list of properties to set.
31
     * @return array An array of attributes.
32
     */
33
    public function props(array $properties): array
34
    {
35
        if (empty($properties)) {
36
            return [];
37
        }
38
39
        $id = count($this->ids);
40
        $this->ids[] = $id;
41
42
        $attributes = [
43
            'data-wc' => $id,
44
        ];
45
        $statements = [];
46
        foreach ($properties as $key => $value) {
47
            if (is_string($value) || is_numeric($value)) {
48
                $attributes[$key] = $value;
49
            } else {
50
                $statements[] = sprintf('elem[\'%s\'] = %s;', $key, json_encode($value));
51
            }
52
        }
53
54
        if (!empty($statements)) {
55
            $content = sprintf('(function(){var elem = document.querySelector(\'[data-wc="%s"]\');%s}());if(document.currentScript)document.currentScript.parentNode.removeChild(document.currentScript);', $id, join('', $statements));
56
            $this->scriptBlock($content, [ 'block' => 'scriptsComponents' ]);
57
        }
58
59
        return $attributes;
60
    }
61
62
    /**
63
     * Initialize a Custom Element which extends a native node.
64
     *
65
     * @param string $tagName The defined Custom Element name to set as `is` attribute.
66
     * @param array $properties A list of properties to set.
67
     * @param string $scriptPath The path of the definition script to import.
68
     * @return string An attributes string list like `is="my-element" data-wc="0"`.
69
     */
70
    public function is(string $tagName, array $properties = [], string $scriptPath = ''): string
71
    {
72
        if (!empty($scriptPath)) {
73
            $this->script($scriptPath, [ 'block' => 'scriptsComponents' ]);
74
        }
75
76
        $options = ['is' => $tagName] + $this->props($properties);
77
78
        return trim($this->templater()->formatAttributes($options));
79
    }
80
81
    /**
82
     * Initialize a Custom Element.
83
     *
84
     * @param string $tagName The defined Custom Element name to use as tag name.
85
     * @param array $properties A list of properties to set.
86
     * @param string $scriptPath The path of the definition script to import.
87
     * @return string An HTML node string like `<my-element data-wc="0"></my-element>`.
88
     */
89
    public function element(string $tagName, array $properties = [], $scriptPath = ''): string
90
    {
91
        if (!empty($scriptPath)) {
92
            $this->script($scriptPath, [ 'block' => 'scriptsComponents' ]);
93
        }
94
95
        return $this->tag($tagName, '', $this->props($properties));
96
    }
97
}
98