Passed
Pull Request — master (#192)
by Alexander
04:44 queued 02:17
created

PartsField::generateHint()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form\Field\Base;
6
7
use InvalidArgumentException;
8
use Stringable;
9
use Yiisoft\Form\Field\Part\Error;
10
use Yiisoft\Form\Field\Part\Hint;
11
use Yiisoft\Form\Field\Part\Label;
12
13
use function in_array;
14
15
abstract class PartsField extends BaseField
16
{
17
    private const BUILTIN_TOKENS = [
18
        '{input}',
19
        '{label}',
20
        '{hint}',
21
        '{error}',
22
    ];
23
24
    /**
25
     * @var string[]|Stringable[]
26
     * @psalm-var array<non-empty-string,string|Stringable>
27
     */
28
    private array $extraTokens = [];
29
30
    protected string $templateBegin = "{label}\n{input}";
31
    protected string $templateEnd = "{input}\n{hint}\n{error}";
32
    protected string $template = "{label}\n{input}\n{hint}\n{error}";
33
    protected ?bool $hideLabel = null;
34
35
    private array $labelConfig = [];
36
    private array $hintConfig = [];
37
    private array $errorConfig = [];
38
39 2
    final public function tokens(array $tokens): static
40
    {
41 2
        $new = clone $this;
42
43 2
        foreach ($tokens as $token => $value) {
44 1
            if (!is_string($token)) {
45
                throw new InvalidArgumentException(
46
                    sprintf(
47
                        'Token should be string. %s given.',
48
                        $token,
49
                    )
50
                );
51
            }
52
53 1
            if (!is_string($value) && !$value instanceof Stringable) {
54
                throw new InvalidArgumentException(
55
                    sprintf(
56
                        'Token value should be string or Stringable. %s given.',
57
                        get_debug_type($value),
58
                    )
59
                );
60
            }
61
62 1
            $this->validateToken($token);
63
64 1
            $new->extraTokens[$token] = $value;
65
        }
66
67 2
        return $new;
68
    }
69
70 4
    final public function token(string $token, string|Stringable $value): static
71
    {
72 4
        $this->validateToken($token);
73
74 2
        $new = clone $this;
75 2
        $new->extraTokens[$token] = $value;
76 2
        return $new;
77
    }
78
79
    /**
80
     * Set layout template for render a field.
81
     */
82 4
    final public function template(string $template): static
83
    {
84 4
        $new = clone $this;
85 4
        $new->template = $template;
86 4
        return $new;
87
    }
88
89 1
    final public function templateBegin(string $template): static
90
    {
91 1
        $new = clone $this;
92 1
        $new->templateBegin = $template;
93 1
        return $new;
94
    }
95
96 1
    final public function templateEnd(string $template): static
97
    {
98 1
        $new = clone $this;
99 1
        $new->templateEnd = $template;
100 1
        return $new;
101
    }
102
103 18
    final public function hideLabel(?bool $hide = true): static
104
    {
105 18
        $new = clone $this;
106 18
        $new->hideLabel = $hide;
107 18
        return $new;
108
    }
109
110 4
    final public function labelConfig(array $config): static
111
    {
112 4
        $new = clone $this;
113 4
        $new->labelConfig = $config;
114 4
        return $new;
115
    }
116
117 3
    final public function label(?string $content): static
118
    {
119 3
        $new = clone $this;
120 3
        $new->labelConfig['content()'] = [$content];
121 3
        return $new;
122
    }
123
124 3
    final public function hintConfig(array $config): static
125
    {
126 3
        $new = clone $this;
127 3
        $new->hintConfig = $config;
128 3
        return $new;
129
    }
130
131 3
    final public function hint(?string $content): static
132
    {
133 3
        $new = clone $this;
134 3
        $new->hintConfig['content()'] = [$content];
135 3
        return $new;
136
    }
137
138 3
    final public function errorConfig(array $config): static
139
    {
140 3
        $new = clone $this;
141 3
        $new->errorConfig = $config;
142 3
        return $new;
143
    }
144
145 2
    final public function error(?string $message): static
146
    {
147 2
        $new = clone $this;
148 2
        $new->errorConfig['message()'] = [$message];
149 2
        return $new;
150
    }
151
152 123
    protected function shouldHideLabel(): bool
153
    {
154 123
        return false;
155
    }
156
157 1
    protected function generateInput(): string
158
    {
159 1
        return '';
160
    }
161
162
    protected function generateBeginInput(): string
163
    {
164
        return '';
165
    }
166
167
    protected function generateEndInput(): string
168
    {
169
        return '';
170
    }
171
172 34
    protected function renderLabel(Label $label): string
173
    {
174 34
        return $label->render();
175
    }
176
177 34
    protected function renderHint(Hint $hint): string
178
    {
179 34
        return $hint->render();
180
    }
181
182 34
    protected function renderError(Error $error): string
183
    {
184 34
        return $error->render();
185
    }
186
187 167
    final protected function generateContent(): ?string
188
    {
189 162
        $parts = [
190 167
            '{input}' => $this->generateInput(),
191 162
            '{label}' => ($this->hideLabel ?? $this->shouldHideLabel()) ? '' : $this->generateLabel(),
192 162
            '{hint}' => $this->generateHint(),
193 162
            '{error}' => $this->generateError(),
194
        ];
195
196 162
        return $this->makeContent($this->template, $parts);
197
    }
198
199 2
    final protected function generateBeginContent(): string
200
    {
201 2
        $parts = [
202 2
            '{input}' => $this->generateBeginInput(),
203 2
            '{label}' => ($this->hideLabel ?? $this->shouldHideLabel()) ? '' : $this->generateLabel(),
204 2
            '{hint}' => $this->generateHint(),
205 2
            '{error}' => $this->generateError(),
206
        ];
207
208 2
        return $this->makeContent($this->templateBegin, $parts);
209
    }
210
211 2
    final protected function generateEndContent(): string
212
    {
213 2
        $parts = [
214 2
            '{input}' => $this->generateEndInput(),
215 2
            '{label}' => ($this->hideLabel ?? $this->shouldHideLabel()) ? '' : $this->generateLabel(),
216 2
            '{hint}' => $this->generateHint(),
217 2
            '{error}' => $this->generateError(),
218
        ];
219
220 2
        return $this->makeContent($this->templateEnd, $parts);
221
    }
222
223 163
    private function makeContent(string $template, array $parts): string
224
    {
225 163
        if (!empty($this->extraTokens)) {
226 1
            $parts += $this->extraTokens;
227
        }
228
229 163
        return preg_replace('/^\h*\v+/m', '', trim(strtr($template, $parts)));
230
    }
231
232 128
    private function generateLabel(): string
233
    {
234 128
        $label = Label::widget($this->labelConfig);
235
236 128
        return $this->renderLabel($label);
237
    }
238
239 163
    private function generateHint(): string
240
    {
241 163
        $hint = Hint::widget($this->hintConfig);
242
243 163
        return $this->renderHint($hint);
244
    }
245
246 163
    private function generateError(): string
247
    {
248 163
        $error = Error::widget($this->errorConfig);
249
250 163
        return $this->renderError($error);
251
    }
252
253
    /**
254
     * @psalm-assert non-empty-string $token
255
     */
256 4
    private function validateToken(string $token): void
257
    {
258 4
        if (in_array($token, self::BUILTIN_TOKENS, true)) {
259 1
            throw new InvalidArgumentException(
260 1
                sprintf(
261
                    'Token name "%s" is built-in.',
262
                    $token,
263
                )
264
            );
265
        }
266
267 3
        if ($token === '') {
268 1
            throw new InvalidArgumentException('Token must be non-empty string.');
269
        }
270
    }
271
}
272