Completed
Push — master ( 4d4acb...f95c98 )
by Kristijan
12s
created

Form::makeField()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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