Completed
Push — master ( fffc7b...0ea26b )
by Rudie
01:58
created

FormField::normalizeRules()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
nc 5
nop 1
dl 0
loc 21
ccs 11
cts 11
cp 1
crap 5
rs 9.2728
c 0
b 0
f 0
1
<?php
2
3
namespace Kris\LaravelFormBuilder\Fields;
4
5
use Illuminate\Support\Arr;
6
use Illuminate\Support\Str;
7
use Kris\LaravelFormBuilder\Filters\Exception\FilterAlreadyBindedException;
8
use Kris\LaravelFormBuilder\Filters\FilterInterface;
9
use Kris\LaravelFormBuilder\Filters\FilterResolver;
10
use Kris\LaravelFormBuilder\Form;
11
use Kris\LaravelFormBuilder\FormHelper;
12
use Kris\LaravelFormBuilder\Rules;
13
14
/**
15
 * Class FormField
16
 *
17
 * @package Kris\LaravelFormBuilder\Fields
18
 */
19
abstract class FormField
20
{
21
    /**
22
     * Name of the field.
23
     *
24
     * @var string
25
     */
26
    protected $name;
27
28
    /**
29
     * Type of the field.
30
     *
31
     * @var string
32
     */
33
    protected $type;
34
35
    /**
36
     * All options for the field.
37
     *
38
     * @var array
39
     */
40
    protected $options = [];
41
42
    /**
43
     * Is field rendered.
44
     *
45
     * @var bool
46
     */
47
    protected $rendered = false;
48
49
    /**
50
     * @var Form
51
     */
52
    protected $parent;
53
54
    /**
55
     * @var string
56
     */
57
    protected $template;
58
59
    /**
60
     * @var FormHelper
61
     */
62
    protected $formHelper;
63
64
    /**
65
     * Name of the property for value setting.
66
     *
67
     * @var string
68
     */
69
    protected $valueProperty = 'value';
70
71
    /**
72
     * Name of the property for default value.
73
     *
74
     * @var string
75
     */
76
    protected $defaultValueProperty = 'default_value';
77
78
    /**
79
     * Is default value set?
80
     *
81
     * @var bool|false
82
     */
83
    protected $hasDefault = false;
84
85
    /**
86
     * @var \Closure|null
87
     */
88
    protected $valueClosure = null;
89
90
    /**
91
     * Array of filters key(alias/name) => objects.
92
     *
93
     * @var array
94
     */
95
    protected $filters = [];
96
97
    /**
98
     * Raw/unfiltered field value.
99
     *
100
     * @var mixed $rawValues
101
     */
102
    protected $rawValue;
103
104
    /**
105
     * Override filters with same alias/name for field.
106
     *
107
     * @var bool
108
     */
109
    protected $filtersOverride = false;
110
111
    /**
112
     * @param string $name
113
     * @param string $type
114
     * @param Form $parent
115
     * @param array $options
116
     */
117 103
    public function __construct($name, $type, Form $parent, array $options = [])
118
    {
119 103
        $this->name = $name;
120 103
        $this->type = $type;
121 103
        $this->parent = $parent;
122 103
        $this->formHelper = $this->parent->getFormHelper();
123 103
        $this->setTemplate();
124 103
        $this->setDefaultOptions($options);
125 103
        $this->setupValue();
126 98
        $this->initFilters();
127 98
    }
128
129
130
    /**
131
     * Setup the value of the form field.
132
     *
133
     * @return void
134
     */
135 103
    protected function setupValue()
136
    {
137 103
        $value = $this->getOption($this->valueProperty);
138 103
        $isChild = $this->getOption('is_child');
139
140 103
        if ($value instanceof \Closure) {
141
            $this->valueClosure = $value;
142
        }
143
144 103
        if (($value === null || $value instanceof \Closure) && !$isChild) {
145 92
            $this->setValue($this->getModelValueAttribute($this->parent->getModel(), $this->name));
146 23
        } elseif (!$isChild) {
147 14
            $this->hasDefault = true;
148
        }
149 98
    }
150
151
    /**
152
     * Get the template, can be config variable or view path.
153
     *
154
     * @return string
155
     */
156
    abstract protected function getTemplate();
157
158
    /**
159
     * @return string
160
     */
161 35
    protected function getViewTemplate()
162
    {
163 35
        return $this->parent->getTemplatePrefix() . $this->getOption('template', $this->template);
164
    }
165
166
    /**
167
     * Render the field.
168
     *
169
     * @param array $options
170
     * @param bool  $showLabel
171
     * @param bool  $showField
172
     * @param bool  $showError
173
     * @return string
174
     */
175 35
    public function render(array $options = [], $showLabel = true, $showField = true, $showError = true)
176
    {
177 35
        $this->prepareOptions($options);
178 35
        $value = $this->getValue();
179 35
        $defaultValue = $this->getDefaultValue();
180
181 35
        if ($showField) {
182 35
            $this->rendered = true;
183
        }
184
185
        // Override default value with value
186 35
        if (!$this->isValidValue($value) && $this->isValidValue($defaultValue)) {
187
            $this->setOption($this->valueProperty, $defaultValue);
188
        }
189
190 35
        if (!$this->needsLabel()) {
191 11
            $showLabel = false;
192
        }
193
194 35
        if ($showError) {
195 34
            $showError = $this->parent->haveErrorsEnabled();
196
        }
197
198 35
        $data = $this->getRenderData();
199
200 35
        return $this->formHelper->getView()->make(
201 35
            $this->getViewTemplate(),
202
            $data + [
203 35
                'name' => $this->name,
204 35
                'nameKey' => $this->getNameKey(),
205 35
                'type' => $this->type,
206 35
                'options' => $this->options,
207 35
                'showLabel' => $showLabel,
208 35
                'showField' => $showField,
209 35
                'showError' => $showError,
210 35
                'errorBag'  => $this->parent->getErrorBag(),
211 35
                'translationTemplate' => $this->parent->getTranslationTemplate(),
212
            ]
213 35
        )->render();
214
    }
215
216
    /**
217
     * Return the extra render data for this form field, passed into the field's template directly.
218
     *
219
     * @return array
220
     */
221 35
    protected function getRenderData()
222
    {
223 35
        return [];
224
    }
225
226
    /**
227
     * Get the attribute value from the model by name.
228
     *
229
     * @param mixed $model
230
     * @param string $name
231
     * @return mixed
232
     */
233 94
    protected function getModelValueAttribute($model, $name)
234
    {
235 94
        $transformedName = $this->transformKey($name);
236 94
        if (is_string($model)) {
237
            return $model;
238 94
        } elseif (is_object($model)) {
239 3
            return object_get($model, $transformedName);
240 94
        } elseif (is_array($model)) {
241 93
            return Arr::get($model, $transformedName);
242
        }
243 5
    }
244
245
    /**
246
     * Transform array like syntax to dot syntax.
247
     *
248
     * @param string $key
249
     * @return mixed
250
     */
251 103
    protected function transformKey($key)
252
    {
253 103
        return $this->formHelper->transformToDotSyntax($key);
254
    }
255
256
    /**
257
     * Prepare options for rendering.
258
     *
259
     * @param array $options
260
     * @return array The parsed options
261
     */
262 103
    protected function prepareOptions(array $options = [])
263
    {
264 103
        $helper = $this->formHelper;
265
266 103
        $this->options = $this->prepareRules($options);
267 103
        $this->options = $helper->mergeOptions($this->options, $options);
268
269 103
        $rulesParser = $helper->createRulesParser($this);
270 103
        $rules = $this->getOption('rules');
271 103
        $parsedRules = $rules ? $rulesParser->parse($rules) : [];
272
273
274 103
        foreach (['attr', 'label_attr', 'wrapper'] as $appendable) {
275
            // Append values to the 'class' attribute
276 103
            if ($this->getOption("{$appendable}.class_append")) {
277
                // Combine the current class attribute with the appends
278 3
                $append = $this->getOption("{$appendable}.class_append");
279 3
                $classAttribute = $this->getOption("{$appendable}.class", '') . ' ' . $append;
280 3
                $this->setOption("{$appendable}.class", $classAttribute);
281
282
                // Then remove the class_append option to prevent it from showing up as an attribute in the HTML
283 3
                $this->setOption("{$appendable}.class_append", null);
284
            }
285
        }
286
287 103
        if ($this->getOption('attr.multiple') && !$this->getOption('tmp.multipleBracesSet')) {
288 2
            $this->name = $this->name . '[]';
289 2
            $this->setOption('tmp.multipleBracesSet', true);
290
        }
291
292 103
        if ($this->parent->haveErrorsEnabled()) {
293 103
            $this->addErrorClass();
294
        }
295
296 103
        if ($this->getOption('required') === true || isset($parsedRules['required'])) {
297 16
            $lblClass = $this->getOption('label_attr.class', '');
298 16
            $requiredClass = $this->getConfig('defaults.required_class', 'required');
299
300 16
            if (!Str::contains($lblClass, $requiredClass)) {
301 16
                $lblClass .= ' ' . $requiredClass;
302 16
                $this->setOption('label_attr.class', $lblClass);
303
            }
304
305 16
            if ($this->parent->clientValidationEnabled()) {
306 15
                $this->setOption('attr.required', 'required');
307
            }
308
        }
309
310 103
        if ($this->parent->clientValidationEnabled() && $parsedRules) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $parsedRules of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
311 13
            $attrs = $this->getOption('attr') + $parsedRules;
312 13
            $this->setOption('attr', $attrs);
313
        }
314
315 103
        $this->setOption('wrapperAttrs', $helper->prepareAttributes($this->getOption('wrapper')));
316 103
        $this->setOption('errorAttrs', $helper->prepareAttributes($this->getOption('errors')));
317
318 103
        if ($this->getOption('help_block.text')) {
319 1
            $this->setOption(
320 1
                'help_block.helpBlockAttrs',
321 1
                $helper->prepareAttributes($this->getOption('help_block.attr'))
322
            );
323
        }
324
325 103
        return $this->options;
326
    }
327
328
    /**
329
     * Normalize and merge rules.
330
     * @param array $sourceOptions
331
     * @return array
332
     */
333 103
    protected function prepareRules(array &$sourceOptions = [])
334
    {
335 103
        $options = $this->options;
336
337
        // Normalize rules
338 103
        if (array_key_exists('rules_append', $sourceOptions)) {
339 1
            $sourceOptions['rules_append'] = $this->normalizeRules($sourceOptions['rules_append']);
340
        }
341
342 103
        if (array_key_exists('rules', $sourceOptions)) {
343 25
            $sourceOptions['rules'] = $this->normalizeRules($sourceOptions['rules']);
344
        }
345
346 103
        if (array_key_exists('rules', $options)) {
347 103
            $options['rules'] = $this->normalizeRules($options['rules']);
348
        }
349
350
351
        // Append rules
352 103
        if ($rulesToBeAppended = Arr::pull($sourceOptions, 'rules_append')) {
353 1
            $mergedRules = array_values(array_unique(array_merge($options['rules'], $rulesToBeAppended), SORT_REGULAR));
354 1
            $options['rules'] = $mergedRules;
355
        }
356
357 103
        return $options;
358
    }
359
360
    /**
361
     * Normalize the the given rule expression to an array.
362
     * @param mixed $rules
363
     * @return array
364
     */
365 103
    protected function normalizeRules($rules)
366
    {
367 103
        if (empty($rules)) {
368 102
            return [];
369
        }
370
371 14
        if (is_string($rules)) {
372 14
            return explode('|', $rules);
373
        }
374
375 8
        if (is_array($rules)) {
376 8
            $normalizedRules = [];
377 8
            foreach ($rules as $rule) {
378 8
                $normalizedRules[] = $this->normalizeRules($rule);
379
            }
380
381 8
            return array_values(array_unique(Arr::flatten($normalizedRules), SORT_REGULAR));
0 ignored issues
show
Documentation introduced by
$normalizedRules is of type array, but the function expects a object<Illuminate\Support\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
382
        }
383
384 1
        return $rules;
385
    }
386
387
388
    /**
389
     * Get name of the field.
390
     *
391
     * @return string
392
     */
393 39
    public function getName()
394
    {
395 39
        return $this->name;
396
    }
397
398
    /**
399
     * Set name of the field.
400
     *
401
     * @param string $name
402
     * @return $this
403
     */
404 11
    public function setName($name)
405
    {
406 11
        $this->name = $name;
407
408 11
        return $this;
409
    }
410
411
    /**
412
     * Get dot notation key for fields.
413
     *
414
     * @return string
415
     **/
416 55
    public function getNameKey()
417
    {
418 55
        return $this->transformKey($this->name);
419
    }
420
421
    /**
422
     * Get field options.
423
     *
424
     * @return array
425
     */
426 12
    public function getOptions()
427
    {
428 12
        return $this->options;
429
    }
430
431
    /**
432
     * Get single option from options array. Can be used with dot notation ('attr.class').
433
     *
434
     * @param string $option
435
     * @param mixed|null $default
436
     * @return mixed
437
     */
438 103
    public function getOption($option, $default = null)
439
    {
440 103
        return Arr::get($this->options, $option, $default);
441
    }
442
443
    /**
444
     * Set field options.
445
     *
446
     * @param array $options
447
     * @return $this
448
     */
449 11
    public function setOptions($options)
450
    {
451 11
        $this->options = $this->prepareOptions($options);
452
453 11
        return $this;
454
    }
455
456
    /**
457
     * Set single option on the field.
458
     *
459
     * @param string $name
460
     * @param mixed $value
461
     * @return $this
462
     */
463 103
    public function setOption($name, $value)
464
    {
465 103
        Arr::set($this->options, $name, $value);
466
467 103
        return $this;
468
    }
469
470
    /**
471
     * Get the type of the field.
472
     *
473
     * @return string
474
     */
475 67
    public function getType()
476
    {
477 67
        return $this->type;
478
    }
479
480
    /**
481
     * Set type of the field.
482
     *
483
     * @param mixed $type
484
     * @return $this
485
     */
486 1
    public function setType($type)
487
    {
488 1
        if ($this->formHelper->getFieldType($type)) {
489 1
            $this->type = $type;
490
        }
491
492 1
        return $this;
493
    }
494
495
    /**
496
     * @return Form
497
     */
498 103
    public function getParent()
499
    {
500 103
        return $this->parent;
501
    }
502
503
    /**
504
     * Check if the field is rendered.
505
     *
506
     * @return bool
507
     */
508 4
    public function isRendered()
509
    {
510 4
        return $this->rendered;
511
    }
512
513
    /**
514
     * Default options for field.
515
     *
516
     * @return array
517
     */
518 76
    protected function getDefaults()
519
    {
520 76
        return [];
521
    }
522
523
    /**
524
     * Defaults used across all fields.
525
     *
526
     * @return array
527
     */
528 103
    private function allDefaults()
529
    {
530
        return [
531 103
            'wrapper' => ['class' => $this->getConfig('defaults.wrapper_class')],
532 103
            'attr' => ['class' => $this->getConfig('defaults.field_class')],
533 103
            'help_block' => ['text' => null, 'tag' => 'p', 'attr' => [
534 103
                'class' => $this->getConfig('defaults.help_block_class')
535
            ]],
536
            'value' => null,
537
            'default_value' => null,
538
            'label' => null,
539
            'label_show' => true,
540
            'is_child' => false,
541 103
            'label_attr' => ['class' => $this->getConfig('defaults.label_class')],
542 103
            'errors' => ['class' => $this->getConfig('defaults.error_class')],
543
            'rules' => [],
544
            'error_messages' => []
545
        ];
546
    }
547
548
    /**
549
     * Get real name of the field without form namespace.
550
     *
551
     * @return string
552
     */
553 102
    public function getRealName()
554
    {
555 102
        return $this->getOption('real_name', $this->name);
556
    }
557
558
    /**
559
     * @param $value
560
     * @return $this
561
     */
562 95
    public function setValue($value)
563
    {
564 95
        if ($this->hasDefault) {
565 1
            return $this;
566
        }
567
568 95
        $closure = $this->valueClosure;
569
570 95
        if ($closure instanceof \Closure) {
571
            $value = $closure($value ?: null);
572
        }
573
574 95
        if (!$this->isValidValue($value)) {
575 92
            $value = $this->getOption($this->defaultValueProperty);
576
        }
577
578 95
        $this->options[$this->valueProperty] = $value;
579
580 95
        return $this;
581
    }
582
583
    /**
584
     * Set the template property on the object.
585
     *
586
     * @return void
587
     */
588 103
    private function setTemplate()
589
    {
590 103
        $this->template = $this->getConfig($this->getTemplate(), $this->getTemplate());
591 103
    }
592
593
    /**
594
     * Add error class to wrapper if validation errors exist.
595
     *
596
     * @return void
597
     */
598 103
    protected function addErrorClass()
599
    {
600 103
        $errors = [];
601 103
        if ($this->parent->getRequest()->hasSession()) {
602 102
            $errors = $this->parent->getRequest()->session()->get('errors');
603
        }
604 103
        $errorBag = $this->parent->getErrorBag();
605
606 103
        if ($errors && $errors->hasBag($errorBag) && $errors->getBag($errorBag)->has($this->getNameKey())) {
607
            $fieldErrorClass = $this->getConfig('defaults.field_error_class');
608
            $fieldClass = $this->getOption('attr.class');
609
610
            if ($fieldErrorClass && !Str::contains($fieldClass, $fieldErrorClass)) {
611
                $fieldClass .= ' ' . $fieldErrorClass;
612
                $this->setOption('attr.class', $fieldClass);
613
            }
614
615
            $wrapperErrorClass = $this->getConfig('defaults.wrapper_error_class');
616
            $wrapperClass = $this->getOption('wrapper.class');
617
618
            if ($wrapperErrorClass && $this->getOption('wrapper') && !Str::contains($wrapperClass, $wrapperErrorClass)) {
619
                $wrapperClass .= ' ' . $wrapperErrorClass;
620
                $this->setOption('wrapper.class', $wrapperClass);
621
            }
622
        }
623 103
    }
624
625
    /**
626
     * Merge all defaults with field specific defaults and set template if passed.
627
     *
628
     * @param array $options
629
     */
630 103
    protected function setDefaultOptions(array $options = [])
631
    {
632 103
        $this->options = $this->formHelper->mergeOptions($this->allDefaults(), $this->getDefaults());
633 103
        $this->options = $this->prepareOptions($options);
634
635 103
        $defaults = $this->setDefaultClasses($options);
636 103
        $this->options = $this->formHelper->mergeOptions($this->options, $defaults);
637
638 103
        $this->setupLabel();
639 103
    }
640
641
    /**
642
     * Creates default wrapper classes for the form element.
643
     *
644
     * @param array $options
645
     * @return array
646
     */
647 103
    protected function setDefaultClasses(array $options = [])
648
    {
649 103
        $wrapper_class = $this->getConfig('defaults.' . $this->type . '.wrapper_class', '');
650 103
        $label_class = $this->getConfig('defaults.' . $this->type . '.label_class', '');
651 103
        $field_class = $this->getConfig('defaults.' . $this->type . '.field_class', '');
652
653 103
        $defaults = [];
654 103
        if ($wrapper_class && !Arr::get($options, 'wrapper.class')) {
655
            $defaults['wrapper']['class'] = $wrapper_class;
656
        }
657 103
        if ($label_class && !Arr::get($options, 'label_attr.class')) {
658
            $defaults['label_attr']['class'] = $label_class;
659
        }
660 103
        if ($field_class && !Arr::get($options, 'attr.class')) {
661 1
            $defaults['attr']['class'] = $field_class;
662
        }
663 103
        return $defaults;
664
    }
665
666
    /**
667
     * Setup the label for the form field.
668
     *
669
     * @return void
670
     */
671 103
    protected function setupLabel()
672
    {
673 103
        if ($this->getOption('label') !== null) {
674 24
            return;
675
        }
676
677 101
        if ($template = $this->parent->getTranslationTemplate()) {
678 3
            $label = str_replace(
679 3
                ['{name}', '{type}'],
680 3
                [$this->getRealName(), 'label'],
681
                $template
682
            );
683 98
        } elseif ($langName = $this->parent->getLanguageName()) {
684 4
            $label = sprintf('%s.%s', $langName, $this->getRealName());
685
        } else {
686 95
            $label = $this->getRealName();
687
        }
688
689 101
        $this->setOption('label', $this->formHelper->formatLabel($label));
690 101
    }
691
692
    /**
693
     * Check if fields needs label.
694
     *
695
     * @return bool
696
     */
697 35
    protected function needsLabel()
698
    {
699
        // If field is <select> and child of choice, we don't need label for it
700 35
        $isChildSelect = $this->type == 'select' && $this->getOption('is_child') === true;
701
702 35
        if ($this->type == 'hidden' || $isChildSelect) {
703 11
            return false;
704
        }
705
706 31
        return true;
707
    }
708
709
    /**
710
     * Disable field.
711
     *
712
     * @return $this
713
     */
714 1
    public function disable()
715
    {
716 1
        $this->setOption('attr.disabled', 'disabled');
717
718 1
        return $this;
719
    }
720
721
    /**
722
     * Enable field.
723
     *
724
     * @return $this
725
     */
726 1
    public function enable()
727
    {
728 1
        Arr::forget($this->options, 'attr.disabled');
729
730 1
        return $this;
731
    }
732
733
    /**
734
     * Get validation rules for a field if any with label for attributes.
735
     *
736
     * @return array|null
737
     */
738 10
    public function getValidationRules()
739
    {
740 10
        $rules = $this->getOption('rules', []);
741 10
        $name = $this->getNameKey();
742 10
        $messages = $this->getOption('error_messages', []);
743 10
        $formName = $this->parent->getNameKey();
744
745 10
        if ($messages && $formName) {
746 1
            $newMessages = [];
747 1
            foreach ($messages as $messageKey => $message) {
748 1
                $messageKey = sprintf('%s.%s', $formName, $messageKey);
749 1
                $newMessages[$messageKey] = $message;
750
            }
751 1
            $messages = $newMessages;
752
        }
753
754 10
        if (!$rules) {
755 2
            return (new Rules([]))->setFieldName($this->getNameKey());
756
        }
757
758 9
        return (new Rules(
759 9
            [$name => $rules],
760 9
            [$name => $this->getOption('label')],
761
            $messages
762 9
        ))->setFieldName($this->getNameKey());
763
    }
764
765
    /**
766
     * Get this field's attributes, probably just one.
767
     *
768
     * @return array
769
     */
770 3
    public function getAllAttributes()
771
    {
772 3
        return [$this->getNameKey()];
773
    }
774
775
    /**
776
     * Get value property.
777
     *
778
     * @param mixed|null $default
779
     * @return mixed
780
     */
781 38
    public function getValue($default = null)
782
    {
783 38
        return $this->getOption($this->valueProperty, $default);
784
    }
785
786
    /**
787
     * Get default value property.
788
     *
789
     * @param mixed|null $default
790
     * @return mixed
791
     */
792 35
    public function getDefaultValue($default = null)
793
    {
794 35
        return $this->getOption($this->defaultValueProperty, $default);
795
    }
796
797
    /**
798
     * Check if provided value is valid for this type.
799
     *
800
     * @return bool
801
     */
802 95
    protected function isValidValue($value)
803
    {
804 95
        return $value !== null;
805
    }
806
807
    /**
808
     * Method initFilters used to initialize filters
809
     * from field options and bind it to the same.
810
     *
811
     * @return $this
812
     */
813 98
    protected function initFilters()
814
    {
815
        // If override status is set in field options to true
816
        // we will change filtersOverride property value to true
817
        // so we can override existing filters with registered
818
        // alias/name in addFilter method.
819 98
        $overrideStatus = $this->getOption('filters_override', false);
820 98
        if ($overrideStatus) {
821 2
            $this->setFiltersOverride(true);
822
        }
823
824
        // Get filters and bind it to field.
825 98
        $filters = $this->getOption('filters', []);
826 98
        foreach ($filters as $filter) {
827 8
            $this->addFilter($filter);
828
        }
829
830 98
        return $this;
831
    }
832
833
    /**
834
     * Method setFilters used to set filters to current filters property.
835
     *
836
     * @param  array $filters
837
     *
838
     * @return \Kris\LaravelFormBuilder\Fields\FormField
839
     */
840
    public function setFilters(array $filters)
841
    {
842
        $this->clearFilters();
843
        foreach ($filters as $filter) {
844
            $this->addFilter($filter);
845
        }
846
847
        return $this;
848
    }
849
850
    /**
851
     * Method getFilters returns array of binded filters
852
     * if there are any binded. Otherwise empty array.
853
     *
854
     * @return array
855
     */
856 23
    public function getFilters()
857
    {
858 23
        return $this->filters;
859
    }
860
861
    /**
862
     * @param  string|FilterInterface $filter
863
     *
864
     * @return \Kris\LaravelFormBuilder\Fields\FormField
865
     *
866
     * @throws FilterAlreadyBindedException
867
     */
868 8
    public function addFilter($filter)
869
    {
870
        // Resolve filter object from string/object or throw Ex.
871 8
        $filterObj = FilterResolver::instance($filter);
872
873
        // If filtersOverride is allowed we will override filter
874
        // with same alias/name if there is one with new resolved filter.
875 8
        if ($this->getFiltersOverride()) {
876 1
            if ($key = array_search($filterObj->getName(), $this->getFilters())) {
877
                $this->filters[$key] = $filterObj;
878
            } else {
879 1
                $this->filters[$filterObj->getName()] = $filterObj;
880
            }
881
        } else {
882
            // If filtersOverride is disabled and we found
883
            // equal alias defined we will throw Ex.
884 7
            if (array_key_exists($filterObj->getName(), $this->getFilters())) {
885 1
                $ex = new FilterAlreadyBindedException($filterObj->getName(), $this->getName());
886 1
                throw $ex;
887
            }
888
889
            // Filter with resolvedFilter alias/name doesn't exist
890
            // so we will bind it as new one to field.
891 7
            $this->filters[$filterObj->getName()] = $filterObj;
892
        }
893
894 8
        return $this;
895
    }
896
897
    /**
898
     * Method removeFilter used to remove filter by provided alias/name.
899
     *
900
     * @param  string $name
901
     *
902
     * @return \Kris\LaravelFormBuilder\Fields\FormField
903
     */
904 1
    public function removeFilter($name)
905
    {
906 1
        $filters = $this->getFilters();
907 1
        if (array_key_exists($name, $filters)) {
908 1
            unset($filters[$name]);
909 1
            $this->filters = $filters;
910
        }
911
912 1
        return $this;
913
    }
914
915
    /**
916
     * Method removeFilters used to remove filters by provided aliases/names.
917
     *
918
     * @param  array $filterNames
919
     *
920
     * @return \Kris\LaravelFormBuilder\Fields\FormField
921
     */
922 1
    public function removeFilters(array $filterNames)
923
    {
924 1
        $filters = $this->getFilters();
925 1
        foreach ($filterNames as $filterName) {
926 1
            if (array_key_exists($filterName, $filters)) {
927 1
                unset($filters[$filterName]);
928 1
                $this->filters = $filters;
929
            }
930
        }
931
932 1
        return $this;
933
    }
934
935
    /**
936
     * Method clearFilters used to empty current filters property.
937
     *
938
     * @return \Kris\LaravelFormBuilder\Fields\FormField
939
     */
940 1
    public function clearFilters()
941
    {
942 1
        $this->filters = [];
943 1
        return $this;
944
    }
945
946
    /**
947
     * Method used to set FiltersOverride status to provided value.
948
     *
949
     * @param $status
950
     *
951
     * @return \Kris\LaravelFormBuilder\Fields\FormField
952
     */
953 2
    public function setFiltersOverride($status)
954
    {
955 2
        $this->filtersOverride = $status;
956 2
        return $this;
957
    }
958
959
    /**
960
     * @return bool
961
     */
962 9
    public function getFiltersOverride()
963
    {
964 9
        return $this->filtersOverride;
965
    }
966
967
    /**
968
     * Method used to set Unfiltered/Unmutated field value.
969
     * Method is called before field value mutating starts - request value filtering.
970
     *
971
     * @param mixed $value
972
     *
973
     * @return \Kris\LaravelFormBuilder\Fields\FormField
974
     */
975 1
    public function setRawValue($value)
976
    {
977 1
        $this->rawValue = $value;
978 1
        return $this;
979
    }
980
981
    /**
982
     * Returns unfiltered raw value of field.
983
     *
984
     * @return mixed
985
     */
986
    public function getRawValue()
987
    {
988
        return $this->rawValue;
989
    }
990
991
    /**
992
     * Get config from the form.
993
     *
994
     * @return mixed
995
     */
996 103
    private function getConfig($key = null, $default = null)
997
    {
998 103
        return $this->parent->getConfig($key, $default);
999
    }
1000
}
1001