Completed
Pull Request — master (#376)
by
unknown
03:46
created

Form::getTemplate()   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
    /**
21
     * All fields that are added.
22
     *
23
     * @var array
24
     */
25
    protected $fields = [];
26
27
    /**
28
     * Model to use.
29
     *
30
     * @var mixed
31
     */
32
    protected $model = [];
33
34
    /**
35
     * @var EventDispatcher
36
     */
37
    protected $eventDispatcher;
38
39
    /**
40
     * @var FormHelper
41
     */
42
    protected $formHelper;
43
44
    /**
45
     * Form options.
46
     *
47
     * @var array
48
     */
49
    protected $formOptions = [
50
        'method' => 'GET',
51
        'url' => null
52
    ];
53
54
    /**
55
     * Additional data which can be used to build fields.
56
     *
57
     * @var array
58
     */
59
    protected $data = [];
60
61
    /**
62
     * Wether errors for each field should be shown when calling form($form) or form_rest($form).
63
     *
64
     * @var bool
65
     */
66
    protected $showFieldErrors = true;
67
68
    /**
69
     * Enable html5 validation.
70
     *
71
     * @var bool
72
     */
73
    protected $clientValidationEnabled = true;
74
75
    /**
76
     * Name of the parent form if any.
77
     *
78
     * @var string|null
79
     */
80
    protected $name = null;
81
82
    /**
83
     * @var FormBuilder
84
     */
85
    protected $formBuilder;
86
87
    /**
88
     * @var ValidatorFactory
89
     */
90
    protected $validatorFactory;
91
92
    /**
93
     * @var Validator
94
     */
95
    protected $validator = null;
96
97
    /**
98
     * @var Request
99
     */
100
    protected $request;
101
102
    /**
103
     * List of fields to not render.
104
     *
105
     * @var array
106
     **/
107
    protected $exclude = [];
108
109
    /**
110
     * Wether the form is beign rebuild.
111
     *
112
     * @var bool
113
     */
114
    protected $rebuilding = false;
115
116
    /**
117
     * @var string
118
     */
119
    protected $templatePrefix;
120
121
    /**
122
     * @var string
123
     */
124
    protected $languageName;
125
126
    /**
127
     * To filter and mutate request values or not.
128
     *
129
     * @var bool
130
     */
131
    protected $lockFiltering = false;
132
133
    /**
134
     * Build the form.
135
     *
136
     * @return mixed
137
     */
138 3
    public function buildForm()
139
    {
140 3
    }
141
142
    /**
143
     * Rebuild the form from scratch.
144
     *
145
     * @return $this
146
     */
147 17
    public function rebuildForm()
148
    {
149 17
        $this->rebuilding = true;
150
        // If form is plain, buildForm method is empty, so we need to take
151
        // existing fields and add them again
152 17
        if (get_class($this) === 'Kris\LaravelFormBuilder\Form') {
153 16
            foreach ($this->fields as $name => $field) {
154
                // Remove any temp variables added in previous instance
155 7
                $options = array_except($field->getOptions(), 'tmp');
156 16
                $this->add($name, $field->getType(), $options);
157
            }
158
        } else {
159 3
            $this->buildForm();
160
        }
161 17
        $this->rebuilding = false;
162
163 17
        return $this;
164
    }
165
166
    /**
167
     * Create the FormField object.
168
     *
169
     * @param string $name
170
     * @param string $type
171
     * @param array  $options
172
     * @return FormField
173
     */
174 62
    protected function makeField($name, $type = 'text', array $options = [])
175
    {
176 62
        $this->setupFieldOptions($name, $options);
177
178 62
        $fieldName = $this->getFieldName($name);
179
180 62
        $fieldType = $this->getFieldType($type);
181
182 61
        $field = new $fieldType($fieldName, $type, $this, $options);
183
184 58
        $this->eventDispatcher->fire(new AfterFieldCreation($this, $field));
185
186 58
        return $field;
187
    }
188
189
    /**
190
     * Create a new field and add it to the form.
191
     *
192
     * @param string $name
193
     * @param string $type
194
     * @param array  $options
195
     * @param bool   $modify
196
     * @return $this
197
     */
198 64
    public function add($name, $type = 'text', array $options = [], $modify = false)
199
    {
200 64
        $this->formHelper->checkFieldName($name, get_class($this));
201
202 62
        if ($this->rebuilding && !$this->has($name)) {
203
            return $this;
204
        }
205
206 62
        $this->addField($this->makeField($name, $type, $options), $modify);
207
208 58
        return $this;
209
    }
210
211
    /**
212
     * Add a FormField to the form's fields.
213
     *
214
     * @param FormField $field
215
     * @return $this
216
     */
217 58
    protected function addField(FormField $field, $modify = false)
218
    {
219 58
        if (!$modify && !$this->rebuilding) {
220 58
            $this->preventDuplicate($field->getRealName());
221
        }
222
223
224 58
        if ($field->getType() == 'file') {
225 3
            $this->formOptions['files'] = true;
226
        }
227
228 58
        $this->fields[$field->getRealName()] = $field;
229
230 58
        return $this;
231
    }
232
233
    /**
234
     * Add field before another field.
235
     *
236
     * @param string  $name         Name of the field before which new field is added.
237
     * @param string  $fieldName    Field name which will be added.
238
     * @param string  $type
239
     * @param array   $options
240
     * @param bool $modify
241
     * @return $this
242
     */
243 1
    public function addBefore($name, $fieldName, $type = 'text', $options = [], $modify = false)
244
    {
245 1
        $offset = array_search($name, array_keys($this->fields));
246
247 1
        $beforeFields = array_slice($this->fields, 0, $offset);
248 1
        $afterFields = array_slice($this->fields, $offset);
249
250 1
        $this->fields = $beforeFields;
251
252 1
        $this->add($fieldName, $type, $options, $modify);
253
254 1
        $this->fields += $afterFields;
255
256 1
        return $this;
257
    }
258
259
    /**
260
     * Add field before another field.
261
     *
262
     * @param string  $name         Name of the field after which new field is added.
263
     * @param string  $fieldName    Field name which will be added.
264
     * @param string  $type
265
     * @param array   $options
266
     * @param bool $modify
267
     * @return $this
268
     */
269 1
    public function addAfter($name, $fieldName, $type = 'text', $options = [], $modify = false)
270
    {
271 1
        $offset = array_search($name, array_keys($this->fields));
272
273 1
        $beforeFields = array_slice($this->fields, 0, $offset + 1);
274 1
        $afterFields = array_slice($this->fields, $offset + 1);
275
276 1
        $this->fields = $beforeFields;
277
278 1
        $this->add($fieldName, $type, $options, $modify);
279
280 1
        $this->fields += $afterFields;
281
282 1
        return $this;
283
    }
284
285
    /**
286
     * Take another form and add it's fields directly to this form.
287
     *
288
     * @param mixed   $class        Form to merge.
289
     * @param array   $options
290
     * @param boolean $modify
291
     * @return $this
292
     */
293 1
    public function compose($class, array $options = [], $modify = false)
294
    {
295 1
        $options['class'] = $class;
296
297
        // If we pass a ready made form just extract the fields.
298 1
        if ($class instanceof Form) {
299 1
            $fields = $class->getFields();
300
        } elseif ($class instanceof Fields\ChildFormType) {
301
            $fields = $class->getForm()->getFields();
302
        } elseif (is_string($class)) {
303
            // If its a string of a class make it the usual way.
304
            $options['model'] = $this->model;
305
            $options['name'] = $this->name;
306
307
            $form = $this->formBuilder->create($class, $options);
308
            $fields = $form->getFields();
309
        } else {
310
            throw new \InvalidArgumentException(
311
                "[{$class}] is invalid. Please provide either a full class name, Form or ChildFormType"
312
            );
313
        }
314
315 1
        foreach ($fields as $field) {
316 1
            $this->addField($field, $modify);
317
        }
318
319 1
        return $this;
320
    }
321
322
    /**
323
     * Remove field with specified name from the form.
324
     *
325
     * @param $name
326
     * @return $this
327
     */
328 2
    public function remove($name)
329
    {
330 2
        if ($this->has($name)) {
331 2
            unset($this->fields[$name]);
332
        }
333
334 2
        return $this;
335
    }
336
337
    /**
338
     * Modify existing field. If it doesn't exist, it is added to form.
339
     *
340
     * @param string $name
341
     * @param string $type
342
     * @param array  $options
343
     * @param bool   $overwriteOptions
344
     * @return Form
345
     */
346 1
    public function modify($name, $type = 'text', array $options = [], $overwriteOptions = false)
347
    {
348
        // If we don't want to overwrite options, we merge them with old options.
349 1
        if ($overwriteOptions === false && $this->has($name)) {
350 1
            $options = $this->formHelper->mergeOptions(
351 1
                $this->getField($name)->getOptions(),
352 1
                $options
353
            );
354
        }
355
356 1
        return $this->add($name, $type, $options, true);
357
    }
358
359
    /**
360
     * Render full form.
361
     *
362
     * @param array $options
363
     * @param bool  $showStart
364
     * @param bool  $showFields
365
     * @param bool  $showEnd
366
     * @return string
367
     */
368 7
    public function renderForm(array $options = [], $showStart = true, $showFields = true, $showEnd = true)
369
    {
370 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...
371
    }
372
373
    /**
374
     * Render rest of the form.
375
     *
376
     * @param bool $showFormEnd
377
     * @param bool $showFields
378
     * @return string
379
     */
380 1
    public function renderRest($showFormEnd = true, $showFields = true)
381
    {
382 1
        $fields = $this->getUnrenderedFields();
383
384 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...
385
    }
386
387
    /**
388
     * Renders the rest of the form up until the specified field name.
389
     *
390
     * @param string $field_name
391
     * @param bool   $showFormEnd
392
     * @param bool   $showFields
393
     * @return string
394
     */
395 2
    public function renderUntil($field_name, $showFormEnd = true, $showFields = true)
396
    {
397 2
        if (!$this->has($field_name)) {
398 1
            $this->fieldDoesNotExist($field_name);
399
        }
400
401 1
        $fields = $this->getUnrenderedFields();
402
403 1
        $i = 1;
404 1
        foreach ($fields as $key => $value) {
405 1
            if ($value->getRealName() == $field_name) {
406 1
                break;
407
            }
408 1
            $i++;
409
        }
410
411 1
        $fields = array_slice($fields, 0, $i, true);
412
413 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...
414
    }
415
416
    /**
417
     * Get single field instance from form object.
418
     *
419
     * @param string $name
420
     * @return FormField
421
     */
422 33
    public function getField($name)
423
    {
424 33
        if ($this->has($name)) {
425 32
            return $this->fields[$name];
426
        }
427
428 1
        $this->fieldDoesNotExist($name);
429
    }
430
431
    /**
432
     * Check if form has field.
433
     *
434
     * @param string $name
435
     * @return bool
436
     */
437 58
    public function has($name)
438
    {
439 58
        return array_key_exists($name, $this->fields);
440
    }
441
442
    /**
443
     * Get all form options.
444
     *
445
     * @return array
446
     */
447 2
    public function getFormOptions()
448
    {
449 2
        return $this->formOptions;
450
    }
451
452
    /**
453
     * Get single form option.
454
     *
455
     * @param string $option
456
     * @param mixed|null $default
457
     * @return mixed
458
     */
459 124
    public function getFormOption($option, $default = null)
460
    {
461 124
        return array_get($this->formOptions, $option, $default);
462
    }
463
464
    /**
465
     * Set single form option on form.
466
     *
467
     * @param string $option
468
     * @param mixed $value
469
     *
470
     * @return $this
471
     */
472 2
    public function setFormOption($option, $value)
473
    {
474 2
        $this->formOptions[$option] = $value;
475
476 2
        return $this;
477
    }
478
479
    /**
480
     * Set form options.
481
     *
482
     * @param array $formOptions
483
     * @return $this
484
     */
485 124
    public function setFormOptions(array $formOptions)
486
    {
487 124
        $this->formOptions = $this->formHelper->mergeOptions($this->formOptions, $formOptions);
488 124
        $this->checkIfNamedForm();
489 124
        $this->pullFromOptions('data', 'addData');
490 124
        $this->pullFromOptions('model', 'setupModel');
491 124
        $this->pullFromOptions('errors_enabled', 'setErrorsEnabled');
492 124
        $this->pullFromOptions('client_validation', 'setClientValidationEnabled');
493 124
        $this->pullFromOptions('template_prefix', 'setTemplatePrefix');
494 124
        $this->pullFromOptions('language_name', 'setLanguageName');
495
496 124
        return $this;
497
    }
498
499
    /**
500
     * Get an option from provided options and call method with that value.
501
     *
502
     * @param string $name
503
     * @param string $method
504
     */
505 124
    protected function pullFromOptions($name, $method)
506
    {
507 124
        if (array_get($this->formOptions, $name) !== null) {
508 18
            $this->{$method}(array_pull($this->formOptions, $name));
509
        }
510 124
    }
511
512
    /**
513
     * Get form http method.
514
     *
515
     * @return string
516
     */
517 3
    public function getMethod()
518
    {
519 3
        return $this->formOptions['method'];
520
    }
521
522
    /**
523
     * Set form http method.
524
     *
525
     * @param string $method
526
     * @return $this
527
     */
528 1
    public function setMethod($method)
529
    {
530 1
        $this->formOptions['method'] = $method;
531
532 1
        return $this;
533
    }
534
535
    /**
536
     * Get form action url.
537
     *
538
     * @return string
539
     */
540 3
    public function getUrl()
541
    {
542 3
        return $this->formOptions['url'];
543
    }
544
545
    /**
546
     * Set form action url.
547
     *
548
     * @param string $url
549
     * @return $this
550
     */
551 1
    public function setUrl($url)
552
    {
553 1
        $this->formOptions['url'] = $url;
554
555 1
        return $this;
556
    }
557
558
    /**
559
     * Returns the name of the form.
560
     *
561
     * @return string|null
562
     */
563 63
    public function getName()
564
    {
565 63
        return $this->name;
566
    }
567
568
    /**
569
     * Set the name of the form.
570
     *
571
     * @param string $name
572
     * @param bool $rebuild
573
     * @return $this
574
     */
575 10
    public function setName($name, $rebuild = true)
576
    {
577 10
        $this->name = $name;
578
579 10
        if ($rebuild) {
580 10
            $this->rebuildForm();
581
        }
582
583 10
        return $this;
584
    }
585
586
    /**
587
     * Get model that is bind to form object.
588
     *
589
     * @return mixed
590
     */
591 92
    public function getModel()
592
    {
593 92
        return $this->model;
594
    }
595
596
    /**
597
     * Set model to form object.
598
     *
599
     * @param mixed $model
600
     * @return $this
601
     * @deprecated deprecated since 1.6.31, will be removed in 1.7 - pass model as option when creating a form
602
     */
603 15
    public function setModel($model)
604
    {
605 15
        $this->model = $model;
606
607 15
        $this->rebuildForm();
608
609 15
        return $this;
610
    }
611
612
    /**
613
     * Setup model for form, add namespace if needed for child forms.
614
     *
615
     * @return $this
616
     */
617 12
    protected function setupModel($model)
618
    {
619 12
        $this->model = $model;
620
621 12
        return $this;
622
    }
623
624
    /**
625
     * Get all fields.
626
     *
627
     * @return FormField[]
628
     */
629 124
    public function getFields()
630
    {
631 124
        return $this->fields;
632
    }
633
634
    /**
635
     * Get field dynamically.
636
     *
637
     * @param string $name
638
     * @return FormField
639
     */
640 19
    public function __get($name)
641
    {
642 19
        if ($this->has($name)) {
643 18
            return $this->getField($name);
644
        }
645 3
    }
646
647
    /**
648
     * Check if field exists when fetched using magic methods.
649
     *
650
     * @param string $name
651
     * @return bool
652
     */
653
    public function __isset($name)
654
    {
655
        return $this->has($name);
656
    }
657
658
    /**
659
     * Set the Event Dispatcher to fire Laravel events.
660
     *
661
     * @param EventDispatcher $eventDispatcher
662
     * @return $this
663
     */
664 124
    public function setEventDispatcher(EventDispatcher $eventDispatcher)
665
    {
666 124
        $this->eventDispatcher = $eventDispatcher;
667
668 124
        return $this;
669
    }
670
671
    /**
672
     * Set the form helper only on first instantiation.
673
     *
674
     * @param FormHelper $formHelper
675
     * @return $this
676
     */
677 124
    public function setFormHelper(FormHelper $formHelper)
678
    {
679 124
        $this->formHelper = $formHelper;
680
681 124
        return $this;
682
    }
683
684
    /**
685
     * Get form helper.
686
     *
687
     * @return FormHelper
688
     */
689 96
    public function getFormHelper()
690
    {
691 96
        return $this->formHelper;
692
    }
693
694
    /**
695
     * Add custom field.
696
     *
697
     * @param $name
698
     * @param $class
699
     */
700 2
    public function addCustomField($name, $class)
701
    {
702 2
        if ($this->rebuilding && $this->formHelper->hasCustomField($name)) {
703
            return $this;
704
        }
705
706 2
        $this->formHelper->addCustomField($name, $class);
707 2
    }
708
709
    /**
710
     * Returns wether form errors should be shown under every field.
711
     *
712
     * @return bool
713
     */
714 96
    public function haveErrorsEnabled()
715
    {
716 96
        return $this->showFieldErrors;
717
    }
718
719
    /**
720
     * Enable or disable showing errors under fields
721
     *
722
     * @param bool $enabled
723
     * @return $this
724
     */
725 1
    public function setErrorsEnabled($enabled)
726
    {
727 1
        $this->showFieldErrors = (bool) $enabled;
728
729 1
        return $this;
730
    }
731
732
    /**
733
     * Is client validation enabled?
734
     *
735
     * @return bool
736
     */
737 21
    public function clientValidationEnabled()
738
    {
739 21
        return $this->clientValidationEnabled;
740
    }
741
742
    /**
743
     * Enable/disable client validation.
744
     *
745
     * @param bool $enable
746
     * @return $this
747
     */
748 2
    public function setClientValidationEnabled($enable)
749
    {
750 2
        $this->clientValidationEnabled = (bool) $enable;
751
752 2
        return $this;
753
    }
754
755
    /**
756
     * Add any aditional data that field needs (ex. array of choices).
757
     *
758
     * @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
759
     * will be switched to protected in 1.7.
760
     * @param string $name
761
     * @param mixed $data
762
     */
763 1
    public function setData($name, $data)
764
    {
765 1
        $this->data[$name] = $data;
766 1
    }
767
768
    /**
769
     * Get single additional data.
770
     *
771
     * @param string $name
772
     * @param null   $default
773
     * @return mixed
774
     */
775 18
    public function getData($name = null, $default = null)
776
    {
777 18
        if (is_null($name)) {
778 17
            return $this->data;
779
        }
780
781 1
        return array_get($this->data, $name, $default);
782
    }
783
784
    /**
785
     * Add multiple peices of data at once.
786
     *
787
     * @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
788
     * will be switched to protected in 1.7.
789
     * @param $data
790
     * @return $this
791
     **/
792 124
    public function addData(array $data)
793
    {
794 124
        foreach ($data as $key => $value) {
795 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...
796
        }
797
798 124
        return $this;
799
    }
800
801
    /**
802
     * Get current request.
803
     *
804
     * @return \Illuminate\Http\Request
805
     */
806 124
    public function getRequest()
807
    {
808 124
        return $this->request;
809
    }
810
811
    /**
812
     * Set request on form.
813
     *
814
     * @param Request $request
815
     * @return $this
816
     */
817 124
    public function setRequest(Request $request)
818
    {
819 124
        $this->request = $request;
820
821 124
        return $this;
822
    }
823
824
    /**
825
     * Get template prefix that is prepended to all template paths.
826
     *
827
     * @return string
828
     */
829 37
    public function getTemplatePrefix()
830
    {
831 37
        if ($this->templatePrefix !== null) {
832 4
            return $this->templatePrefix;
833
        }
834
835 33
        return $this->formHelper->getConfig('template_prefix');
836
    }
837
838
    /**
839
     * Set a template prefix for the form and its fields.
840
     *
841
     * @param string $prefix
842
     * @return $this
843
     */
844 4
    public function setTemplatePrefix($prefix)
845
    {
846 4
        $this->templatePrefix = (string) $prefix;
847
848 4
        return $this;
849
    }
850
851
    /**
852
     * Get the language name.
853
     *
854
     * @return string
855
     */
856 94
    public function getLanguageName()
857
    {
858 94
        return $this->languageName;
859
    }
860
861
    /**
862
     * Set a language name, used as prefix for translated strings.
863
     *
864
     * @param string $prefix
865
     * @return $this
866
     */
867 11
    public function setLanguageName($prefix)
868
    {
869 11
        $this->languageName = (string) $prefix;
870
871 11
        return $this;
872
    }
873
874
    /**
875
     * Render the form.
876
     *
877
     * @param array $options
878
     * @param string $fields
879
     * @param bool $showStart
880
     * @param bool $showFields
881
     * @param bool $showEnd
882
     * @return string
883
     */
884 9
    protected function render($options, $fields, $showStart, $showFields, $showEnd)
885
    {
886 9
        $formOptions = $this->formHelper->mergeOptions($this->formOptions, $options);
887
888 9
        $this->setupNamedModel();
889
890 9
        return $this->formHelper->getView()
891 9
            ->make($this->getTemplate())
892 9
            ->with(compact('showStart', 'showFields', 'showEnd'))
893 9
            ->with('formOptions', $formOptions)
894 9
            ->with('fields', $fields)
895 9
            ->with('model', $this->getModel())
896 9
            ->with('exclude', $this->exclude)
897 9
            ->with('form', $this)
898 9
            ->render();
899
    }
900
901
    /**
902
     * Get template from options if provided, otherwise fallback to config.
903
     *
904
     * @return mixed
905
     */
906 9
    protected function getTemplate()
907
    {
908 9
        return $this->getTemplatePrefix() . $this->getFormOption('template', $this->formHelper->getConfig('form'));
909
    }
910
911
    /**
912
     * Get all fields that are not rendered.
913
     *
914
     * @return array
915
     */
916 2
    protected function getUnrenderedFields()
917
    {
918 2
        $unrenderedFields = [];
919
920 2
        foreach ($this->fields as $field) {
921 2
            if (!$field->isRendered()) {
922 2
                $unrenderedFields[] = $field;
923 2
                continue;
924
            }
925
        }
926
927 2
        return $unrenderedFields;
928
    }
929
930
    /**
931
     * Prevent adding fields with same name.
932
     *
933
     * @param string $name
934
     * @throws \InvalidArgumentException
935
     * @return void
936
     */
937 58
    protected function preventDuplicate($name)
938
    {
939 58
        if ($this->has($name)) {
940 1
            throw new \InvalidArgumentException('Field ['.$name.'] already exists in the form '.get_class($this));
941
        }
942 58
    }
943
944
    /**
945
     * Returns and checks the type of the field.
946
     *
947
     * @param string $type
948
     * @return string
949
     */
950 62
    protected function getFieldType($type)
951
    {
952 62
        $fieldType = $this->formHelper->getFieldType($type);
953
954 61
        return $fieldType;
955
    }
956
957
    /**
958
     * Check if form is named form.
959
     *
960
     * @return void
961
     */
962 124
    protected function checkIfNamedForm()
963
    {
964 124
        if ($this->getFormOption('name')) {
965 8
            $this->name = array_pull($this->formOptions, 'name', $this->name);
966
        }
967 124
    }
968
969
    /**
970
     * Set up options on single field depending on form options.
971
     *
972
     * @param string $name
973
     * @param $options
974
     */
975 62
    protected function setupFieldOptions($name, &$options)
976
    {
977 62
        $options['real_name'] = $name;
978 62
    }
979
980
    /**
981
     * Set namespace to model if form is named so the data is bound properly.
982
     * Returns true if model is changed, otherwise false.
983
     *
984
     * @return bool
985
     */
986 9
    protected function setupNamedModel()
987
    {
988 9
        if (!$this->getModel() || !$this->getName()) {
989 8
            return false;
990
        }
991
992 1
        $dotName = $this->formHelper->transformToDotSyntax($this->getName());
993 1
        $model = $this->formHelper->convertModelToArray($this->getModel());
994
995 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 993 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...
996 1
            $newModel = [];
997 1
            array_set($newModel, $dotName, $model);
998 1
            $this->model = $newModel;
999
1000 1
            return true;
1001
        }
1002
1003
        return false;
1004
    }
1005
1006
    /**
1007
     * Set form builder instance on helper so we can use it later.
1008
     *
1009
     * @param FormBuilder $formBuilder
1010
     * @return $this
1011
     */
1012 124
    public function setFormBuilder(FormBuilder $formBuilder)
1013
    {
1014 124
        $this->formBuilder = $formBuilder;
1015
1016 124
        return $this;
1017
    }
1018
1019
    /**
1020
     * Returns the instance of the FormBuilder.
1021
     *
1022
     * @return FormBuilder
1023
     */
1024 12
    public function getFormBuilder()
1025
    {
1026 12
        return $this->formBuilder;
1027
    }
1028
1029
    /**
1030
     * Set the Validator instance on this so we can use it later.
1031
     *
1032
     * @param ValidatorFactory $validator
1033
     * @return $this
1034
     */
1035 124
    public function setValidator(ValidatorFactory $validator)
1036
    {
1037 124
        $this->validatorFactory = $validator;
1038
1039 124
        return $this;
1040
    }
1041
1042
    /**
1043
     * Returns the validator instance.
1044
     *
1045
     * @return Validator
1046
     */
1047 1
    public function getValidator()
1048
    {
1049 1
        return $this->validator;
1050
    }
1051
1052
    /**
1053
     * Exclude some fields from rendering.
1054
     *
1055
     * @return $this
1056
     */
1057
    public function exclude(array $fields)
1058
    {
1059
        $this->exclude = array_merge($this->exclude, $fields);
1060
1061
        return $this;
1062
    }
1063
1064
    /**
1065
     * If form is named form, modify names to be contained in single key (parent[child_field_name]).
1066
     *
1067
     * @param string $name
1068
     * @return string
1069
     */
1070 62
    protected function getFieldName($name)
1071
    {
1072 62
        $formName = $this->getName();
1073 62
        if ($formName !== null) {
1074 14
            if (strpos($formName, '[') !== false || strpos($formName, ']') !== false) {
1075 6
                return $this->formHelper->transformToBracketSyntax(
1076 6
                    $this->formHelper->transformToDotSyntax(
1077 6
                        $formName . '[' . $name . ']'
1078
                    )
1079
                );
1080
            }
1081
1082 11
            return $formName . '[' . $name . ']';
1083
        }
1084
1085 62
        return $name;
1086
    }
1087
1088
    /**
1089
     * Disable all fields in a form.
1090
     */
1091 1
    public function disableFields()
1092
    {
1093 1
        foreach ($this->fields as $field) {
1094 1
            $field->disable();
1095
        }
1096 1
    }
1097
1098
    /**
1099
     * Enable all fields in a form.
1100
     */
1101 1
    public function enableFields()
1102
    {
1103 1
        foreach ($this->fields as $field) {
1104 1
            $field->enable();
1105
        }
1106 1
    }
1107
1108
    /**
1109
     * Validate the form.
1110
     *
1111
     * @param array $validationRules
1112
     * @param array $messages
1113
     * @return Validator
1114
     */
1115 9
    public function validate($validationRules = [], $messages = [])
1116
    {
1117 9
        $fieldRules = $this->formHelper->mergeFieldsRules($this->fields);
1118 9
        $rules = array_merge($fieldRules['rules'], $validationRules);
1119 9
        $messages = array_merge($fieldRules['error_messages'], $messages);
1120
1121 9
        $this->validator = $this->validatorFactory->make($this->getRequest()->all(), $rules, $messages);
1122 9
        $this->validator->setAttributeNames($fieldRules['attributes']);
1123
1124 9
        $this->eventDispatcher->fire(new BeforeFormValidation($this, $this->validator));
1125
1126 9
        return $this->validator;
1127
    }
1128
1129
    /**
1130
     * Get validation rules for the form.
1131
     *
1132
     * @param array $overrideRules
1133
     * @return array
1134
     */
1135 1
    public function getRules($overrideRules = [])
1136
    {
1137 1
        $fieldRules = $this->formHelper->mergeFieldsRules($this->fields);
1138
1139 1
        return array_merge($fieldRules['rules'], $overrideRules);
1140
    }
1141
1142
    /**
1143
     * Redirects to a destination when form is invalid.
1144
     *
1145
     * @param  string|null $destination The target url.
1146
     * @return HttpResponseException
1147
     */
1148 3
    public function redirectIfNotValid($destination = null)
1149
    {
1150 3
        if (! $this->isValid()) {
1151 3
            $response = redirect($destination);
1152
1153 3
            if (is_null($destination)) {
1154 2
                $response = $response->back();
1155
            }
1156
1157 3
            $response = $response->withErrors($this->getErrors())->withInput();
1158
1159 3
            throw new HttpResponseException($response);
1160
        }
1161
    }
1162
1163
    /**
1164
     * Get all form field attributes, including child forms, in a flat array.
1165
     *
1166
     * @return array
1167
     */
1168 3
    public function getAllAttributes()
1169
    {
1170 3
        return $this->formHelper->mergeAttributes($this->fields);
1171
    }
1172
1173
    /**
1174
     * Check if the form is valid.
1175
     *
1176
     * @return bool
1177
     */
1178 9
    public function isValid()
1179
    {
1180 9
        if (!$this->validator) {
1181 8
            $this->validate();
1182
        }
1183
1184 9
        $isValid = !$this->validator->fails();
1185
1186 9
        $this->formHelper->alterValid($this, $this, $isValid);
1187
1188 9
        $this->eventDispatcher->fire(new AfterFormValidation($this, $this->validator, $isValid));
1189
1190 9
        return $isValid;
1191
    }
1192
1193
    /**
1194
     * Optionally change the validation result, and/or add error messages.
1195
     *
1196
     * @param Form $mainForm
1197
     * @param bool $isValid
1198
     * @return void|array
1199
     */
1200 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...
1201
    {
1202
        // return ['name' => ['Some other error about the Name field.']];
1203 9
    }
1204
1205
    /**
1206
     * Get validation errors.
1207
     *
1208
     * @return array
1209
     */
1210 8
    public function getErrors()
1211
    {
1212 8
        if (!$this->validator || !$this->validator instanceof Validator) {
1213 1
            throw new \InvalidArgumentException(
1214 1
                sprintf(
1215 1
                    'Form %s was not validated. To validate it, call "isValid" method before retrieving the errors',
1216 1
                    get_class($this)
1217
                )
1218
            );
1219
        }
1220
1221 7
        return $this->validator->getMessageBag()->getMessages();
1222
    }
1223
1224
    /**
1225
     * Get all Request values from all fields, and nothing else.
1226
     *
1227
     * @param bool $with_nulls
1228
     * @return array
1229
     */
1230 3
    public function getFieldValues($with_nulls = true)
1231
    {
1232 3
        $request_values = $this->getRequest()->all();
1233
1234 3
        $values = [];
1235 3
        foreach ($this->getAllAttributes() as $attribute) {
1236 3
            $value = Arr::get($request_values, $attribute);
1237 3
            if ($with_nulls || $value !== null) {
1238 3
                Arr::set($values, $attribute, $value);
1239
            }
1240
        }
1241
1242
        // If this form is a child form, cherry pick a part
1243 3
        if ($prefix = $this->getName()) {
1244 1
            $prefix = $this->formHelper->transformToDotSyntax($prefix);
1245 1
            $values = Arr::get($values, $prefix);
1246
        }
1247
1248
        // Allow form-specific value alters
1249 3
        $this->formHelper->alterFieldValues($this, $values);
1250
1251 3
        return $values;
1252
    }
1253
1254
    /**
1255
     * Optionally mess with this form's $values before it's returned from getFieldValues().
1256
     *
1257
     * @param array $values
1258
     * @return void
1259
     */
1260 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...
1261
    {
1262 3
    }
1263
1264
    /**
1265
     * Throw an exception indicating a field does not exist on the class.
1266
     *
1267
     * @param string $name
1268
     * @throws \InvalidArgumentException
1269
     * @return void
1270
     */
1271 2
    protected function fieldDoesNotExist($name)
1272
    {
1273 2
        throw new \InvalidArgumentException('Field ['.$name.'] does not exist in '.get_class($this));
1274
    }
1275
1276
    /**
1277
     * Method filterFields used as *Main* method for starting
1278
     * filtering and request field mutating process.
1279
     *
1280
     * @return \Kris\LaravelFormBuilder\Form
1281
     */
1282 124
    public function filterFields()
1283
    {
1284
        // If filtering is unlocked/allowed we can start with filtering process.
1285 124
        if (!$this->isFilteringLocked()) {
1286
            // Init required vars.
1287 124
            $filters = $this->getFilters();
1288 124
            $request = $this->getRequest();
1289
1290 124
            if (!empty($filters)) {
1291 16
                foreach ($filters as $field => $fieldFilters) {
1292
                    // If field exist in request object, try to mutate/filter
1293
                    // it to filtered value if there is one.
1294 16
                    if (array_key_exists($field, $request->all())) {
1295 1
                        foreach ($fieldFilters as $filter) {
1296 1
                            $filterObj = FilterResolver::instance($filter);
1297 16
                            $request[$field] = $filterObj->filter($request[$field]);
1298
                        }
1299
                    }
1300
                }
1301
            }
1302
        }
1303
1304 124
        return $this;
1305
    }
1306
1307
    /**
1308
     * Method getFilters used to return array of all binded filters to form fields.
1309
     *
1310
     * @return array
1311
     */
1312 124
    public function getFilters()
1313
    {
1314 124
        $filters = [];
1315 124
        foreach ($this->getFields() as $field) {
1316 17
            $filters[$field->getName()] = $field->getFilters();
1317
        }
1318
1319 124
        return $filters;
1320
    }
1321
1322
    /**
1323
     * If lockFiltering is set to true then we will not
1324
     * filter fields and mutate request data binded to fields.
1325
     *
1326
     * @return \Kris\LaravelFormBuilder\Form
1327
     */
1328 1
    public function lockFiltering()
1329
    {
1330 1
        $this->lockFiltering = true;
1331 1
        return $this;
1332
    }
1333
1334
    /**
1335
     * Unlock fields filtering/mutating.
1336
     *
1337
     * @return \Kris\LaravelFormBuilder\Form
1338
     */
1339
    public function unlockFiltering()
1340
    {
1341
        $this->lockFiltering = false;
1342
        return $this;
1343
    }
1344
1345
    /**
1346
     * Method isFilteringLocked used to check
1347
     * if current filteringLocked property status is set to true.
1348
     *
1349
     * @return bool
1350
     */
1351 124
    public function isFilteringLocked()
1352
    {
1353 124
        return !$this->lockFiltering ? false : true;
1354
    }
1355
}
1356