Passed
Push — 5.x ( 6e3031...af6781 )
by Enjoys
11:41
created

Attribute::add()   A

Complexity

Conditions 5
Paths 7

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 11
c 2
b 0
f 1
dl 0
loc 20
ccs 11
cts 11
cp 1
rs 9.6111
cc 5
nc 7
nop 1
crap 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Enjoys\Forms;
6
7
use Enjoys\Forms\Interfaces\AttributeInterface;
8
use Webmozart\Assert\Assert;
9
use Webmozart\Assert\InvalidArgumentException;
10
11
abstract class Attribute implements AttributeInterface
12
{
13
    protected string $name = '';
14
15
    private array $values = [];
16
17
    protected bool $withoutValue = true;
18
    protected bool $fillNameAsValue = false;
19
    protected bool $multiple = false;
20
    protected string $separator = '';
21
22 300
    public function withName(string $name): AttributeInterface
23
    {
24 300
        $new = clone $this;
25 300
        $new->name = $name;
26 300
        return $new;
27
    }
28
29
30 329
    public function setWithoutValue(bool $withoutValue): AttributeInterface
31
    {
32 329
        $this->withoutValue = $withoutValue;
33 329
        return $this;
34
    }
35
36 1
    public function setFillNameAsValue(bool $fillNameAsValue): AttributeInterface
37
    {
38 1
        $this->fillNameAsValue = $fillNameAsValue;
39 1
        return $this;
40
    }
41
42 32
    public function setMultiple(bool $multiple, string $separator = ' '): AttributeInterface
43
    {
44 32
        $this->multiple = $multiple;
45 32
        $this->separator = $separator;
46 32
        return $this;
47
    }
48
49
50 3
    public function setSeparator(string $separator): AttributeInterface
51
    {
52 3
        $this->separator = $separator;
53 3
        return $this;
54
    }
55
56 324
    public function getName(): string
57
    {
58 324
        return $this->name;
59
    }
60
61 73
    public function __toString(): string
62
    {
63 73
        if ($this->getName() === '') {
64
            return '';
65
        }
66 73
        if ($this->withoutValue && empty($this->values)) {
67 21
            if ($this->fillNameAsValue) {
68 1
                return sprintf('%1$s="%1$s"', $this->getName());
69
            }
70 21
            return $this->getName();
71
        }
72
73 65
        if (!$this->withoutValue && empty($this->values)) {
74 10
            return '';
75
        }
76
77 60
        return sprintf('%s="%s"', $this->getName(), $this->getValueString());
78
    }
79
80 168
    public function getValues(): array
81
    {
82 168
        return $this->values;
83
    }
84
85 160
    public function getValueString(): string
86
    {
87 160
        return implode($this->separator, $this->getValues());
88
    }
89
90 4
    public function set(array $values): void
91
    {
92 4
        $this->clear();
93 4
        foreach ($values as $item) {
94 4
            $this->add($item);
95
        }
96
    }
97
98 318
    public function clear(): void
99
    {
100 318
        $this->values = [];
101
    }
102
103 327
    public function has(mixed $value): bool
104
    {
105 327
        return in_array($value, $this->values, true);
106
    }
107
108
109 334
    public function add(mixed $value): AttributeInterface
110
    {
111 334
        $value = $this->normalize($value);
112
113 333
        if ($value === null) {
114 138
            return $this;
115
        }
116
117 327
        if (!$this->multiple) {
118 316
            $this->clear();
119
        } else {
120 28
            $value = explode($this->separator, $value);
121
        }
122 327
        foreach ((array)$value as $item) {
123 327
            if (!$this->has($item)) {
124 327
                $this->values[] = $item;
125
            }
126
        }
127
128 327
        return $this;
129
    }
130
131 4
    public function remove(string $value): bool
132
    {
133 4
        $key = array_search($value, $this->values, true);
134
135 4
        if ($key === false) {
136 1
            return false;
137
        }
138
139 4
        unset($this->values[$key]);
140
141 4
        return true;
142
    }
143
144
    /**
145
     * @param mixed $value
146
     * @return string|null
147
     * @throws InvalidArgumentException
148
     */
149 334
    private function normalize(mixed $value): ?string
150
    {
151 334
        if ($value instanceof \Closure) {
152 5
            $value = $value();
153
        }
154
155 334
        Assert::nullOrScalar($value);
156
157 333
        return ($value === null) ? null : $this->safety((string)$value);
158
    }
159
160 327
    private function safety(string $value): string
161
    {
162 327
        return \htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401);
163
    }
164
}
165