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

Form::getFormConfig()   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 0
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 config
45
     *
46
     * @var array
47
     */
48
    protected $formConfig = [];
49
50
    /**
51
     * Form options.
52
     *
53
     * @var array
54
     */
55
    protected $formOptions = [
56
        'method' => 'GET',
57
        'url' => null
58
    ];
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 4
    public function buildForm()
150
    {
151 4
    }
152
153
    /**
154
     * Rebuild the form from scratch.
155
     *
156
     * @return $this
157
     */
158 19
    public function rebuildForm()
159
    {
160 19
        $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 19
        if (get_class($this) === 'Kris\LaravelFormBuilder\Form') {
164 18
            foreach ($this->fields as $name => $field) {
165
                // Remove any temp variables added in previous instance
166 7
                $options = array_except($field->getOptions(), 'tmp');
167 18
                $this->add($name, $field->getType(), $options);
168
            }
169
        } else {
170 3
            $this->buildForm();
171
        }
172 19
        $this->rebuilding = false;
173
174 19
        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 66
    protected function makeField($name, $type = 'text', array $options = [])
186
    {
187 66
        $this->setupFieldOptions($name, $options);
188
189 66
        $fieldName = $this->getFieldName($name);
190
191 66
        $fieldType = $this->getFieldType($type);
192
193 65
        $field = new $fieldType($fieldName, $type, $this, $options);
194
195 62
        $this->eventDispatcher->fire(new AfterFieldCreation($this, $field));
196
197 62
        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 68
    public function add($name, $type = 'text', array $options = [], $modify = false)
210
    {
211 68
        $this->formHelper->checkFieldName($name, get_class($this));
212
213 66
        if ($this->rebuilding && !$this->has($name)) {
214
            return $this;
215
        }
216
217 66
        $this->addField($this->makeField($name, $type, $options), $modify);
218
219 62
        return $this;
220
    }
221
222
    /**
223
     * Add a FormField to the form's fields.
224
     *
225
     * @param FormField $field
226
     * @return $this
227
     */
228 62
    protected function addField(FormField $field, $modify = false)
229
    {
230 62
        if (!$modify && !$this->rebuilding) {
231 62
            $this->preventDuplicate($field->getRealName());
232
        }
233
234
235 62
        if ($field->getType() == 'file') {
236 3
            $this->formOptions['files'] = true;
237
        }
238
239 62
        $this->fields[$field->getRealName()] = $field;
240
241 62
        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 62
    public function has($name)
449
    {
450 62
        return array_key_exists($name, $this->fields);
451
    }
452
453
    /**
454
     * Get form config.
455
     *
456
     * @return array
457
     */
458 18
    public function getFormConfig()
459
    {
460 18
        return $this->formConfig;
461
    }
462
463
    /**
464
     * Get all form options.
465
     *
466
     * @return array
467
     */
468 2
    public function getFormOptions()
469
    {
470 2
        return $this->formOptions;
471
    }
472
473
    /**
474
     * Get single form option.
475
     *
476
     * @param string $option
477
     * @param mixed|null $default
478
     * @return mixed
479
     */
480 130
    public function getFormOption($option, $default = null)
481
    {
482 130
        return array_get($this->formOptions, $option, $default);
483
    }
484
485
    /**
486
     * Set single form option on form.
487
     *
488
     * @param string $option
489
     * @param mixed $value
490
     *
491
     * @return $this
492
     */
493 2
    public function setFormOption($option, $value)
494
    {
495 2
        $this->formOptions[$option] = $value;
496
497 2
        return $this;
498
    }
499
500
    /**
501
     * Set form options.
502
     *
503
     * @param array $formOptions
504
     * @return $this
505
     */
506 130
    public function setFormOptions(array $formOptions)
507
    {
508 130
        $this->formOptions = $this->formHelper->mergeOptions($this->formOptions, $formOptions);
509 130
        $this->checkIfNamedForm();
510 130
        $this->pullFromOptions('data', 'addData');
511 130
        $this->pullFromOptions('model', 'setupModel');
512 130
        $this->pullFromOptions('errors_enabled', 'setErrorsEnabled');
513 130
        $this->pullFromOptions('client_validation', 'setClientValidationEnabled');
514 130
        $this->pullFromOptions('template_prefix', 'setTemplatePrefix');
515 130
        $this->pullFromOptions('language_name', 'setLanguageName');
516 130
        $this->pullFromOptions('translation_template', 'setTranslationTemplate');
517
518 130
        return $this;
519
    }
520
521
    /**
522
     * Get an option from provided options and call method with that value.
523
     *
524
     * @param string $name
525
     * @param string $method
526
     */
527 130
    protected function pullFromOptions($name, $method)
528
    {
529 130
        if (array_get($this->formOptions, $name) !== null) {
530 20
            $this->{$method}(array_pull($this->formOptions, $name));
531
        }
532 130
    }
533
534
    /**
535
     * Get form http method.
536
     *
537
     * @return string
538
     */
539 3
    public function getMethod()
540
    {
541 3
        return $this->formOptions['method'];
542
    }
543
544
    /**
545
     * Set form http method.
546
     *
547
     * @param string $method
548
     * @return $this
549
     */
550 1
    public function setMethod($method)
551
    {
552 1
        $this->formOptions['method'] = $method;
553
554 1
        return $this;
555
    }
556
557
    /**
558
     * Get form action url.
559
     *
560
     * @return string
561
     */
562 3
    public function getUrl()
563
    {
564 3
        return $this->formOptions['url'];
565
    }
566
567
    /**
568
     * Set form action url.
569
     *
570
     * @param string $url
571
     * @return $this
572
     */
573 1
    public function setUrl($url)
574
    {
575 1
        $this->formOptions['url'] = $url;
576
577 1
        return $this;
578
    }
579
580
    /**
581
     * Returns the name of the form.
582
     *
583
     * @return string|null
584
     */
585 67
    public function getName()
586
    {
587 67
        return $this->name;
588
    }
589
590
    /**
591
     * Set the name of the form.
592
     *
593
     * @param string $name
594
     * @param bool $rebuild
595
     * @return $this
596
     */
597 12
    public function setName($name, $rebuild = true)
598
    {
599 12
        $this->name = $name;
600
601 12
        if ($rebuild) {
602 12
            $this->rebuildForm();
603
        }
604
605 12
        return $this;
606
    }
607
608
    /**
609
     * Get model that is bind to form object.
610
     *
611
     * @return mixed
612
     */
613 97
    public function getModel()
614
    {
615 97
        return $this->model;
616
    }
617
618
    /**
619
     * Set model to form object.
620
     *
621
     * @param mixed $model
622
     * @return $this
623
     * @deprecated deprecated since 1.6.31, will be removed in 1.7 - pass model as option when creating a form
624
     */
625 17
    public function setModel($model)
626
    {
627 17
        $this->model = $model;
628
629 17
        $this->rebuildForm();
630
631 17
        return $this;
632
    }
633
634
    /**
635
     * Setup model for form, add namespace if needed for child forms.
636
     *
637
     * @return $this
638
     */
639 12
    protected function setupModel($model)
640
    {
641 12
        $this->model = $model;
642
643 12
        return $this;
644
    }
645
646
    /**
647
     * Get all fields.
648
     *
649
     * @return FormField[]
650
     */
651 130
    public function getFields()
652
    {
653 130
        return $this->fields;
654
    }
655
656
    /**
657
     * Get field dynamically.
658
     *
659
     * @param string $name
660
     * @return FormField
661
     */
662 20
    public function __get($name)
663
    {
664 20
        if ($this->has($name)) {
665 19
            return $this->getField($name);
666
        }
667 3
    }
668
669
    /**
670
     * Check if field exists when fetched using magic methods.
671
     *
672
     * @param string $name
673
     * @return bool
674
     */
675
    public function __isset($name)
676
    {
677
        return $this->has($name);
678
    }
679
680
    /**
681
     * Set the Event Dispatcher to fire Laravel events.
682
     *
683
     * @param EventDispatcher $eventDispatcher
684
     * @return $this
685
     */
686 130
    public function setEventDispatcher(EventDispatcher $eventDispatcher)
687
    {
688 130
        $this->eventDispatcher = $eventDispatcher;
689
690 130
        return $this;
691
    }
692
693
    /**
694
     * Set the form helper only on first instantiation.
695
     *
696
     * @param FormHelper $formHelper
697
     * @return $this
698
     */
699 130
    public function setFormHelper(FormHelper $formHelper)
700
    {
701 130
        $this->formHelper = $formHelper;
702
703 130
        return $this;
704
    }
705
706
    /**
707
     * Get form helper.
708
     *
709
     * @return FormHelper
710
     */
711 102
    public function getFormHelper()
712
    {
713 102
        return $this->formHelper;
714
    }
715
716
    /**
717
     * Add custom field.
718
     *
719
     * @param $name
720
     * @param $class
721
     */
722 2
    public function addCustomField($name, $class)
723
    {
724 2
        if ($this->rebuilding && $this->formHelper->hasCustomField($name)) {
725
            return $this;
726
        }
727
728 2
        $this->formHelper->addCustomField($name, $class);
729 2
    }
730
731
    /**
732
     * Returns wether form errors should be shown under every field.
733
     *
734
     * @return bool
735
     */
736 102
    public function haveErrorsEnabled()
737
    {
738 102
        return $this->showFieldErrors;
739
    }
740
741
    /**
742
     * Enable or disable showing errors under fields
743
     *
744
     * @param bool $enabled
745
     * @return $this
746
     */
747 1
    public function setErrorsEnabled($enabled)
748
    {
749 1
        $this->showFieldErrors = (bool) $enabled;
750
751 1
        return $this;
752
    }
753
754
    /**
755
     * Is client validation enabled?
756
     *
757
     * @return bool
758
     */
759 102
    public function clientValidationEnabled()
760
    {
761 102
        return $this->clientValidationEnabled;
762
    }
763
764
    /**
765
     * Enable/disable client validation.
766
     *
767
     * @param bool $enable
768
     * @return $this
769
     */
770 2
    public function setClientValidationEnabled($enable)
771
    {
772 2
        $this->clientValidationEnabled = (bool) $enable;
773
774 2
        return $this;
775
    }
776
777
    /**
778
     * Add any aditional data that field needs (ex. array of choices).
779
     *
780
     * @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
781
     * will be switched to protected in 1.7.
782
     * @param string $name
783
     * @param mixed $data
784
     */
785 1
    public function setData($name, $data)
786
    {
787 1
        $this->data[$name] = $data;
788 1
    }
789
790
    /**
791
     * Get single additional data.
792
     *
793
     * @param string $name
794
     * @param null   $default
795
     * @return mixed
796
     */
797 20
    public function getData($name = null, $default = null)
798
    {
799 20
        if (is_null($name)) {
800 19
            return $this->data;
801
        }
802
803 1
        return array_get($this->data, $name, $default);
804
    }
805
806
    /**
807
     * Add multiple peices of data at once.
808
     *
809
     * @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
810
     * will be switched to protected in 1.7.
811
     * @param $data
812
     * @return $this
813
     **/
814 130
    public function addData(array $data)
815
    {
816 130
        foreach ($data as $key => $value) {
817 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...
818
        }
819
820 130
        return $this;
821
    }
822
823
    /**
824
     * Get current request.
825
     *
826
     * @return \Illuminate\Http\Request
827
     */
828 130
    public function getRequest()
829
    {
830 130
        return $this->request;
831
    }
832
833
    /**
834
     * Set request on form.
835
     *
836
     * @param Request $request
837
     * @return $this
838
     */
839 130
    public function setRequest(Request $request)
840
    {
841 130
        $this->request = $request;
842
843 130
        return $this;
844
    }
845
846
    /**
847
     * Get template prefix that is prepended to all template paths.
848
     *
849
     * @return string
850
     */
851 39
    public function getTemplatePrefix()
852
    {
853 39
        if ($this->templatePrefix !== null) {
854 4
            return $this->templatePrefix;
855
        }
856
857 35
        return $this->formHelper->getConfig('template_prefix');
858
    }
859
860
    /**
861
     * Set a template prefix for the form and its fields.
862
     *
863
     * @param string $prefix
864
     * @return $this
865
     */
866 4
    public function setTemplatePrefix($prefix)
867
    {
868 4
        $this->templatePrefix = (string) $prefix;
869
870 4
        return $this;
871
    }
872
873
    /**
874
     * Get the language name.
875
     *
876
     * @return string
877
     */
878 99
    public function getLanguageName()
879
    {
880 99
        return $this->languageName;
881
    }
882
883
    /**
884
     * Set a language name, used as prefix for translated strings.
885
     *
886
     * @param string $prefix
887
     * @return $this
888
     */
889 13
    public function setLanguageName($prefix)
890
    {
891 13
        $this->languageName = (string) $prefix;
892
893 13
        return $this;
894
    }
895
896
    /**
897
     * Get the translation template.
898
     *
899
     * @return string
900
     */
901 101
    public function getTranslationTemplate()
902
    {
903 101
        return $this->translationTemplate;
904
    }
905
906
    /**
907
     * Set a translation template, used to determine labels for fields.
908
     *
909
     * @param string $template
910
     * @return $this
911
     */
912 11
    public function setTranslationTemplate($template)
913
    {
914 11
        $this->translationTemplate = (string) $template;
915
916 11
        return $this;
917
    }
918
919
    /**
920
     * Render the form.
921
     *
922
     * @param array $options
923
     * @param string $fields
924
     * @param bool $showStart
925
     * @param bool $showFields
926
     * @param bool $showEnd
927
     * @return string
928
     */
929 9
    protected function render($options, $fields, $showStart, $showFields, $showEnd)
930
    {
931 9
        $formOptions = $this->formHelper->mergeOptions($this->formOptions, $options);
932
933 9
        $this->setupNamedModel();
934
935 9
        return $this->formHelper->getView()
936 9
            ->make($this->getTemplate())
937 9
            ->with(compact('showStart', 'showFields', 'showEnd'))
938 9
            ->with('formOptions', $formOptions)
939 9
            ->with('fields', $fields)
940 9
            ->with('model', $this->getModel())
941 9
            ->with('exclude', $this->exclude)
942 9
            ->with('form', $this)
943 9
            ->render();
944
    }
945
946
    /**
947
     * Get template from options if provided, otherwise fallback to config.
948
     *
949
     * @return mixed
950
     */
951 9
    protected function getTemplate()
952
    {
953 9
        return $this->getTemplatePrefix() . $this->getFormOption('template', $this->formHelper->getConfig('form'));
954
    }
955
956
    /**
957
     * Get all fields that are not rendered.
958
     *
959
     * @return array
960
     */
961 2
    protected function getUnrenderedFields()
962
    {
963 2
        $unrenderedFields = [];
964
965 2
        foreach ($this->fields as $field) {
966 2
            if (!$field->isRendered()) {
967 2
                $unrenderedFields[] = $field;
968 2
                continue;
969
            }
970
        }
971
972 2
        return $unrenderedFields;
973
    }
974
975
    /**
976
     * Prevent adding fields with same name.
977
     *
978
     * @param string $name
979
     * @throws \InvalidArgumentException
980
     * @return void
981
     */
982 62
    protected function preventDuplicate($name)
983
    {
984 62
        if ($this->has($name)) {
985 1
            throw new \InvalidArgumentException('Field ['.$name.'] already exists in the form '.get_class($this));
986
        }
987 62
    }
988
989
    /**
990
     * Returns and checks the type of the field.
991
     *
992
     * @param string $type
993
     * @return string
994
     */
995 66
    protected function getFieldType($type)
996
    {
997 66
        $fieldType = $this->formHelper->getFieldType($type);
998
999 65
        return $fieldType;
1000
    }
1001
1002
    /**
1003
     * Check if form is named form.
1004
     *
1005
     * @return void
1006
     */
1007 130
    protected function checkIfNamedForm()
1008
    {
1009 130
        if ($this->getFormOption('name')) {
1010 8
            $this->name = array_pull($this->formOptions, 'name', $this->name);
1011
        }
1012 130
    }
1013
1014
    /**
1015
     * Set up options on single field depending on form options.
1016
     *
1017
     * @param string $name
1018
     * @param $options
1019
     */
1020 66
    protected function setupFieldOptions($name, &$options)
1021
    {
1022 66
        $options['real_name'] = $name;
1023 66
    }
1024
1025
    /**
1026
     * Set namespace to model if form is named so the data is bound properly.
1027
     * Returns true if model is changed, otherwise false.
1028
     *
1029
     * @return bool
1030
     */
1031 9
    protected function setupNamedModel()
1032
    {
1033 9
        if (!$this->getModel() || !$this->getName()) {
1034 8
            return false;
1035
        }
1036
1037 1
        $dotName = $this->formHelper->transformToDotSyntax($this->getName());
1038 1
        $model = $this->formHelper->convertModelToArray($this->getModel());
1039
1040 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 1038 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...
1041 1
            $newModel = [];
1042 1
            array_set($newModel, $dotName, $model);
1043 1
            $this->model = $newModel;
1044
1045 1
            return true;
1046
        }
1047
1048
        return false;
1049
    }
1050
1051
    /**
1052
     * Set form builder instance on helper so we can use it later.
1053
     *
1054
     * @param FormBuilder $formBuilder
1055
     * @return $this
1056
     */
1057 130
    public function setFormBuilder(FormBuilder $formBuilder)
1058
    {
1059 130
        $this->formBuilder = $formBuilder;
1060
1061 130
        return $this;
1062
    }
1063
1064
    /**
1065
     * Returns the instance of the FormBuilder.
1066
     *
1067
     * @return FormBuilder
1068
     */
1069 12
    public function getFormBuilder()
1070
    {
1071 12
        return $this->formBuilder;
1072
    }
1073
1074
    /**
1075
     * Set the Validator instance on this so we can use it later.
1076
     *
1077
     * @param ValidatorFactory $validator
1078
     * @return $this
1079
     */
1080 130
    public function setValidator(ValidatorFactory $validator)
1081
    {
1082 130
        $this->validatorFactory = $validator;
1083
1084 130
        return $this;
1085
    }
1086
1087
    /**
1088
     * Returns the validator instance.
1089
     *
1090
     * @return Validator
1091
     */
1092 1
    public function getValidator()
1093
    {
1094 1
        return $this->validator;
1095
    }
1096
1097
    /**
1098
     * Exclude some fields from rendering.
1099
     *
1100
     * @return $this
1101
     */
1102
    public function exclude(array $fields)
1103
    {
1104
        $this->exclude = array_merge($this->exclude, $fields);
1105
1106
        return $this;
1107
    }
1108
1109
    /**
1110
     * If form is named form, modify names to be contained in single key (parent[child_field_name]).
1111
     *
1112
     * @param string $name
1113
     * @return string
1114
     */
1115 66
    protected function getFieldName($name)
1116
    {
1117 66
        $formName = $this->getName();
1118 66
        if ($formName !== null) {
1119 14
            if (strpos($formName, '[') !== false || strpos($formName, ']') !== false) {
1120 6
                return $this->formHelper->transformToBracketSyntax(
1121 6
                    $this->formHelper->transformToDotSyntax(
1122 6
                        $formName . '[' . $name . ']'
1123
                    )
1124
                );
1125
            }
1126
1127 11
            return $formName . '[' . $name . ']';
1128
        }
1129
1130 66
        return $name;
1131
    }
1132
1133
    /**
1134
     * Disable all fields in a form.
1135
     */
1136 1
    public function disableFields()
1137
    {
1138 1
        foreach ($this->fields as $field) {
1139 1
            $field->disable();
1140
        }
1141 1
    }
1142
1143
    /**
1144
     * Enable all fields in a form.
1145
     */
1146 1
    public function enableFields()
1147
    {
1148 1
        foreach ($this->fields as $field) {
1149 1
            $field->enable();
1150
        }
1151 1
    }
1152
1153
    /**
1154
     * Validate the form.
1155
     *
1156
     * @param array $validationRules
1157
     * @param array $messages
1158
     * @return Validator
1159
     */
1160 9
    public function validate($validationRules = [], $messages = [])
1161
    {
1162 9
        $fieldRules = $this->formHelper->mergeFieldsRules($this->fields);
1163 9
        $rules = array_merge($fieldRules['rules'], $validationRules);
1164 9
        $messages = array_merge($fieldRules['error_messages'], $messages);
1165
1166 9
        $this->validator = $this->validatorFactory->make($this->getRequest()->all(), $rules, $messages);
1167 9
        $this->validator->setAttributeNames($fieldRules['attributes']);
1168
1169 9
        $this->eventDispatcher->fire(new BeforeFormValidation($this, $this->validator));
1170
1171 9
        return $this->validator;
1172
    }
1173
1174
    /**
1175
     * Get validation rules for the form.
1176
     *
1177
     * @param array $overrideRules
1178
     * @return array
1179
     */
1180 1
    public function getRules($overrideRules = [])
1181
    {
1182 1
        $fieldRules = $this->formHelper->mergeFieldsRules($this->fields);
1183
1184 1
        return array_merge($fieldRules['rules'], $overrideRules);
1185
    }
1186
1187
    /**
1188
     * Redirects to a destination when form is invalid.
1189
     *
1190
     * @param  string|null $destination The target url.
1191
     * @return HttpResponseException
1192
     */
1193 3
    public function redirectIfNotValid($destination = null)
1194
    {
1195 3
        if (! $this->isValid()) {
1196 3
            $response = redirect($destination);
1197
1198 3
            if (is_null($destination)) {
1199 2
                $response = $response->back();
1200
            }
1201
1202 3
            $response = $response->withErrors($this->getErrors())->withInput();
1203
1204 3
            throw new HttpResponseException($response);
1205
        }
1206
    }
1207
1208
    /**
1209
     * Get all form field attributes, including child forms, in a flat array.
1210
     *
1211
     * @return array
1212
     */
1213 3
    public function getAllAttributes()
1214
    {
1215 3
        return $this->formHelper->mergeAttributes($this->fields);
1216
    }
1217
1218
    /**
1219
     * Check if the form is valid.
1220
     *
1221
     * @return bool
1222
     */
1223 9
    public function isValid()
1224
    {
1225 9
        if (!$this->validator) {
1226 8
            $this->validate();
1227
        }
1228
1229 9
        $isValid = !$this->validator->fails();
1230
1231 9
        $this->formHelper->alterValid($this, $this, $isValid);
1232
1233 9
        $this->eventDispatcher->fire(new AfterFormValidation($this, $this->validator, $isValid));
1234
1235 9
        return $isValid;
1236
    }
1237
1238
    /**
1239
     * Optionally change the validation result, and/or add error messages.
1240
     *
1241
     * @param Form $mainForm
1242
     * @param bool $isValid
1243
     * @return void|array
1244
     */
1245 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...
1246
    {
1247
        // return ['name' => ['Some other error about the Name field.']];
1248 9
    }
1249
1250
    /**
1251
     * Get validation errors.
1252
     *
1253
     * @return array
1254
     */
1255 8
    public function getErrors()
1256
    {
1257 8
        if (!$this->validator || !$this->validator instanceof Validator) {
1258 1
            throw new \InvalidArgumentException(
1259 1
                sprintf(
1260 1
                    'Form %s was not validated. To validate it, call "isValid" method before retrieving the errors',
1261 1
                    get_class($this)
1262
                )
1263
            );
1264
        }
1265
1266 7
        return $this->validator->getMessageBag()->getMessages();
1267
    }
1268
1269
    /**
1270
     * Get all Request values from all fields, and nothing else.
1271
     *
1272
     * @param bool $with_nulls
1273
     * @return array
1274
     */
1275 3
    public function getFieldValues($with_nulls = true)
1276
    {
1277 3
        $request_values = $this->getRequest()->all();
1278
1279 3
        $values = [];
1280 3
        foreach ($this->getAllAttributes() as $attribute) {
1281 3
            $value = Arr::get($request_values, $attribute);
1282 3
            if ($with_nulls || $value !== null) {
1283 3
                Arr::set($values, $attribute, $value);
1284
            }
1285
        }
1286
1287
        // If this form is a child form, cherry pick a part
1288 3
        if ($prefix = $this->getName()) {
1289 1
            $prefix = $this->formHelper->transformToDotSyntax($prefix);
1290 1
            $values = Arr::get($values, $prefix);
1291
        }
1292
1293
        // Allow form-specific value alters
1294 3
        $this->formHelper->alterFieldValues($this, $values);
1295
1296 3
        return $values;
1297
    }
1298
1299
    /**
1300
     * Optionally mess with this form's $values before it's returned from getFieldValues().
1301
     *
1302
     * @param array $values
1303
     * @return void
1304
     */
1305 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...
1306
    {
1307 3
    }
1308
1309
    /**
1310
     * Throw an exception indicating a field does not exist on the class.
1311
     *
1312
     * @param string $name
1313
     * @throws \InvalidArgumentException
1314
     * @return void
1315
     */
1316 2
    protected function fieldDoesNotExist($name)
1317
    {
1318 2
        throw new \InvalidArgumentException('Field ['.$name.'] does not exist in '.get_class($this));
1319
    }
1320
1321
    /**
1322
     * Method filterFields used as *Main* method for starting
1323
     * filtering and request field mutating process.
1324
     *
1325
     * @return \Kris\LaravelFormBuilder\Form
1326
     */
1327 130
    public function filterFields()
1328
    {
1329
        // If filtering is unlocked/allowed we can start with filtering process.
1330 130
        if (!$this->isFilteringLocked()) {
1331
            // Init required vars.
1332 130
            $filters = $this->getFilters();
1333 130
            $request = $this->getRequest();
1334
1335 130
            if (!empty($filters)) {
1336 17
                foreach ($filters as $field => $fieldFilters) {
1337
                    // If field exist in request object, try to mutate/filter
1338
                    // it to filtered value if there is one.
1339 17
                    if (array_key_exists($field, $request->all())) {
1340
                        // Assign current Raw/Unmutated value from request.
1341 1
                        $this->fields[$field]->setRawValue($request[$field]);
1342 1
                        foreach ($fieldFilters as $filter) {
1343 1
                            $filterObj = FilterResolver::instance($filter);
1344 17
                            $request[$field] = $filterObj->filter($request[$field]);
1345
                        }
1346
                    }
1347
                }
1348
            }
1349
        }
1350
1351 130
        return $this;
1352
    }
1353
1354
    /**
1355
     * Method getFilters used to return array of all binded filters to form fields.
1356
     *
1357
     * @return array
1358
     */
1359 130
    public function getFilters()
1360
    {
1361 130
        $filters = [];
1362 130
        foreach ($this->getFields() as $field) {
1363 18
            $filters[$field->getName()] = $field->getFilters();
1364
        }
1365
1366 130
        return $filters;
1367
    }
1368
1369
    /**
1370
     * If lockFiltering is set to true then we will not
1371
     * filter fields and mutate request data binded to fields.
1372
     *
1373
     * @return \Kris\LaravelFormBuilder\Form
1374
     */
1375 1
    public function lockFiltering()
1376
    {
1377 1
        $this->lockFiltering = true;
1378 1
        return $this;
1379
    }
1380
1381
    /**
1382
     * Unlock fields filtering/mutating.
1383
     *
1384
     * @return \Kris\LaravelFormBuilder\Form
1385
     */
1386
    public function unlockFiltering()
1387
    {
1388
        $this->lockFiltering = false;
1389
        return $this;
1390
    }
1391
1392
    /**
1393
     * Method isFilteringLocked used to check
1394
     * if current filteringLocked property status is set to true.
1395
     *
1396
     * @return bool
1397
     */
1398 130
    public function isFilteringLocked()
1399
    {
1400 130
        return !$this->lockFiltering ? false : true;
1401
    }
1402
1403
    /**
1404
     * Method getRawValues returns Unfiltered/Unmutated fields -> values.
1405
     *
1406
     * @return array
1407
     */
1408
    public function getRawValues()
1409
    {
1410
        $rawValues = [];
1411
        foreach ($this->getFields() as $field) {
1412
            $rawValues[$field->getName()] = $field->getRawValue();
1413
        }
1414
1415
        return $rawValues;
1416
    }
1417
}
1418