Passed
Push — master ( d126fc...a9869f )
by Ivan
03:15
created

FormFieldPrefixer   C

Complexity

Total Complexity 56

Size/Duplication

Total Lines 451
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 81
c 4
b 0
f 0
dl 0
loc 451
ccs 104
cts 104
cp 1
rs 5.5199
wmc 56

28 Methods

Rating   Name   Duplication   Size   Complexity  
A buildArrayName() 0 7 2
A withPrefix() 0 5 1
A getArrayValidationSeparator() 0 3 1
A buildName() 0 11 5
A isArray() 0 3 1
A asArray() 0 7 2
A asMultiDimensionalArray() 0 3 1
A selected() 0 7 3
A getDefaultSeparator() 0 3 1
A hasArrayKey() 0 3 1
A __construct() 0 3 1
A select() 0 9 2
A id() 0 5 1
A isJavaScript() 0 3 2
A validationKey() 0 7 3
A buildArrayIdentifier() 0 3 2
A hasPrefix() 0 3 1
A value() 0 7 2
A buildArrayKey() 0 7 3
A isMultiDimensionalArray() 0 3 1
A buildAttributeName() 0 15 6
A name() 0 5 1
A getCurrentValue() 0 3 2
A for() 0 3 1
A buildJavaScriptValueKey() 0 10 4
A make() 0 3 1
A buildAttributeValue() 0 15 3
A buildAttribute() 0 7 2

How to fix   Complexity   

Complex Class

Complex classes like FormFieldPrefixer often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FormFieldPrefixer, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace CodeZero\FormFieldPrefixer;
4
5
use Illuminate\Support\Facades\Session;
6
use Illuminate\Support\HtmlString;
7
use Illuminate\Support\Str;
8
9
class FormFieldPrefixer
10
{
11
    /**
12
     * The form field prefix.
13
     *
14
     * @var string|null
15
     */
16
    protected $prefix;
17
18
    /**
19
     * The array key for the form field.
20
     *
21
     * @var string|null
22
     */
23
    protected $arrayKey = null;
24
25
    /**
26
     * Indicator if we are generating a form field name as an array.
27
     *
28
     * @var bool
29
     */
30
    protected $isArray = false;
31
32
    /**
33
     * Indicator if we are generating a form field name with a multi dimensional array.
34
     *
35
     * @var bool
36
     */
37
    protected $multiDimensional = false;
38
39
    /**
40
     * Get a FormFieldPrefixer instance.
41
     *
42
     * @param string|null $prefix
43
     *
44
     * @return static
45
     */
46 2
    public static function make($prefix = null)
47
    {
48 2
        return new static($prefix);
49
    }
50
51
    /**
52
     * FormPrefixer constructor.
53
     *
54
     * @param string|null $prefix
55
     */
56 52
    public function __construct($prefix = null)
57
    {
58 52
        $this->withPrefix($prefix);
59 52
    }
60
61
    /**
62
     * Set the prefix to be used for the form fields.
63
     *
64
     * @param string|null $prefix
65
     *
66
     * @return $this
67
     */
68 52
    public function withPrefix($prefix)
69
    {
70 52
        $this->prefix = $prefix;
71
72 52
        return $this;
73
    }
74
75
    /**
76
     * Set the array key to use for the form field
77
     * and generate a name with a flat array.
78
     *
79
     * @param string $arrayKey
80
     * @param bool $multiDimensional
81
     *
82
     * @return $this
83
     */
84 27
    public function asArray($arrayKey = null, $multiDimensional = false)
85
    {
86 27
        $this->arrayKey = $arrayKey;
87 27
        $this->isArray = true;
88 27
        $this->multiDimensional = $multiDimensional && $this->prefix !== null;
89
90 27
        return $this;
91
    }
92
93
    /**
94
     * Set the array key to use for the form field and
95
     * generate a name with a multi dimensional array.
96
     *
97
     * @param string $arrayKey
98
     *
99
     * @return $this
100
     */
101 12
    public function asMultiDimensionalArray($arrayKey)
102
    {
103 12
        return $this->asArray($arrayKey, true);
104
    }
105
106
    /**
107
     * Determine if any key uses javascript.
108
     *
109
     * @return bool
110
     */
111 52
    public function isJavaScript()
112
    {
113 52
        return Str::startsWith($this->prefix, '${') || Str::startsWith($this->arrayKey, '${');
114
    }
115
116
    /**
117
     * Get the form field's "name" attribute.
118
     *
119
     * @param string $name
120
     * @param string|null $attribute
121
     *
122
     * @return string
123
     */
124 29
    public function name($name, $attribute = 'name')
125
    {
126 29
        return $this->buildAttribute(
127 29
            $this->buildAttributeValue($name, $this->isArray()),
128 29
            $this->buildAttributeName($attribute)
129
        );
130
    }
131
132
    /**
133
     * Get the form field's "id" attribute.
134
     *
135
     * @param string $id
136
     * @param string|null $attribute
137
     *
138
     * @return string
139
     */
140 15
    public function id($id, $attribute = 'id')
141
    {
142 15
        return $this->buildAttribute(
143 15
            $this->buildAttributeValue($id, false),
144 15
            $this->buildAttributeName($attribute)
145
        );
146
    }
147
148
    /**
149
     * Get the label's "for" attribute.
150
     *
151
     * @param string $id
152
     * @param string|null $attribute
153
     *
154
     * @return string
155
     */
156 15
    public function for($id, $attribute = 'for')
157
    {
158 15
        return $this->id($id, $attribute);
159
    }
160
161
    /**
162
     * Get the input's "value" attribute.
163
     *
164
     * @param string $name
165
     * @param string|null $default
166
     * @param string|null $attribute
167
     *
168
     * @return string
169
     */
170 17
    public function value($name, $default = null, $attribute = 'value')
171
    {
172 17
        $value = $this->isJavaScript()
173 5
            ? $this->buildJavaScriptValueKey($name)
174 17
            : e($this->getCurrentValue($name, $default));
175
176 17
        return $this->buildAttribute($value, $this->buildAttributeName($attribute));
177
    }
178
179
    /**
180
     * Get the "selected" attribute for the given option value.
181
     *
182
     * @param string $name
183
     * @param string $value
184
     * @param string|null $default
185
     *
186
     * @return string
187
     */
188 10
    public function selected($name, $value, $default = null)
189
    {
190 10
        if ($this->isJavaScript() || $value != $this->getCurrentValue($name, $default)) {
191 10
            return '';
192
        }
193
194 8
        return $this->buildAttribute('selected', $this->buildAttributeName('selected'));
195
    }
196
197
    /**
198
     * Get the select's "v-model" binding when using javascript.
199
     *
200
     * @param string $name
201
     *
202
     * @return string
203
     */
204 11
    public function select($name)
205
    {
206 11
        if ( ! $this->isJavaScript()) {
207 6
            return '';
208
        }
209
210 5
        return $this->buildAttribute(
211 5
            $this->buildJavaScriptValueKey($name),
212 5
            $this->buildAttributeName('v-model')
213
        );
214
    }
215
216
    /**
217
     * Get the validation key for the form field.
218
     *
219
     * @param string $key
220
     *
221
     * @return string
222
     */
223 32
    public function validationKey($key)
224
    {
225 32
        $separator = $this->isArray() || $this->isJavaScript()
226 18
            ? $this->getArrayValidationSeparator()
227 32
            : $this->getDefaultSeparator();
228
229 32
        return $this->buildAttributeValue($key,false, $separator);
230
    }
231
232
    /**
233
     * Check if the form field is an array.
234
     *
235
     * @return bool
236
     */
237 48
    public function isArray()
238
    {
239 48
        return $this->isArray;
240
    }
241
242
    /**
243
     * Check if the form field is a multi dimensional array.
244
     *
245
     * @return bool
246
     */
247 48
    public function isMultiDimensionalArray()
248
    {
249 48
        return $this->multiDimensional;
250
    }
251
252
    /**
253
     * Check if the form field has a prefix.
254
     *
255
     * @return bool
256
     */
257 48
    public function hasPrefix()
258
    {
259 48
        return !! $this->prefix;
260
    }
261
262
    /**
263
     * Check if the form field has an array key.
264
     *
265
     * @return bool
266
     */
267 13
    public function hasArrayKey()
268
    {
269 13
        return ! is_null($this->arrayKey);
270
    }
271
272
    /**
273
     * Build the attribute.
274
     *
275
     * @param string $value
276
     * @param string|null $attribute
277
     *
278
     * @return string
279
     */
280 49
    protected function buildAttribute($value, $attribute)
281
    {
282 49
        if ($attribute) {
283 43
            return new HtmlString($attribute . '="' . $value . '"');
284
        }
285
286 16
        return $value;
287
    }
288
289
    /**
290
     * Build the attribute name if needed.
291
     *
292
     * @param string|null $attribute
293
     *
294
     * @return string
295
     */
296 49
    protected function buildAttributeName($attribute)
297
    {
298 49
        if ( ! $attribute) {
299 16
            return '';
300
        }
301
302 43
        if ($attribute === 'value' && $this->isJavaScript()) {
303 5
            return 'v-model';
304
        }
305
306 38
        if ($attribute !== 'v-model' && $this->isJavaScript()) {
307 5
            return ":{$attribute}";
308
        }
309
310 33
        return $attribute;
311
    }
312
313
    /**
314
     * Build the attribute value.
315
     *
316
     * @param string $name
317
     * @param bool $useArraySyntax
318
     * @param string|null $separator
319
     *
320
     * @return string
321
     */
322 48
    protected function buildAttributeValue($name, $useArraySyntax, $separator = null)
323
    {
324 48
        $separator = $separator ?: $this->getDefaultSeparator();
325
326 48
        $prefix = $this->buildName($name);
327 48
        $arrayKey = $this->buildArrayKey($name, $useArraySyntax, $separator);
328 48
        $arrayName = $this->buildArrayName($name, $useArraySyntax, $separator);
329
330 48
        $identifier = $prefix . $arrayKey . $arrayName;
331
332 48
        if ($this->isJavaScript()) {
333 15
            $identifier = "`{$identifier}`";
334
        }
335
336 48
        return $identifier;
337
    }
338
339
    /**
340
     * Build the (base)name of the form field.
341
     *
342
     * @param string $name
343
     *
344
     * @return string
345
     */
346 48
    protected function buildName($name)
347
    {
348 48
        if ( ! $this->hasPrefix()) {
349 24
            return $name;
350
        }
351
352 24
        if ($this->isMultiDimensionalArray() || ($this->isArray() && ! $this->hasArrayKey())) {
353 9
            return $this->prefix;
354
        }
355
356 15
        return $this->prefix . $this->getDefaultSeparator() . $name;
357
    }
358
359
    /**
360
     * Build the array key part of the form field identifier if needed.
361
     *
362
     * @param string $name
363
     * @param bool $useArraySyntax
364
     * @param string $separator
365
     *
366
     * @return string
367
     */
368 48
    protected function buildArrayKey($name, $useArraySyntax, $separator)
369
    {
370 48
        if ( ! $this->isArray()) {
371 23
            return '';
372
        }
373
374 25
        return $this->buildArrayIdentifier($this->arrayKey ?: $name, $useArraySyntax, $separator);
375
    }
376
377
    /**
378
     * Build the array part of the form field identifier
379
     * that has the form field name if needed.
380
     *
381
     * @param string $name
382
     * @param bool $useArraySyntax
383
     * @param string $separator
384
     *
385
     * @return string
386
     */
387 48
    protected function buildArrayName($name, $useArraySyntax, $separator)
388
    {
389 48
        if ( ! $this->isMultiDimensionalArray()) {
390 42
            return '';
391
        }
392
393 6
        return $this->buildArrayIdentifier($name, $useArraySyntax, $separator);
394
    }
395
396
    /**
397
     * Build the array part of a form field identifier.
398
     *
399
     * @param string $value
400
     * @param bool $useArraySyntax
401
     * @param string $separator
402
     *
403
     * @return string
404
     */
405 25
    protected function buildArrayIdentifier($value, $useArraySyntax, $separator)
406
    {
407 25
        return $useArraySyntax ? "[{$value}]" : $separator . $value;
408
    }
409
410
    /**
411
     * Build the javascript key that holds the inputs value.
412
     *
413
     * @param string $key
414
     *
415
     * @return string
416
     */
417 10
    protected function buildJavaScriptValueKey($key)
418
    {
419 10
        if ($this->isMultiDimensionalArray() || ($this->isArray() && ! $this->hasArrayKey())) {
420 2
            $key = "'{$key}'";
421
        }
422
423 10
        $key = $this->name($key, null);
424 10
        $key = preg_replace('/`|\${\s*|\s*}/', '', $key);
425
426 10
        return $key;
427
    }
428
429
    /**
430
     * Get the old input value or any default value.
431
     *
432
     * @param string $name
433
     * @param string|null $default
434
     *
435
     * @return mixed
436
     */
437 21
    protected function getCurrentValue($name, $default)
438
    {
439 21
        return Session::hasOldInput() ? Session::getOldInput($this->validationKey($name)) : $default;
440
    }
441
442
    /**
443
     * Get the default separator for form fields.
444
     *
445
     * @return string
446
     */
447 42
    protected function getDefaultSeparator()
448
    {
449 42
        return '_';
450
    }
451
452
    /**
453
     * Get the separator to use for validation keys.
454
     *
455
     * @return string
456
     */
457 18
    protected function getArrayValidationSeparator()
458
    {
459 18
        return '.';
460
    }
461
}
462