Completed
Pull Request — master (#525)
by
unknown
05:10 queued 14s
created

Form::getUrl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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