Completed
Pull Request — master (#266)
by Rudie
05:32
created

Form::render()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 1

Importance

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