Completed
Pull Request — master (#615)
by
unknown
04:00
created

FormField::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 4
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
ccs 10
cts 10
cp 1
crap 1
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 105
    public function __construct($name, $type, Form $parent, array $options = [])
118
    {
119 105
        $this->name = $name;
120 105
        $this->type = $type;
121 105
        $this->parent = $parent;
122 105
        $this->formHelper = $this->parent->getFormHelper();
123 105
        $this->setTemplate();
124 105
        $this->setDefaultOptions($options);
125 105
        $this->setupValue();
126 100
        $this->initFilters();
127 100
    }
128
129
130
    /**
131
     * Setup the value of the form field.
132
     *
133
     * @return void
134
     */
135 105
    protected function setupValue()
136
    {
137 105
        $value = $this->getOption($this->valueProperty);
138 105
        $isChild = $this->getOption('is_child');
139
140 105
        if ($value instanceof \Closure) {
141
            $this->valueClosure = $value;
142
        }
143
144 105
        if (($value === null || $value instanceof \Closure) && !$isChild) {
145 94
            if ($this instanceof EntityType) {
146 5
                $attributeName = $this->name;
147
            } else {
148 89
                $attributeName = $this->getOption('property', $this->name);
149
            }
150
151 94
            $this->setValue($this->getModelValueAttribute($this->parent->getModel(), $attributeName));
152 25
        } elseif (!$isChild) {
153 14
            $this->hasDefault = true;
154
        }
155 100
    }
156
157
    /**
158
     * Get the template, can be config variable or view path.
159
     *
160
     * @return string
161
     */
162
    abstract protected function getTemplate();
163
164
    /**
165
     * @return string
166
     */
167 35
    protected function getViewTemplate()
168
    {
169 35
        return $this->parent->getTemplatePrefix() . $this->getOption('template', $this->template);
170
    }
171
172
    /**
173
     * Render the field.
174
     *
175
     * @param array $options
176
     * @param bool  $showLabel
177
     * @param bool  $showField
178
     * @param bool  $showError
179
     * @return string
180
     */
181 35
    public function render(array $options = [], $showLabel = true, $showField = true, $showError = true)
182
    {
183 35
        $this->prepareOptions($options);
184 35
        $value = $this->getValue();
185 35
        $defaultValue = $this->getDefaultValue();
186
187 35
        if ($showField) {
188 35
            $this->rendered = true;
189
        }
190
191
        // Override default value with value
192 35
        if (!$this->isValidValue($value) && $this->isValidValue($defaultValue)) {
193
            $this->setOption($this->valueProperty, $defaultValue);
194
        }
195
196 35
        if (!$this->needsLabel()) {
197 11
            $showLabel = false;
198
        }
199
200 35
        if ($showError) {
201 34
            $showError = $this->parent->haveErrorsEnabled();
202
        }
203
204 35
        $data = $this->getRenderData();
205
206 35
        return $this->formHelper->getView()->make(
207 35
            $this->getViewTemplate(),
208
            $data + [
209 35
                'name' => $this->name,
210 35
                'nameKey' => $this->getNameKey(),
211 35
                'type' => $this->type,
212 35
                'options' => $this->options,
213 35
                'showLabel' => $showLabel,
214 35
                'showField' => $showField,
215 35
                'showError' => $showError,
216 35
                'errorBag'  => $this->parent->getErrorBag(),
217 35
                'translationTemplate' => $this->parent->getTranslationTemplate(),
218
            ]
219 35
        )->render();
220
    }
221
222
    /**
223
     * Return the extra render data for this form field, passed into the field's template directly.
224
     *
225
     * @return array
226
     */
227 35
    protected function getRenderData()
228
    {
229 35
        return [];
230
    }
231
232
    /**
233
     * Get the attribute value from the model by name.
234
     *
235
     * @param mixed $model
236
     * @param string $name
237
     * @return mixed
238
     */
239 96
    protected function getModelValueAttribute($model, $name)
240
    {
241 96
        $transformedName = $this->transformKey($name);
242 96
        if (is_string($model)) {
243
            return $model;
244 96
        } elseif (is_object($model)) {
245 5
            return object_get($model, $transformedName);
246 94
        } elseif (is_array($model)) {
247 93
            return Arr::get($model, $transformedName);
248
        }
249 5
    }
250
251
    /**
252
     * Transform array like syntax to dot syntax.
253
     *
254
     * @param string $key
255
     * @return mixed
256
     */
257 105
    protected function transformKey($key)
258
    {
259 105
        return $this->formHelper->transformToDotSyntax($key);
260
    }
261
262
    /**
263
     * Prepare options for rendering.
264
     *
265
     * @param array $options
266
     * @return array The parsed options
267
     */
268 105
    protected function prepareOptions(array $options = [])
269
    {
270 105
        $helper = $this->formHelper;
271
272 105
        $this->options = $this->prepareRules($options);
273 105
        $this->options = $helper->mergeOptions($this->options, $options);
274
275 105
        $rulesParser = $helper->createRulesParser($this);
276 105
        $rules = $this->getOption('rules');
277 105
        $parsedRules = $rules ? $rulesParser->parse($rules) : [];
278
279
280 105
        foreach (['attr', 'label_attr', 'wrapper'] as $appendable) {
281
            // Append values to the 'class' attribute
282 105
            if ($this->getOption("{$appendable}.class_append")) {
283
                // Combine the current class attribute with the appends
284 3
                $append = $this->getOption("{$appendable}.class_append");
285 3
                $classAttribute = $this->getOption("{$appendable}.class", '') . ' ' . $append;
286 3
                $this->setOption("{$appendable}.class", $classAttribute);
287
288
                // Then remove the class_append option to prevent it from showing up as an attribute in the HTML
289 105
                $this->setOption("{$appendable}.class_append", null);
290
            }
291
        }
292
293 105
        if ($this->getOption('attr.multiple') && !$this->getOption('tmp.multipleBracesSet')) {
294 2
            $this->name = $this->name . '[]';
295 2
            $this->setOption('tmp.multipleBracesSet', true);
296
        }
297
298 105
        if ($this->parent->haveErrorsEnabled()) {
299 105
            $this->addErrorClass();
300
        }
301
302 105
        if ($this->getOption('required') === true || isset($parsedRules['required'])) {
303 16
            $lblClass = $this->getOption('label_attr.class', '');
304 16
            $requiredClass = $this->getConfig('defaults.required_class', 'required');
305
306 16
            if (!Str::contains($lblClass, $requiredClass)) {
307 16
                $lblClass .= ' ' . $requiredClass;
308 16
                $this->setOption('label_attr.class', $lblClass);
309
            }
310
311 16
            if ($this->parent->clientValidationEnabled()) {
312 15
                $this->setOption('attr.required', 'required');
313
            }
314
        }
315
316 105
        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...
317 13
            $attrs = $this->getOption('attr') + $parsedRules;
318 13
            $this->setOption('attr', $attrs);
319
        }
320
321 105
        $this->setOption('wrapperAttrs', $helper->prepareAttributes($this->getOption('wrapper')));
322 105
        $this->setOption('errorAttrs', $helper->prepareAttributes($this->getOption('errors')));
323
324 105
        if ($this->getOption('help_block.text')) {
325 1
            $this->setOption(
326 1
                'help_block.helpBlockAttrs',
327 1
                $helper->prepareAttributes($this->getOption('help_block.attr'))
328
            );
329
        }
330
331 105
        return $this->options;
332
    }
333
334
    /**
335
     * Normalize and merge rules.
336
     * @param array $sourceOptions
337
     * @return array
338
     */
339 105
    protected function prepareRules(array &$sourceOptions = [])
340
    {
341 105
        $options = $this->options;
342
343
        // Normalize rules
344 105
        if (array_key_exists('rules_append', $sourceOptions)) {
345 1
            $sourceOptions['rules_append'] = $this->normalizeRules($sourceOptions['rules_append']);
346
        }
347
348 105
        if (array_key_exists('rules', $sourceOptions)) {
349 27
            $sourceOptions['rules'] = $this->normalizeRules($sourceOptions['rules']);
350
        }
351
352 105
        if (array_key_exists('rules', $options)) {
353 105
            $options['rules'] = $this->normalizeRules($options['rules']);
354
        }
355
356
357
        // Append rules
358 105
        if ($rulesToBeAppended = Arr::pull($sourceOptions, 'rules_append')) {
359 1
            $mergedRules = array_values(array_unique(array_merge($options['rules'], $rulesToBeAppended), SORT_REGULAR));
360 1
            $options['rules'] = $mergedRules;
361
        }
362
363 105
        return $options;
364
    }
365
366
    /**
367
     * Normalize the the given rule expression to an array.
368
     * @param mixed $rules
369
     * @return array
370
     */
371 105
    protected function normalizeRules($rules)
372
    {
373 105
        if (empty($rules)) {
374 104
            return [];
375
        }
376
377 14
        if (is_string($rules)) {
378 10
            return explode('|', $rules);
379
        }
380
381 8
        if (is_array($rules)) {
382 8
            return array_values(array_unique(Arr::flatten($rules), SORT_REGULAR));
0 ignored issues
show
Documentation introduced by
$rules 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...
383
        }
384
385
        return $rules;
386
    }
387
388
389
    /**
390
     * Get name of the field.
391
     *
392
     * @return string
393
     */
394 40
    public function getName()
395
    {
396 40
        return $this->name;
397
    }
398
399
    /**
400
     * Set name of the field.
401
     *
402
     * @param string $name
403
     * @return $this
404
     */
405 12
    public function setName($name)
406
    {
407 12
        $this->name = $name;
408
409 12
        return $this;
410
    }
411
412
    /**
413
     * Get dot notation key for fields.
414
     *
415
     * @return string
416
     **/
417 55
    public function getNameKey()
418
    {
419 55
        return $this->transformKey($this->name);
420
    }
421
422
    /**
423
     * Get field options.
424
     *
425
     * @return array
426
     */
427 12
    public function getOptions()
428
    {
429 12
        return $this->options;
430
    }
431
432
    /**
433
     * Get single option from options array. Can be used with dot notation ('attr.class').
434
     *
435
     * @param string $option
436
     * @param mixed|null $default
437
     * @return mixed
438
     */
439 105
    public function getOption($option, $default = null)
440
    {
441 105
        return Arr::get($this->options, $option, $default);
442
    }
443
444
    /**
445
     * Set field options.
446
     *
447
     * @param array $options
448
     * @return $this
449
     */
450 12
    public function setOptions($options)
451
    {
452 12
        $this->options = $this->prepareOptions($options);
453
454 12
        return $this;
455
    }
456
457
    /**
458
     * Set single option on the field.
459
     *
460
     * @param string $name
461
     * @param mixed $value
462
     * @return $this
463
     */
464 105
    public function setOption($name, $value)
465
    {
466 105
        Arr::set($this->options, $name, $value);
467
468 105
        return $this;
469
    }
470
471
    /**
472
     * Get the type of the field.
473
     *
474
     * @return string
475
     */
476 69
    public function getType()
477
    {
478 69
        return $this->type;
479
    }
480
481
    /**
482
     * Set type of the field.
483
     *
484
     * @param mixed $type
485
     * @return $this
486
     */
487 1
    public function setType($type)
488
    {
489 1
        if ($this->formHelper->getFieldType($type)) {
490 1
            $this->type = $type;
491
        }
492
493 1
        return $this;
494
    }
495
496
    /**
497
     * @return Form
498
     */
499 105
    public function getParent()
500
    {
501 105
        return $this->parent;
502
    }
503
504
    /**
505
     * Check if the field is rendered.
506
     *
507
     * @return bool
508
     */
509 4
    public function isRendered()
510
    {
511 4
        return $this->rendered;
512
    }
513
514
    /**
515
     * Default options for field.
516
     *
517
     * @return array
518
     */
519 77
    protected function getDefaults()
520
    {
521 77
        return [];
522
    }
523
524
    /**
525
     * Defaults used across all fields.
526
     *
527
     * @return array
528
     */
529 105
    private function allDefaults()
530
    {
531
        return [
532 105
            'wrapper' => ['class' => $this->getConfig('defaults.wrapper_class')],
533 105
            'attr' => ['class' => $this->getConfig('defaults.field_class')],
534 105
            'help_block' => ['text' => null, 'tag' => 'p', 'attr' => [
535 105
                'class' => $this->getConfig('defaults.help_block_class')
536
            ]],
537
            'value' => null,
538
            'default_value' => null,
539
            'label' => null,
540
            'label_show' => true,
541
            'is_child' => false,
542 105
            'label_attr' => ['class' => $this->getConfig('defaults.label_class')],
543 105
            'errors' => ['class' => $this->getConfig('defaults.error_class')],
544
            'rules' => [],
545
            'error_messages' => []
546
        ];
547
    }
548
549
    /**
550
     * Get real name of the field without form namespace.
551
     *
552
     * @return string
553
     */
554 104
    public function getRealName()
555
    {
556 104
        return $this->getOption('real_name', $this->name);
557
    }
558
559
    /**
560
     * @param $value
561
     * @return $this
562
     */
563 98
    public function setValue($value)
564
    {
565 98
        if ($this->hasDefault) {
566 1
            return $this;
567
        }
568
569 98
        $closure = $this->valueClosure;
570
571 98
        if ($closure instanceof \Closure) {
572
            $value = $closure($value ?: null);
573
        }
574
575 98
        if (!$this->isValidValue($value)) {
576 93
            $value = $this->getOption($this->defaultValueProperty);
577
        }
578
579 98
        $this->options[$this->valueProperty] = $value;
580
581 98
        return $this;
582
    }
583
584
    /**
585
     * Set the template property on the object.
586
     *
587
     * @return void
588
     */
589 105
    private function setTemplate()
590
    {
591 105
        $this->template = $this->getConfig($this->getTemplate(), $this->getTemplate());
592 105
    }
593
594
    /**
595
     * Add error class to wrapper if validation errors exist.
596
     *
597
     * @return void
598
     */
599 105
    protected function addErrorClass()
600
    {
601 105
        $errors = [];
602 105
        if ($this->parent->getRequest()->hasSession()) {
603 104
            $errors = $this->parent->getRequest()->session()->get('errors');
604
        }
605 105
        $errorBag = $this->parent->getErrorBag();
606
607 105
        if ($errors && $errors->hasBag($errorBag) && $errors->getBag($errorBag)->has($this->getNameKey())) {
608
            $fieldErrorClass = $this->getConfig('defaults.field_error_class');
609
            $fieldClass = $this->getOption('attr.class');
610
611
            if ($fieldErrorClass && !Str::contains($fieldClass, $fieldErrorClass)) {
612
                $fieldClass .= ' ' . $fieldErrorClass;
613
                $this->setOption('attr.class', $fieldClass);
614
            }
615
616
            $wrapperErrorClass = $this->getConfig('defaults.wrapper_error_class');
617
            $wrapperClass = $this->getOption('wrapper.class');
618
619
            if ($wrapperErrorClass && $this->getOption('wrapper') && !Str::contains($wrapperClass, $wrapperErrorClass)) {
620
                $wrapperClass .= ' ' . $wrapperErrorClass;
621
                $this->setOption('wrapper.class', $wrapperClass);
622
            }
623
        }
624 105
    }
625
626
    /**
627
     * Merge all defaults with field specific defaults and set template if passed.
628
     *
629
     * @param array $options
630
     */
631 105
    protected function setDefaultOptions(array $options = [])
632
    {
633 105
        $this->options = $this->formHelper->mergeOptions($this->allDefaults(), $this->getDefaults());
634 105
        $this->options = $this->prepareOptions($options);
635
636 105
        $defaults = $this->setDefaultClasses($options);
637 105
        $this->options = $this->formHelper->mergeOptions($this->options, $defaults);
638
639 105
        $this->setupLabel();
640 105
    }
641
642
    /**
643
     * Creates default wrapper classes for the form element.
644
     *
645
     * @param array $options
646
     * @return array
647
     */
648 105
    protected function setDefaultClasses(array $options = [])
649
    {
650 105
        $wrapper_class = $this->getConfig('defaults.' . $this->type . '.wrapper_class', '');
651 105
        $label_class = $this->getConfig('defaults.' . $this->type . '.label_class', '');
652 105
        $field_class = $this->getConfig('defaults.' . $this->type . '.field_class', '');
653
654 105
        $defaults = [];
655 105
        if ($wrapper_class && !Arr::get($options, 'wrapper.class')) {
656
            $defaults['wrapper']['class'] = $wrapper_class;
657
        }
658 105
        if ($label_class && !Arr::get($options, 'label_attr.class')) {
659
            $defaults['label_attr']['class'] = $label_class;
660
        }
661 105
        if ($field_class && !Arr::get($options, 'attr.class')) {
662 1
            $defaults['attr']['class'] = $field_class;
663
        }
664 105
        return $defaults;
665
    }
666
667
    /**
668
     * Setup the label for the form field.
669
     *
670
     * @return void
671
     */
672 105
    protected function setupLabel()
673
    {
674 105
        if ($this->getOption('label') !== null) {
675 26
            return;
676
        }
677
678 103
        if ($template = $this->parent->getTranslationTemplate()) {
679 3
            $label = str_replace(
680 3
                ['{name}', '{type}'],
681 3
                [$this->getRealName(), 'label'],
682 3
                $template
683
            );
684 100
        } elseif ($langName = $this->parent->getLanguageName()) {
685 4
            $label = sprintf('%s.%s', $langName, $this->getRealName());
686
        } else {
687 97
            $label = $this->getRealName();
688
        }
689
690 103
        $this->setOption('label', $this->formHelper->formatLabel($label));
691 103
    }
692
693
    /**
694
     * Check if fields needs label.
695
     *
696
     * @return bool
697
     */
698 35
    protected function needsLabel()
699
    {
700
        // If field is <select> and child of choice, we don't need label for it
701 35
        $isChildSelect = $this->type == 'select' && $this->getOption('is_child') === true;
702
703 35
        if ($this->type == 'hidden' || $isChildSelect) {
704 11
            return false;
705
        }
706
707 31
        return true;
708
    }
709
710
    /**
711
     * Disable field.
712
     *
713
     * @return $this
714
     */
715 1
    public function disable()
716
    {
717 1
        $this->setOption('attr.disabled', 'disabled');
718
719 1
        return $this;
720
    }
721
722
    /**
723
     * Enable field.
724
     *
725
     * @return $this
726
     */
727 1
    public function enable()
728
    {
729 1
        Arr::forget($this->options, 'attr.disabled');
730
731 1
        return $this;
732
    }
733
734
    /**
735
     * Get validation rules for a field if any with label for attributes.
736
     *
737
     * @return array|null
738
     */
739 10
    public function getValidationRules()
740
    {
741 10
        $rules = $this->getOption('rules', []);
742 10
        $name = $this->getNameKey();
743 10
        $messages = $this->getOption('error_messages', []);
744 10
        $formName = $this->parent->getNameKey();
745
746 10
        if ($messages && $formName) {
747 1
            $newMessages = [];
748 1
            foreach ($messages as $messageKey => $message) {
749 1
                $messageKey = sprintf('%s.%s', $formName, $messageKey);
750 1
                $newMessages[$messageKey] = $message;
751
            }
752 1
            $messages = $newMessages;
753
        }
754
755 10
        if (!$rules) {
756 2
            return (new Rules([]))->setFieldName($this->getNameKey());
757
        }
758
759 9
        return (new Rules(
760 9
            [$name => $rules],
761 9
            [$name => $this->getOption('label')],
762 9
            $messages
763 9
        ))->setFieldName($this->getNameKey());
764
    }
765
766
    /**
767
     * Get this field's attributes, probably just one.
768
     *
769
     * @return array
770
     */
771 3
    public function getAllAttributes()
772
    {
773 3
        return [$this->getNameKey()];
774
    }
775
776
    /**
777
     * Get value property.
778
     *
779
     * @param mixed|null $default
780
     * @return mixed
781
     */
782 40
    public function getValue($default = null)
783
    {
784 40
        return $this->getOption($this->valueProperty, $default);
785
    }
786
787
    /**
788
     * Get default value property.
789
     *
790
     * @param mixed|null $default
791
     * @return mixed
792
     */
793 35
    public function getDefaultValue($default = null)
794
    {
795 35
        return $this->getOption($this->defaultValueProperty, $default);
796
    }
797
798
    /**
799
     * Check if provided value is valid for this type.
800
     *
801
     * @return bool
802
     */
803 98
    protected function isValidValue($value)
804
    {
805 98
        return $value !== null;
806
    }
807
808
    /**
809
     * Method initFilters used to initialize filters
810
     * from field options and bind it to the same.
811
     *
812
     * @return $this
813
     */
814 100
    protected function initFilters()
815
    {
816
        // If override status is set in field options to true
817
        // we will change filtersOverride property value to true
818
        // so we can override existing filters with registered
819
        // alias/name in addFilter method.
820 100
        $overrideStatus = $this->getOption('filters_override', false);
821 100
        if ($overrideStatus) {
822 2
            $this->setFiltersOverride(true);
823
        }
824
825
        // Get filters and bind it to field.
826 100
        $filters = $this->getOption('filters', []);
827 100
        foreach ($filters as $filter) {
828 8
            $this->addFilter($filter);
829
        }
830
831 100
        return $this;
832
    }
833
834
    /**
835
     * Method setFilters used to set filters to current filters property.
836
     *
837
     * @param  array $filters
838
     *
839
     * @return \Kris\LaravelFormBuilder\Fields\FormField
840
     */
841
    public function setFilters(array $filters)
842
    {
843
        $this->clearFilters();
844
        foreach ($filters as $filter) {
845
            $this->addFilter($filter);
846
        }
847
848
        return $this;
849
    }
850
851
    /**
852
     * Method getFilters returns array of binded filters
853
     * if there are any binded. Otherwise empty array.
854
     *
855
     * @return array
856
     */
857 23
    public function getFilters()
858
    {
859 23
        return $this->filters;
860
    }
861
862
    /**
863
     * @param  string|FilterInterface $filter
864
     *
865
     * @return \Kris\LaravelFormBuilder\Fields\FormField
866
     *
867
     * @throws FilterAlreadyBindedException
868
     */
869 8
    public function addFilter($filter)
870
    {
871
        // Resolve filter object from string/object or throw Ex.
872 8
        $filterObj = FilterResolver::instance($filter);
873
874
        // If filtersOverride is allowed we will override filter
875
        // with same alias/name if there is one with new resolved filter.
876 8
        if ($this->getFiltersOverride()) {
877 1
            if ($key = array_search($filterObj->getName(), $this->getFilters())) {
878
                $this->filters[$key] = $filterObj;
879
            } else {
880 1
                $this->filters[$filterObj->getName()] = $filterObj;
881
            }
882
        } else {
883
            // If filtersOverride is disabled and we found
884
            // equal alias defined we will throw Ex.
885 7
            if (array_key_exists($filterObj->getName(), $this->getFilters())) {
886 1
                $ex = new FilterAlreadyBindedException($filterObj->getName(), $this->getName());
887 1
                throw $ex;
888
            }
889
890
            // Filter with resolvedFilter alias/name doesn't exist
891
            // so we will bind it as new one to field.
892 7
            $this->filters[$filterObj->getName()] = $filterObj;
893
        }
894
895 8
        return $this;
896
    }
897
898
    /**
899
     * Method removeFilter used to remove filter by provided alias/name.
900
     *
901
     * @param  string $name
902
     *
903
     * @return \Kris\LaravelFormBuilder\Fields\FormField
904
     */
905 1
    public function removeFilter($name)
906
    {
907 1
        $filters = $this->getFilters();
908 1
        if (array_key_exists($name, $filters)) {
909 1
            unset($filters[$name]);
910 1
            $this->filters = $filters;
911
        }
912
913 1
        return $this;
914
    }
915
916
    /**
917
     * Method removeFilters used to remove filters by provided aliases/names.
918
     *
919
     * @param  array $filterNames
920
     *
921
     * @return \Kris\LaravelFormBuilder\Fields\FormField
922
     */
923 1
    public function removeFilters(array $filterNames)
924
    {
925 1
        $filters = $this->getFilters();
926 1
        foreach ($filterNames as $filterName) {
927 1
            if (array_key_exists($filterName, $filters)) {
928 1
                unset($filters[$filterName]);
929 1
                $this->filters = $filters;
930
            }
931
        }
932
933 1
        return $this;
934
    }
935
936
    /**
937
     * Method clearFilters used to empty current filters property.
938
     *
939
     * @return \Kris\LaravelFormBuilder\Fields\FormField
940
     */
941 1
    public function clearFilters()
942
    {
943 1
        $this->filters = [];
944 1
        return $this;
945
    }
946
947
    /**
948
     * Method used to set FiltersOverride status to provided value.
949
     *
950
     * @param $status
951
     *
952
     * @return \Kris\LaravelFormBuilder\Fields\FormField
953
     */
954 2
    public function setFiltersOverride($status)
955
    {
956 2
        $this->filtersOverride = $status;
957 2
        return $this;
958
    }
959
960
    /**
961
     * @return bool
962
     */
963 9
    public function getFiltersOverride()
964
    {
965 9
        return $this->filtersOverride;
966
    }
967
968
    /**
969
     * Method used to set Unfiltered/Unmutated field value.
970
     * Method is called before field value mutating starts - request value filtering.
971
     *
972
     * @param mixed $value
973
     *
974
     * @return \Kris\LaravelFormBuilder\Fields\FormField
975
     */
976 1
    public function setRawValue($value)
977
    {
978 1
        $this->rawValue = $value;
979 1
        return $this;
980
    }
981
982
    /**
983
     * Returns unfiltered raw value of field.
984
     *
985
     * @return mixed
986
     */
987
    public function getRawValue()
988
    {
989
        return $this->rawValue;
990
    }
991
992
    /**
993
     * Get config from the form.
994
     *
995
     * @return mixed
996
     */
997 105
    private function getConfig($key = null, $default = null)
998
    {
999 105
        return $this->parent->getConfig($key, $default);
1000
    }
1001
}
1002