Completed
Pull Request — master (#406)
by
unknown
03:49
created

Form::getConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Kris\LaravelFormBuilder;
4
5
use Illuminate\Contracts\Events\Dispatcher as EventDispatcher;
6
use Illuminate\Contracts\Validation\Factory as ValidatorFactory;
7
use Illuminate\Contracts\Validation\Validator;
8
use Illuminate\Http\Exceptions\HttpResponseException;
9
use Illuminate\Http\Request;
10
use Illuminate\Support\Arr;
11
use Kris\LaravelFormBuilder\Events\AfterFieldCreation;
12
use Kris\LaravelFormBuilder\Events\AfterFormValidation;
13
use Kris\LaravelFormBuilder\Events\BeforeFormValidation;
14
use Kris\LaravelFormBuilder\Fields\FormField;
15
use Kris\LaravelFormBuilder\Filters\FilterResolver;
16
17
class Form
18
{
19
    /**
20
     * All fields that are added.
21
     *
22
     * @var array
23
     */
24
    protected $fields = [];
25
26
    /**
27
     * Model to use.
28
     *
29
     * @var mixed
30
     */
31
    protected $model = [];
32
33
    /**
34
     * @var EventDispatcher
35
     */
36
    protected $eventDispatcher;
37
38
    /**
39
     * @var FormHelper
40
     */
41
    protected $formHelper;
42
43
    /**
44
     * Form options.
45
     *
46
     * @var array
47
     */
48
    protected $formOptions = [
49
        'method' => 'GET',
50
        'url' => null
51
    ];
52
53
	/**
54
	 * Form specific configuration.
55
	 *
56
	 * @var array
57
	 */
58
	protected $formConfig;
59
60
    /**
61
     * Additional data which can be used to build fields.
62
     *
63
     * @var array
64
     */
65
    protected $data = [];
66
67
    /**
68
     * Wether errors for each field should be shown when calling form($form) or form_rest($form).
69
     *
70
     * @var bool
71
     */
72
    protected $showFieldErrors = true;
73
74
    /**
75
     * Enable html5 validation.
76
     *
77
     * @var bool
78
     */
79
    protected $clientValidationEnabled = true;
80
81
    /**
82
     * Name of the parent form if any.
83
     *
84
     * @var string|null
85
     */
86
    protected $name = null;
87
88
    /**
89
     * @var FormBuilder
90
     */
91
    protected $formBuilder;
92
93
    /**
94
     * @var ValidatorFactory
95
     */
96
    protected $validatorFactory;
97
98
    /**
99
     * @var Validator
100
     */
101
    protected $validator = null;
102
103
    /**
104
     * @var Request
105
     */
106
    protected $request;
107
108
    /**
109
     * List of fields to not render.
110
     *
111
     * @var array
112
     **/
113
    protected $exclude = [];
114
115
    /**
116
     * Wether the form is beign rebuild.
117
     *
118
     * @var bool
119
     */
120
    protected $rebuilding = false;
121
122
    /**
123
     * @var string
124
     */
125
    protected $templatePrefix;
126
127
    /**
128
     * @var string
129
     */
130
    protected $languageName;
131
132
    /**
133
     * @var string
134
     */
135
    protected $translationTemplate;
136
137
    /**
138
     * To filter and mutate request values or not.
139
     *
140
     * @var bool
141
     */
142
    protected $lockFiltering = false;
143
144
    /**
145
     * Build the form.
146
     *
147
     * @return mixed
148
     */
149 3
    public function buildForm()
150
    {
151 3
    }
152
153
    /**
154
     * Rebuild the form from scratch.
155
     *
156
     * @return $this
157
     */
158 27
    public function rebuildForm()
159
    {
160 27
        $this->rebuilding = true;
161
        // If form is plain, buildForm method is empty, so we need to take
162
        // existing fields and add them again
163 27
        if (get_class($this) === 'Kris\LaravelFormBuilder\Form') {
164 24
            foreach ($this->fields as $name => $field) {
165
                // Remove any temp variables added in previous instance
166 13
                $options = array_except($field->getOptions(), 'tmp');
167 24
                $this->add($name, $field->getType(), $options);
168
            }
169
        } else {
170 5
            $this->buildForm();
171
        }
172 27
        $this->rebuilding = false;
173
174 27
        return $this;
175
    }
176
177
    /**
178
     * Create the FormField object.
179
     *
180
     * @param string $name
181
     * @param string $type
182
     * @param array  $options
183
     * @return FormField
184
     */
185 65
    protected function makeField($name, $type = 'text', array $options = [])
186
    {
187 65
        $this->setupFieldOptions($name, $options);
188
189 65
        $fieldName = $this->getFieldName($name);
190
191 65
        $fieldType = $this->getFieldType($type);
192
193 64
        $field = new $fieldType($fieldName, $type, $this, $options);
194
195 61
        $this->eventDispatcher->fire(new AfterFieldCreation($this, $field));
196
197 61
        return $field;
198
    }
199
200
    /**
201
     * Create a new field and add it to the form.
202
     *
203
     * @param string $name
204
     * @param string $type
205
     * @param array  $options
206
     * @param bool   $modify
207
     * @return $this
208
     */
209 67
    public function add($name, $type = 'text', array $options = [], $modify = false)
210
    {
211 67
        $this->formHelper->checkFieldName($name, get_class($this));
212
213 65
        if ($this->rebuilding && !$this->has($name)) {
214
            return $this;
215
        }
216
217 65
        $this->addField($this->makeField($name, $type, $options), $modify);
218
219 61
        return $this;
220
    }
221
222
    /**
223
     * Add a FormField to the form's fields.
224
     *
225
     * @param FormField $field
226
     * @return $this
227
     */
228 61
    protected function addField(FormField $field, $modify = false)
229
    {
230 61
        if (!$modify && !$this->rebuilding) {
231 61
            $this->preventDuplicate($field->getRealName());
232
        }
233
234
235 61
        if ($field->getType() == 'file') {
236 3
            $this->formOptions['files'] = true;
237
        }
238
239 61
        $this->fields[$field->getRealName()] = $field;
240
241 61
        return $this;
242
    }
243
244
    /**
245
     * Add field before another field.
246
     *
247
     * @param string  $name         Name of the field before which new field is added.
248
     * @param string  $fieldName    Field name which will be added.
249
     * @param string  $type
250
     * @param array   $options
251
     * @param bool $modify
252
     * @return $this
253
     */
254 1
    public function addBefore($name, $fieldName, $type = 'text', $options = [], $modify = false)
255
    {
256 1
        $offset = array_search($name, array_keys($this->fields));
257
258 1
        $beforeFields = array_slice($this->fields, 0, $offset);
259 1
        $afterFields = array_slice($this->fields, $offset);
260
261 1
        $this->fields = $beforeFields;
262
263 1
        $this->add($fieldName, $type, $options, $modify);
264
265 1
        $this->fields += $afterFields;
266
267 1
        return $this;
268
    }
269
270
    /**
271
     * Add field before another field.
272
     *
273
     * @param string  $name         Name of the field after which new field is added.
274
     * @param string  $fieldName    Field name which will be added.
275
     * @param string  $type
276
     * @param array   $options
277
     * @param bool $modify
278
     * @return $this
279
     */
280 1
    public function addAfter($name, $fieldName, $type = 'text', $options = [], $modify = false)
281
    {
282 1
        $offset = array_search($name, array_keys($this->fields));
283
284 1
        $beforeFields = array_slice($this->fields, 0, $offset + 1);
285 1
        $afterFields = array_slice($this->fields, $offset + 1);
286
287 1
        $this->fields = $beforeFields;
288
289 1
        $this->add($fieldName, $type, $options, $modify);
290
291 1
        $this->fields += $afterFields;
292
293 1
        return $this;
294
    }
295
296
    /**
297
     * Take another form and add it's fields directly to this form.
298
     *
299
     * @param mixed   $class        Form to merge.
300
     * @param array   $options
301
     * @param boolean $modify
302
     * @return $this
303
     */
304 1
    public function compose($class, array $options = [], $modify = false)
305
    {
306 1
        $options['class'] = $class;
307
308
        // If we pass a ready made form just extract the fields.
309 1
        if ($class instanceof Form) {
310 1
            $fields = $class->getFields();
311
        } elseif ($class instanceof Fields\ChildFormType) {
312
            $fields = $class->getForm()->getFields();
313
        } elseif (is_string($class)) {
314
            // If its a string of a class make it the usual way.
315
            $options['model'] = $this->model;
316
            $options['name'] = $this->name;
317
318
            $form = $this->formBuilder->create($class, $options);
319
            $fields = $form->getFields();
320
        } else {
321
            throw new \InvalidArgumentException(
322
                "[{$class}] is invalid. Please provide either a full class name, Form or ChildFormType"
323
            );
324
        }
325
326 1
        foreach ($fields as $field) {
327 1
            $this->addField($field, $modify);
328
        }
329
330 1
        return $this;
331
    }
332
333
    /**
334
     * Remove field with specified name from the form.
335
     *
336
     * @param $name
337
     * @return $this
338
     */
339 2
    public function remove($name)
340
    {
341 2
        if ($this->has($name)) {
342 2
            unset($this->fields[$name]);
343
        }
344
345 2
        return $this;
346
    }
347
348
    /**
349
     * Modify existing field. If it doesn't exist, it is added to form.
350
     *
351
     * @param string $name
352
     * @param string $type
353
     * @param array  $options
354
     * @param bool   $overwriteOptions
355
     * @return Form
356
     */
357 1
    public function modify($name, $type = 'text', array $options = [], $overwriteOptions = false)
358
    {
359
        // If we don't want to overwrite options, we merge them with old options.
360 1
        if ($overwriteOptions === false && $this->has($name)) {
361 1
            $options = $this->formHelper->mergeOptions(
362 1
                $this->getField($name)->getOptions(),
363 1
                $options
364
            );
365
        }
366
367 1
        return $this->add($name, $type, $options, true);
368
    }
369
370
    /**
371
     * Render full form.
372
     *
373
     * @param array $options
374
     * @param bool  $showStart
375
     * @param bool  $showFields
376
     * @param bool  $showEnd
377
     * @return string
378
     */
379 7
    public function renderForm(array $options = [], $showStart = true, $showFields = true, $showEnd = true)
380
    {
381 7
        return $this->render($options, $this->fields, $showStart, $showFields, $showEnd);
0 ignored issues
show
Documentation introduced by
$this->fields is of type array, but the function expects a string.

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
    /**
385
     * Render rest of the form.
386
     *
387
     * @param bool $showFormEnd
388
     * @param bool $showFields
389
     * @return string
390
     */
391 1
    public function renderRest($showFormEnd = true, $showFields = true)
392
    {
393 1
        $fields = $this->getUnrenderedFields();
394
395 1
        return $this->render([], $fields, false, $showFields, $showFormEnd);
0 ignored issues
show
Documentation introduced by
$fields is of type array, but the function expects a string.

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...
396
    }
397
398
    /**
399
     * Renders the rest of the form up until the specified field name.
400
     *
401
     * @param string $field_name
402
     * @param bool   $showFormEnd
403
     * @param bool   $showFields
404
     * @return string
405
     */
406 2
    public function renderUntil($field_name, $showFormEnd = true, $showFields = true)
407
    {
408 2
        if (!$this->has($field_name)) {
409 1
            $this->fieldDoesNotExist($field_name);
410
        }
411
412 1
        $fields = $this->getUnrenderedFields();
413
414 1
        $i = 1;
415 1
        foreach ($fields as $key => $value) {
416 1
            if ($value->getRealName() == $field_name) {
417 1
                break;
418
            }
419 1
            $i++;
420
        }
421
422 1
        $fields = array_slice($fields, 0, $i, true);
423
424 1
        return $this->render([], $fields, false, $showFields, $showFormEnd);
0 ignored issues
show
Documentation introduced by
$fields is of type array, but the function expects a string.

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...
425
    }
426
427
    /**
428
     * Get single field instance from form object.
429
     *
430
     * @param string $name
431
     * @return FormField
432
     */
433 34
    public function getField($name)
434
    {
435 34
        if ($this->has($name)) {
436 33
            return $this->fields[$name];
437
        }
438
439 1
        $this->fieldDoesNotExist($name);
440
    }
441
442
    /**
443
     * Check if form has field.
444
     *
445
     * @param string $name
446
     * @return bool
447
     */
448 61
    public function has($name)
449
    {
450 61
        return array_key_exists($name, $this->fields);
451
    }
452
453
    /**
454
     * Get all form options.
455
     *
456
     * @return array
457
     */
458 2
    public function getFormOptions()
459
    {
460 2
        return $this->formOptions;
461
    }
462
463
    /**
464
     * Get single form option.
465
     *
466
     * @param string $option
467
     * @param mixed|null $default
468
     * @return mixed
469
     */
470 129
    public function getFormOption($option, $default = null)
471
    {
472 129
        return array_get($this->formOptions, $option, $default);
473
    }
474
475
    /**
476
     * Set single form option on form.
477
     *
478
     * @param string $option
479
     * @param mixed $value
480
     *
481
     * @return $this
482
     */
483 2
    public function setFormOption($option, $value)
484
    {
485 2
        $this->formOptions[$option] = $value;
486
487 2
        return $this;
488
    }
489
490
	/**
491
	 * Get the passed config key using the custom
492
	 * form config, if any.
493
	 *
494
	 * @param string $key
495
	 * @param mixed $default
496
	 *
497
	 * @return mixed
498
	 */
499 103
	public function getConfig($key = null, $default = null)
500
	{
501 103
		return $this->formHelper->getConfig($key, $default, $this->formConfig);
502
	}
503
504
    /**
505
     * Set form options.
506
     *
507
     * @param array $formOptions
508
     * @return $this
509
     */
510 129
    public function setFormOptions(array $formOptions)
511
    {
512 129
        $this->formOptions = $this->formHelper->mergeOptions($this->formOptions, $formOptions);
513 129
        $this->checkIfNamedForm();
514 129
        $this->pullFromOptions('data', 'addData');
515 129
        $this->pullFromOptions('model', 'setupModel');
516 129
        $this->pullFromOptions('errors_enabled', 'setErrorsEnabled');
517 129
        $this->pullFromOptions('client_validation', 'setClientValidationEnabled');
518 129
        $this->pullFromOptions('template_prefix', 'setTemplatePrefix');
519 129
        $this->pullFromOptions('language_name', 'setLanguageName');
520 129
        $this->pullFromOptions('translation_template', 'setTranslationTemplate');
521
522 129
        return $this;
523
    }
524
525
    /**
526
     * Get an option from provided options and call method with that value.
527
     *
528
     * @param string $name
529
     * @param string $method
530
     */
531 129
    protected function pullFromOptions($name, $method)
532
    {
533 129
        if (array_get($this->formOptions, $name) !== null) {
534 20
            $this->{$method}(array_pull($this->formOptions, $name));
535
        }
536 129
    }
537
538
    /**
539
     * Get form http method.
540
     *
541
     * @return string
542
     */
543 3
    public function getMethod()
544
    {
545 3
        return $this->formOptions['method'];
546
    }
547
548
    /**
549
     * Set form http method.
550
     *
551
     * @param string $method
552
     * @return $this
553
     */
554 1
    public function setMethod($method)
555
    {
556 1
        $this->formOptions['method'] = $method;
557
558 1
        return $this;
559
    }
560
561
    /**
562
     * Get form action url.
563
     *
564
     * @return string
565
     */
566 3
    public function getUrl()
567
    {
568 3
        return $this->formOptions['url'];
569
    }
570
571
    /**
572
     * Set form action url.
573
     *
574
     * @param string $url
575
     * @return $this
576
     */
577 1
    public function setUrl($url)
578
    {
579 1
        $this->formOptions['url'] = $url;
580
581 1
        return $this;
582
    }
583
584
    /**
585
     * Returns the name of the form.
586
     *
587
     * @return string|null
588
     */
589 66
    public function getName()
590
    {
591 66
        return $this->name;
592
    }
593
594
    /**
595
     * Set the name of the form.
596
     *
597
     * @param string $name
598
     * @param bool $rebuild
599
     * @return $this
600
     */
601 12
    public function setName($name, $rebuild = true)
602
    {
603 12
        $this->name = $name;
604
605 12
        if ($rebuild) {
606 12
            $this->rebuildForm();
607
        }
608
609 12
        return $this;
610
    }
611
612
    /**
613
     * Get model that is bind to form object.
614
     *
615
     * @return mixed
616
     */
617 96
    public function getModel()
618
    {
619 96
        return $this->model;
620
    }
621
622
    /**
623
     * Set model to form object.
624
     *
625
     * @param mixed $model
626
     * @return $this
627
     * @deprecated deprecated since 1.6.31, will be removed in 1.7 - pass model as option when creating a form
628
     */
629 17
    public function setModel($model)
630
    {
631 17
        $this->model = $model;
632
633 17
        $this->rebuildForm();
634
635 17
        return $this;
636
    }
637
638
    /**
639
     * Setup model for form, add namespace if needed for child forms.
640
     *
641
     * @return $this
642
     */
643 20
    protected function setupModel($model)
644
    {
645 20
        $this->model = $model;
646
647 20
        return $this;
648
    }
649
650
    /**
651
     * Get all fields.
652
     *
653
     * @return FormField[]
654
     */
655 129
    public function getFields()
656
    {
657 129
        return $this->fields;
658
    }
659
660
    /**
661
     * Get field dynamically.
662
     *
663
     * @param string $name
664
     * @return FormField
665
     */
666 20
    public function __get($name)
667
    {
668 20
        if ($this->has($name)) {
669 19
            return $this->getField($name);
670
        }
671 3
    }
672
673
    /**
674
     * Check if field exists when fetched using magic methods.
675
     *
676
     * @param string $name
677
     * @return bool
678
     */
679
    public function __isset($name)
680
    {
681
        return $this->has($name);
682
    }
683
684
    /**
685
     * Set the Event Dispatcher to fire Laravel events.
686
     *
687
     * @param EventDispatcher $eventDispatcher
688
     * @return $this
689
     */
690 129
    public function setEventDispatcher(EventDispatcher $eventDispatcher)
691
    {
692 129
        $this->eventDispatcher = $eventDispatcher;
693
694 129
        return $this;
695
    }
696
697
    /**
698
     * Set the form helper only on first instantiation.
699
     *
700
     * @param FormHelper $formHelper
701
     * @return $this
702
     */
703 129
    public function setFormHelper(FormHelper $formHelper)
704
    {
705 129
        $this->formHelper = $formHelper;
706
707 129
        return $this;
708
    }
709
710
    /**
711
     * Get form helper.
712
     *
713
     * @return FormHelper
714
     */
715 101
    public function getFormHelper()
716
    {
717 101
        return $this->formHelper;
718
    }
719
720
    /**
721
     * Add custom field.
722
     *
723
     * @param $name
724
     * @param $class
725
     */
726 2
    public function addCustomField($name, $class)
727
    {
728 2
        if ($this->rebuilding && $this->formHelper->hasCustomField($name)) {
729
            return $this;
730
        }
731
732 2
        $this->formHelper->addCustomField($name, $class);
733 2
    }
734
735
    /**
736
     * Returns wether form errors should be shown under every field.
737
     *
738
     * @return bool
739
     */
740 101
    public function haveErrorsEnabled()
741
    {
742 101
        return $this->showFieldErrors;
743
    }
744
745
    /**
746
     * Enable or disable showing errors under fields
747
     *
748
     * @param bool $enabled
749
     * @return $this
750
     */
751 1
    public function setErrorsEnabled($enabled)
752
    {
753 1
        $this->showFieldErrors = (bool) $enabled;
754
755 1
        return $this;
756
    }
757
758
    /**
759
     * Is client validation enabled?
760
     *
761
     * @return bool
762
     */
763 101
    public function clientValidationEnabled()
764
    {
765 101
        return $this->clientValidationEnabled;
766
    }
767
768
    /**
769
     * Enable/disable client validation.
770
     *
771
     * @param bool $enable
772
     * @return $this
773
     */
774 2
    public function setClientValidationEnabled($enable)
775
    {
776 2
        $this->clientValidationEnabled = (bool) $enable;
777
778 2
        return $this;
779
    }
780
781
    /**
782
     * Add any aditional data that field needs (ex. array of choices).
783
     *
784
     * @deprecated deprecated since 1.6.20, will be removed in 1.7 - use 3rd param on create, or 2nd on plain method to pass data
785
     * will be switched to protected in 1.7.
786
     * @param string $name
787
     * @param mixed $data
788
     */
789 1
    public function setData($name, $data)
790
    {
791 1
        $this->data[$name] = $data;
792 1
    }
793
794
    /**
795
     * Get single additional data.
796
     *
797
     * @param string $name
798
     * @param null   $default
799
     * @return mixed
800
     */
801 20
    public function getData($name = null, $default = null)
802
    {
803 20
        if (is_null($name)) {
804 19
            return $this->data;
805
        }
806
807 1
        return array_get($this->data, $name, $default);
808
    }
809
810
    /**
811
     * Add multiple peices of data at once.
812
     *
813
     * @deprecated deprecated since 1.6.12, will be removed in 1.7 - use 3rd param on create, or 2nd on plain method to pass data
814
     * will be switched to protected in 1.7.
815
     * @param $data
816
     * @return $this
817
     **/
818 129
    public function addData(array $data)
819
    {
820 129
        foreach ($data as $key => $value) {
821 1
            $this->setData($key, $value);
0 ignored issues
show
Deprecated Code introduced by
The method Kris\LaravelFormBuilder\Form::setData() has been deprecated with message: deprecated since 1.6.20, will be removed in 1.7 - use 3rd param on create, or 2nd on plain method to pass data
will be switched to protected in 1.7.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
822
        }
823
824 129
        return $this;
825
    }
826
827
    /**
828
     * Get current request.
829
     *
830
     * @return \Illuminate\Http\Request
831
     */
832 129
    public function getRequest()
833
    {
834 129
        return $this->request;
835
    }
836
837
    /**
838
     * Set request on form.
839
     *
840
     * @param Request $request
841
     * @return $this
842
     */
843 129
    public function setRequest(Request $request)
844
    {
845 129
        $this->request = $request;
846
847 129
        return $this;
848
    }
849
850
    /**
851
     * Get template prefix that is prepended to all template paths.
852
     *
853
     * @return string
854
     */
855 39
    public function getTemplatePrefix()
856
    {
857 39
        if ($this->templatePrefix !== null) {
858 4
            return $this->templatePrefix;
859
        }
860
861 35
        return $this->getConfig('template_prefix');
862
    }
863
864
    /**
865
     * Set a template prefix for the form and its fields.
866
     *
867
     * @param string $prefix
868
     * @return $this
869
     */
870 4
    public function setTemplatePrefix($prefix)
871
    {
872 4
        $this->templatePrefix = (string) $prefix;
873
874 4
        return $this;
875
    }
876
877
    /**
878
     * Get the language name.
879
     *
880
     * @return string
881
     */
882 98
    public function getLanguageName()
883
    {
884 98
        return $this->languageName;
885
    }
886
887
    /**
888
     * Set a language name, used as prefix for translated strings.
889
     *
890
     * @param string $prefix
891
     * @return $this
892
     */
893 13
    public function setLanguageName($prefix)
894
    {
895 13
        $this->languageName = (string) $prefix;
896
897 13
        return $this;
898
    }
899
900
    /**
901
     * Get the translation template.
902
     *
903
     * @return string
904
     */
905 100
    public function getTranslationTemplate()
906
    {
907 100
        return $this->translationTemplate;
908
    }
909
910
    /**
911
     * Set a translation template, used to determine labels for fields.
912
     *
913
     * @param string $template
914
     * @return $this
915
     */
916 11
    public function setTranslationTemplate($template)
917
    {
918 11
        $this->translationTemplate = (string) $template;
919
920 11
        return $this;
921
    }
922
923
    /**
924
     * Render the form.
925
     *
926
     * @param array $options
927
     * @param string $fields
928
     * @param bool $showStart
929
     * @param bool $showFields
930
     * @param bool $showEnd
931
     * @return string
932
     */
933 9
    protected function render($options, $fields, $showStart, $showFields, $showEnd)
934
    {
935 9
        $formOptions = $this->formHelper->mergeOptions($this->formOptions, $options);
936
937 9
        $this->setupNamedModel();
938
939 9
        return $this->formHelper->getView()
940 9
            ->make($this->getTemplate())
941 9
            ->with(compact('showStart', 'showFields', 'showEnd'))
942 9
            ->with('formOptions', $formOptions)
943 9
            ->with('fields', $fields)
944 9
            ->with('model', $this->getModel())
945 9
            ->with('exclude', $this->exclude)
946 9
            ->with('form', $this)
947 9
            ->render();
948
    }
949
950
    /**
951
     * Get template from options if provided, otherwise fallback to config.
952
     *
953
     * @return mixed
954
     */
955 9
    protected function getTemplate()
956
    {
957 9
        return $this->getTemplatePrefix() . $this->getFormOption('template', $this->getConfig('form'));
958
    }
959
960
    /**
961
     * Get all fields that are not rendered.
962
     *
963
     * @return array
964
     */
965 2
    protected function getUnrenderedFields()
966
    {
967 2
        $unrenderedFields = [];
968
969 2
        foreach ($this->fields as $field) {
970 2
            if (!$field->isRendered()) {
971 2
                $unrenderedFields[] = $field;
972 2
                continue;
973
            }
974
        }
975
976 2
        return $unrenderedFields;
977
    }
978
979
    /**
980
     * Prevent adding fields with same name.
981
     *
982
     * @param string $name
983
     * @throws \InvalidArgumentException
984
     * @return void
985
     */
986 61
    protected function preventDuplicate($name)
987
    {
988 61
        if ($this->has($name)) {
989 1
            throw new \InvalidArgumentException('Field ['.$name.'] already exists in the form '.get_class($this));
990
        }
991 61
    }
992
993
    /**
994
     * Returns and checks the type of the field.
995
     *
996
     * @param string $type
997
     * @return string
998
     */
999 65
    protected function getFieldType($type)
1000
    {
1001 65
        $fieldType = $this->formHelper->getFieldType($type);
1002
1003 64
        return $fieldType;
1004
    }
1005
1006
    /**
1007
     * Check if form is named form.
1008
     *
1009
     * @return void
1010
     */
1011 129
    protected function checkIfNamedForm()
1012
    {
1013 129
        if ($this->getFormOption('name')) {
1014 8
            $this->name = array_pull($this->formOptions, 'name', $this->name);
1015
        }
1016 129
    }
1017
1018
    /**
1019
     * Set up options on single field depending on form options.
1020
     *
1021
     * @param string $name
1022
     * @param $options
1023
     */
1024 65
    protected function setupFieldOptions($name, &$options)
1025
    {
1026 65
        $options['real_name'] = $name;
1027 65
    }
1028
1029
    /**
1030
     * Set namespace to model if form is named so the data is bound properly.
1031
     * Returns true if model is changed, otherwise false.
1032
     *
1033
     * @return bool
1034
     */
1035 9
    protected function setupNamedModel()
1036
    {
1037 9
        if (!$this->getModel() || !$this->getName()) {
1038 8
            return false;
1039
        }
1040
1041 1
        $dotName = $this->formHelper->transformToDotSyntax($this->getName());
1042 1
        $model = $this->formHelper->convertModelToArray($this->getModel());
1043
1044 1
        if (!array_get($model, $dotName)) {
0 ignored issues
show
Bug introduced by
It seems like $model defined by $this->formHelper->conve...rray($this->getModel()) on line 1042 can also be of type null or object; however, array_get() does only seem to accept object<ArrayAccess>|array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1045 1
            $newModel = [];
1046 1
            array_set($newModel, $dotName, $model);
1047 1
            $this->model = $newModel;
1048
1049 1
            return true;
1050
        }
1051
1052
        return false;
1053
    }
1054
1055
    /**
1056
     * Set form builder instance on helper so we can use it later.
1057
     *
1058
     * @param FormBuilder $formBuilder
1059
     * @return $this
1060
     */
1061 129
    public function setFormBuilder(FormBuilder $formBuilder)
1062
    {
1063 129
        $this->formBuilder = $formBuilder;
1064
1065 129
        return $this;
1066
    }
1067
1068
    /**
1069
     * Returns the instance of the FormBuilder.
1070
     *
1071
     * @return FormBuilder
1072
     */
1073 12
    public function getFormBuilder()
1074
    {
1075 12
        return $this->formBuilder;
1076
    }
1077
1078
    /**
1079
     * Set the Validator instance on this so we can use it later.
1080
     *
1081
     * @param ValidatorFactory $validator
1082
     * @return $this
1083
     */
1084 129
    public function setValidator(ValidatorFactory $validator)
1085
    {
1086 129
        $this->validatorFactory = $validator;
1087
1088 129
        return $this;
1089
    }
1090
1091
    /**
1092
     * Returns the validator instance.
1093
     *
1094
     * @return Validator
1095
     */
1096 1
    public function getValidator()
1097
    {
1098 1
        return $this->validator;
1099
    }
1100
1101
    /**
1102
     * Exclude some fields from rendering.
1103
     *
1104
     * @return $this
1105
     */
1106
    public function exclude(array $fields)
1107
    {
1108
        $this->exclude = array_merge($this->exclude, $fields);
1109
1110
        return $this;
1111
    }
1112
1113
    /**
1114
     * If form is named form, modify names to be contained in single key (parent[child_field_name]).
1115
     *
1116
     * @param string $name
1117
     * @return string
1118
     */
1119 65
    protected function getFieldName($name)
1120
    {
1121 65
        $formName = $this->getName();
1122 65
        if ($formName !== null) {
1123 14
            if (strpos($formName, '[') !== false || strpos($formName, ']') !== false) {
1124 6
                return $this->formHelper->transformToBracketSyntax(
1125 6
                    $this->formHelper->transformToDotSyntax(
1126 6
                        $formName . '[' . $name . ']'
1127
                    )
1128
                );
1129
            }
1130
1131 11
            return $formName . '[' . $name . ']';
1132
        }
1133
1134 65
        return $name;
1135
    }
1136
1137
    /**
1138
     * Disable all fields in a form.
1139
     */
1140 1
    public function disableFields()
1141
    {
1142 1
        foreach ($this->fields as $field) {
1143 1
            $field->disable();
1144
        }
1145 1
    }
1146
1147
    /**
1148
     * Enable all fields in a form.
1149
     */
1150 1
    public function enableFields()
1151
    {
1152 1
        foreach ($this->fields as $field) {
1153 1
            $field->enable();
1154
        }
1155 1
    }
1156
1157
    /**
1158
     * Validate the form.
1159
     *
1160
     * @param array $validationRules
1161
     * @param array $messages
1162
     * @return Validator
1163
     */
1164 9
    public function validate($validationRules = [], $messages = [])
1165
    {
1166 9
        $this->setupModel($this->getRequest()->all());
1167 9
        $this->rebuildForm();
1168 9
        $fieldRules = $this->formHelper->mergeFieldsRules($this->fields);
1169 9
        $rules = array_merge($fieldRules['rules'], $validationRules);
1170 9
        $messages = array_merge($fieldRules['error_messages'], $messages);
1171
1172 9
        $this->validator = $this->validatorFactory->make($this->getRequest()->all(), $rules, $messages);
1173 9
        $this->validator->setAttributeNames($fieldRules['attributes']);
1174
1175 9
        $this->eventDispatcher->fire(new BeforeFormValidation($this, $this->validator));
1176
1177 9
        return $this->validator;
1178
    }
1179
1180
    /**
1181
     * Get validation rules for the form.
1182
     *
1183
     * @param array $overrideRules
1184
     * @return array
1185
     */
1186 1
    public function getRules($overrideRules = [])
1187
    {
1188 1
        $fieldRules = $this->formHelper->mergeFieldsRules($this->fields);
1189
1190 1
        return array_merge($fieldRules['rules'], $overrideRules);
1191
    }
1192
1193
    /**
1194
     * Redirects to a destination when form is invalid.
1195
     *
1196
     * @param  string|null $destination The target url.
1197
     * @return HttpResponseException
1198
     */
1199 3
    public function redirectIfNotValid($destination = null)
1200
    {
1201 3
        if (! $this->isValid()) {
1202 3
            $response = redirect($destination);
1203
1204 3
            if (is_null($destination)) {
1205 2
                $response = $response->back();
1206
            }
1207
1208 3
            $response = $response->withErrors($this->getErrors())->withInput();
1209
1210 3
            throw new HttpResponseException($response);
1211
        }
1212
    }
1213
1214
    /**
1215
     * Get all form field attributes, including child forms, in a flat array.
1216
     *
1217
     * @return array
1218
     */
1219 3
    public function getAllAttributes()
1220
    {
1221 3
        return $this->formHelper->mergeAttributes($this->fields);
1222
    }
1223
1224
    /**
1225
     * Check if the form is valid.
1226
     *
1227
     * @return bool
1228
     */
1229 9
    public function isValid()
1230
    {
1231 9
        if (!$this->validator) {
1232 8
            $this->validate();
1233
        }
1234
1235 9
        $isValid = !$this->validator->fails();
1236
1237 9
        $this->formHelper->alterValid($this, $this, $isValid);
1238
1239 9
        $this->eventDispatcher->fire(new AfterFormValidation($this, $this->validator, $isValid));
1240
1241 9
        return $isValid;
1242
    }
1243
1244
    /**
1245
     * Optionally change the validation result, and/or add error messages.
1246
     *
1247
     * @param Form $mainForm
1248
     * @param bool $isValid
1249
     * @return void|array
1250
     */
1251 9
    public function alterValid(Form $mainForm, &$isValid)
0 ignored issues
show
Unused Code introduced by
The parameter $mainForm is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $isValid is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1252
    {
1253
        // return ['name' => ['Some other error about the Name field.']];
1254 9
    }
1255
1256
    /**
1257
     * Get validation errors.
1258
     *
1259
     * @return array
1260
     */
1261 8
    public function getErrors()
1262
    {
1263 8
        if (!$this->validator || !$this->validator instanceof Validator) {
1264 1
            throw new \InvalidArgumentException(
1265 1
                sprintf(
1266 1
                    'Form %s was not validated. To validate it, call "isValid" method before retrieving the errors',
1267 1
                    get_class($this)
1268
                )
1269
            );
1270
        }
1271
1272 7
        return $this->validator->getMessageBag()->getMessages();
1273
    }
1274
1275
    /**
1276
     * Get all Request values from all fields, and nothing else.
1277
     *
1278
     * @param bool $with_nulls
1279
     * @return array
1280
     */
1281 3
    public function getFieldValues($with_nulls = true)
1282
    {
1283 3
        $request_values = $this->getRequest()->all();
1284
1285 3
        $values = [];
1286 3
        foreach ($this->getAllAttributes() as $attribute) {
1287 3
            $value = Arr::get($request_values, $attribute);
1288 3
            if ($with_nulls || $value !== null) {
1289 3
                Arr::set($values, $attribute, $value);
1290
            }
1291
        }
1292
1293
        // If this form is a child form, cherry pick a part
1294 3
        if ($prefix = $this->getName()) {
1295 1
            $prefix = $this->formHelper->transformToDotSyntax($prefix);
1296 1
            $values = Arr::get($values, $prefix);
1297
        }
1298
1299
        // Allow form-specific value alters
1300 3
        $this->formHelper->alterFieldValues($this, $values);
1301
1302 3
        return $values;
1303
    }
1304
1305
    /**
1306
     * Optionally mess with this form's $values before it's returned from getFieldValues().
1307
     *
1308
     * @param array $values
1309
     * @return void
1310
     */
1311 3
    public function alterFieldValues(array &$values)
0 ignored issues
show
Unused Code introduced by
The parameter $values is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1312
    {
1313 3
    }
1314
1315
    /**
1316
     * Throw an exception indicating a field does not exist on the class.
1317
     *
1318
     * @param string $name
1319
     * @throws \InvalidArgumentException
1320
     * @return void
1321
     */
1322 2
    protected function fieldDoesNotExist($name)
1323
    {
1324 2
        throw new \InvalidArgumentException('Field ['.$name.'] does not exist in '.get_class($this));
1325
    }
1326
1327
    /**
1328
     * Method filterFields used as *Main* method for starting
1329
     * filtering and request field mutating process.
1330
     *
1331
     * @return \Kris\LaravelFormBuilder\Form
1332
     */
1333 129
    public function filterFields()
1334
    {
1335
        // If filtering is unlocked/allowed we can start with filtering process.
1336 129
        if (!$this->isFilteringLocked()) {
1337
            // Init required vars.
1338 129
            $filters = $this->getFilters();
1339 129
            $request = $this->getRequest();
1340
1341 129
            if (!empty($filters)) {
1342 16
                foreach ($filters as $field => $fieldFilters) {
1343
                    // If field exist in request object, try to mutate/filter
1344
                    // it to filtered value if there is one.
1345 16
                    if (array_key_exists($field, $request->all())) {
1346
                        // Assign current Raw/Unmutated value from request.
1347 1
                        $this->fields[$field]->setRawValue($request[$field]);
1348 1
                        foreach ($fieldFilters as $filter) {
1349 1
                            $filterObj = FilterResolver::instance($filter);
1350 16
                            $request[$field] = $filterObj->filter($request[$field]);
1351
                        }
1352
                    }
1353
                }
1354
            }
1355
        }
1356
1357 129
        return $this;
1358
    }
1359
1360
    /**
1361
     * Method getFilters used to return array of all binded filters to form fields.
1362
     *
1363
     * @return array
1364
     */
1365 129
    public function getFilters()
1366
    {
1367 129
        $filters = [];
1368 129
        foreach ($this->getFields() as $field) {
1369 17
            $filters[$field->getName()] = $field->getFilters();
1370
        }
1371
1372 129
        return $filters;
1373
    }
1374
1375
    /**
1376
     * If lockFiltering is set to true then we will not
1377
     * filter fields and mutate request data binded to fields.
1378
     *
1379
     * @return \Kris\LaravelFormBuilder\Form
1380
     */
1381 1
    public function lockFiltering()
1382
    {
1383 1
        $this->lockFiltering = true;
1384 1
        return $this;
1385
    }
1386
1387
    /**
1388
     * Unlock fields filtering/mutating.
1389
     *
1390
     * @return \Kris\LaravelFormBuilder\Form
1391
     */
1392
    public function unlockFiltering()
1393
    {
1394
        $this->lockFiltering = false;
1395
        return $this;
1396
    }
1397
1398
    /**
1399
     * Method isFilteringLocked used to check
1400
     * if current filteringLocked property status is set to true.
1401
     *
1402
     * @return bool
1403
     */
1404 129
    public function isFilteringLocked()
1405
    {
1406 129
        return !$this->lockFiltering ? false : true;
1407
    }
1408
1409
    /**
1410
     * Method getRawValues returns Unfiltered/Unmutated fields -> values.
1411
     *
1412
     * @return array
1413
     */
1414
    public function getRawValues()
1415
    {
1416
        $rawValues = [];
1417
        foreach ($this->getFields() as $field) {
1418
            $rawValues[$field->getName()] = $field->getRawValue();
1419
        }
1420
1421
        return $rawValues;
1422
    }
1423
}
1424