Passed
Pull Request — master (#192)
by Alexander
05:43 queued 02:47
created

PartsField::generateBeginInput()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
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 5
    final public function tokens(array $tokens): static
40
    {
41 5
        $new = clone $this;
42
43 5
        foreach ($tokens as $token => $value) {
44 4
            if (!is_string($token)) {
45 1
                throw new InvalidArgumentException(
46 1
                    sprintf(
47
                        'Token should be string. %s given.',
48
                        $token,
49
                    )
50
                );
51
            }
52
53 3
            if (!is_string($value) && !$value instanceof Stringable) {
54 1
                throw new InvalidArgumentException(
55 1
                    sprintf(
56
                        'Token value should be string or Stringable. %s given.',
57 1
                        get_debug_type($value),
58
                    )
59
                );
60
            }
61
62 2
            $this->validateToken($token);
63
64 2
            $new->extraTokens[$token] = $value;
65
        }
66
67 3
        return $new;
68
    }
69
70 5
    final public function token(string $token, string|Stringable $value): static
71
    {
72 5
        $this->validateToken($token);
73
74 3
        $new = clone $this;
75 3
        $new->extraTokens[$token] = $value;
76 3
        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 2
    final public function templateBegin(string $template): static
90
    {
91 2
        $new = clone $this;
92 2
        $new->templateBegin = $template;
93 2
        return $new;
94
    }
95
96 2
    final public function templateEnd(string $template): static
97
    {
98 2
        $new = clone $this;
99 2
        $new->templateEnd = $template;
100 2
        return $new;
101
    }
102
103 188
    final public function hideLabel(?bool $hide = true): static
104
    {
105 188
        $new = clone $this;
106 188
        $new->hideLabel = $hide;
107 188
        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 165
    protected function shouldHideLabel(): bool
153
    {
154 165
        return false;
155
    }
156
157 1
    protected function generateInput(): string
158
    {
159 1
        return '';
160
    }
161
162 1
    protected function generateBeginInput(): string
163
    {
164 1
        return '';
165
    }
166
167 1
    protected function generateEndInput(): string
168
    {
169 1
        return '';
170
    }
171
172 61
    protected function renderLabel(Label $label): string
173
    {
174 61
        return $label->render();
175
    }
176
177 61
    protected function renderHint(Hint $hint): string
178
    {
179 61
        return $hint->render();
180
    }
181
182 61
    protected function renderError(Error $error): string
183
    {
184 61
        return $error->render();
185
    }
186
187 390
    final protected function generateContent(): ?string
188
    {
189 373
        $parts = [
190 390
            '{input}' => $this->generateInput(),
191 373
            '{label}' => ($this->hideLabel ?? $this->shouldHideLabel()) ? '' : $this->generateLabel(),
192 373
            '{hint}' => $this->generateHint(),
193 373
            '{error}' => $this->generateError(),
194
        ];
195
196 373
        return $this->makeContent($this->template, $parts);
197
    }
198
199 3
    final protected function generateBeginContent(): string
200
    {
201 3
        $parts = [
202 3
            '{input}' => $this->generateBeginInput(),
203 3
            '{label}' => ($this->hideLabel ?? $this->shouldHideLabel()) ? '' : $this->generateLabel(),
204 3
            '{hint}' => $this->generateHint(),
205 3
            '{error}' => $this->generateError(),
206
        ];
207
208 3
        return $this->makeContent($this->templateBegin, $parts);
209
    }
210
211 3
    final protected function generateEndContent(): string
212
    {
213 3
        $parts = [
214 3
            '{input}' => $this->generateEndInput(),
215 3
            '{label}' => ($this->hideLabel ?? $this->shouldHideLabel()) ? '' : $this->generateLabel(),
216 3
            '{hint}' => $this->generateHint(),
217 3
            '{error}' => $this->generateError(),
218
        ];
219
220 3
        return $this->makeContent($this->templateEnd, $parts);
221
    }
222
223 375
    private function makeContent(string $template, array $parts): string
224
    {
225 375
        if (!empty($this->extraTokens)) {
226 2
            $parts += $this->extraTokens;
227
        }
228
229 375
        return preg_replace('/^\h*\v+/m', '', trim(strtr($template, $parts)));
230
    }
231
232 170
    private function generateLabel(): string
233
    {
234 170
        $label = Label::widget($this->labelConfig);
235
236 170
        return $this->renderLabel($label);
237
    }
238
239 375
    private function generateHint(): string
240
    {
241 375
        $hint = Hint::widget($this->hintConfig);
242
243 375
        return $this->renderHint($hint);
244
    }
245
246 375
    private function generateError(): string
247
    {
248 375
        $error = Error::widget($this->errorConfig);
249
250 375
        return $this->renderError($error);
251
    }
252
253
    /**
254
     * @psalm-assert non-empty-string $token
255
     */
256 5
    private function validateToken(string $token): void
257
    {
258 5
        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 4
        if ($token === '') {
268 1
            throw new InvalidArgumentException('Token must be non-empty string.');
269
        }
270
    }
271
}
272