Completed
Push — master ( 6bc88b...6ee090 )
by
unknown
05:08 queued 03:37
created

Form::redirectIfNotValid()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3.0175

Importance

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