Completed
Push — master ( e13153...047960 )
by Kristijan
11s
created

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