Passed
Pull Request — 4 (#10033)
by Maxime
06:42
created

AttributesHTML   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 119
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 36
dl 0
loc 119
rs 10
c 1
b 0
f 0
wmc 15

4 Methods

Rating   Name   Duplication   Size   Complexity  
B getAttributesHTML() 0 43 10
A setAttribute() 0 5 1
A getAttributes() 0 11 2
A getAttribute() 0 9 2
1
<?php
2
3
namespace SilverStripe\View;
4
5
use SilverStripe\Core\Convert;
6
7
/**
8
 * This trait can be applied to a ViewableData class to add the logic to render attributes in an SS template.
9
 *
10
 * When applying this trait to a class, you also need to add the following casting configuration.
11
 * ```
12
 * private static $casting = [
13
 *     'AttributesHTML' => 'HTMLFragment',
14
 *     'getAttributesHTML' => 'HTMLFragment',
15
 * ];
16
 * ```
17
 */
18
trait AttributesHTML
19
{
20
21
    /**
22
     * List of attributes to render on the frontend
23
     * @var array
24
     */
25
    protected $attributes = [];
26
27
    /**
28
     * Set an HTML attribute
29
     * @param $name
30
     * @param $value
31
     * @return $this
32
     */
33
    public function setAttribute($name, $value)
34
    {
35
        $this->attributes[$name] = $value;
36
37
        return $this;
38
    }
39
40
    /**
41
     * Retrieve the value of an HTML attribute
42
     * @param string $name
43
     * @return mixed|null
44
     */
45
    public function getAttribute($name)
46
    {
47
        $attributes = $this->getAttributes();
48
49
        if (isset($attributes[$name])) {
50
            return $attributes[$name];
51
        }
52
53
        return null;
54
    }
55
56
    /**
57
     * Get the default attributes when rendering this object.
58
     *
59
     * Called by `getAttributes()`
60
     *
61
     * @return array
62
     */
63
    abstract protected function getDefaultAttributes(): array;
64
65
    /**
66
     * Allows customization through an 'updateAttributes' hook on the base class.
67
     * Existing attributes are passed in as the first argument and can be manipulated,
68
     * but any attributes added through a subclass implementation won't be included.
69
     *
70
     * @return array
71
     */
72
    public function getAttributes()
73
    {
74
        $defaultAttributes = $this->getDefaultAttributes();
75
76
        $attributes = array_merge($defaultAttributes, $this->attributes);
77
78
        if (method_exists($this, 'extend')) {
79
            $this->extend('updateAttributes', $attributes);
80
        }
81
82
        return $attributes;
83
    }
84
85
    /**
86
     * Custom attributes to process. Falls back to {@link getAttributes()}.
87
     *
88
     * If at least one argument is passed as a string, all arguments act as excludes, by name.
89
     *
90
     * @param array $attributes
91
     *
92
     * @return string
93
     */
94
    public function getAttributesHTML($attributes = null)
95
    {
96
        $exclude = null;
97
98
        if (is_string($attributes)) {
99
            $exclude = func_get_args();
100
        }
101
102
        if (!$attributes || is_string($attributes)) {
103
            $attributes = $this->getAttributes();
104
        }
105
106
        $attributes = (array) $attributes;
107
108
        $attributes = array_filter($attributes, function ($v) {
109
            return ($v || $v === 0 || $v === '0');
110
        });
111
112
        if ($exclude) {
113
            $attributes = array_diff_key(
114
                $attributes,
115
                array_flip($exclude)
116
            );
117
        }
118
119
        // Create markup
120
        $parts = [];
121
122
        foreach ($attributes as $name => $value) {
123
            if ($value === true) {
124
                $value = $name;
125
            } else {
126
                if (is_scalar($value)) {
127
                    $value = (string) $value;
128
                } else {
129
                    $value = json_encode($value);
130
                }
131
            }
132
133
            $parts[] = sprintf('%s="%s"', Convert::raw2att($name), Convert::raw2att($value));
0 ignored issues
show
Bug introduced by
It seems like SilverStripe\Core\Convert::raw2att($name) can also be of type array and array; however, parameter $values of sprintf() does only seem to accept double|integer|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

133
            $parts[] = sprintf('%s="%s"', /** @scrutinizer ignore-type */ Convert::raw2att($name), Convert::raw2att($value));
Loading history...
134
        }
135
136
        return implode(' ', $parts);
137
    }
138
}
139