Completed
Push — master ( f20011...9a6c8b )
by Kristijan
06:22
created

Form::getName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
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 7
                $this->add($name, $field->getType(), $options);
147 15
            }
148 15
        } 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 49
    protected function makeField($name, $type = 'text', array $options = [])
165
    {
166 49
        $this->setupFieldOptions($name, $options);
167
168 49
        $fieldName = $this->getFieldName($name);
169
170 49
        $fieldType = $this->getFieldType($type);
171
172 48
        $field = new $fieldType($fieldName, $type, $this, $options);
173
174 45
        $this->eventDispatcher->fire(new AfterFieldCreation($this, $field));
175
176 45
        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 51
    public function add($name, $type = 'text', array $options = [], $modify = false)
189
    {
190 51
        $this->formHelper->checkFieldName($name, get_class($this));
191
192 49
        if ($this->rebuilding && !$this->has($name)) {
193
            return $this;
194
        }
195
196 49
        $this->addField($this->makeField($name, $type, $options), $modify);
197
198 45
        return $this;
199
    }
200
201
    /**
202
     * Add a FormField to the form's fields
203
     *
204
     * @param FormField $field
205
     * @return $this
206
     */
207 45
    protected function addField(FormField $field, $modify = false)
208
    {
209 45
        if (!$modify && !$this->rebuilding) {
210 45
            $this->preventDuplicate($field->getRealName());
211 45
        }
212
213
214 45
        if ($field->getType() == 'file') {
215 3
            $this->formOptions['files'] = true;
216 3
        }
217
218 45
        $this->fields[$field->getRealName()] = $field;
219
220 45
        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 1
        } 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 1
        }
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 2
        }
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 1
            );
342 1
        }
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 7
    public function renderForm(array $options = [], $showStart = true, $showFields = true, $showEnd = true)
357
    {
358 7
        return $this->render($options, $this->fields, $showStart, $showFields, $showEnd);
359
    }
360
361
    /**
362
     * Render rest of the form
363
     *
364
     * @param bool $showFormEnd
365
     * @param bool $showFields
366
     * @return string
367
     */
368 1
    public function renderRest($showFormEnd = true, $showFields = true)
369
    {
370 1
        $fields = $this->getUnrenderedFields();
371
372 1
        return $this->render([], $fields, false, $showFields, $showFormEnd);
373
    }
374
375
    /**
376
     * Renders the rest of the form up until the specified field name
377
     *
378
     * @param string $field_name
379
     * @param bool   $showFormEnd
380
     * @param bool   $showFields
381
     * @return string
382
     */
383 2
    public function renderUntil($field_name, $showFormEnd = true, $showFields = true)
384
    {
385 2
        if (!$this->has($field_name)) {
386 1
            $this->fieldDoesNotExist($field_name);
387
        }
388
389 1
        $fields = $this->getUnrenderedFields();
390
391 1
        $i = 1;
392 1
        foreach ($fields as $key => $value) {
393 1
            if ($value->getRealName() == $field_name) {
394 1
                break;
395
            }
396 1
            $i++;
397 1
        }
398
399 1
        $fields = array_slice($fields, 0, $i, true);
400
401 1
        return $this->render([], $fields, false, $showFields, $showFormEnd);
402
    }
403
404
    /**
405
     * Get single field instance from form object
406
     *
407
     * @param $name
408
     * @return FormField
409
     */
410 25
    public function getField($name)
411
    {
412 25
        if ($this->has($name)) {
413 24
            return $this->fields[$name];
414
        }
415
416 1
        $this->fieldDoesNotExist($name);
417
    }
418
419
    /**
420
     * Check if form has field
421
     *
422
     * @param $name
423
     * @return bool
424
     */
425 45
    public function has($name)
426
    {
427 45
        return array_key_exists($name, $this->fields);
428
    }
429
430
    /**
431
     * Get all form options
432
     *
433
     * @return array
434
     */
435 2
    public function getFormOptions()
436
    {
437 2
        return $this->formOptions;
438
    }
439
440
    /**
441
     * Get single form option
442
     *
443
     * @param string $option
444
     * @param $default
445
     * @return mixed
446
     */
447 104
    public function getFormOption($option, $default = null)
448
    {
449 104
        return array_get($this->formOptions, $option, $default);
450
    }
451
452
    /**
453
     * Set single form option on form
454
     *
455
     * @param string $option
456
     * @param mixed $value
457
     *
458
     * @return $this
459
     */
460 2
    public function setFormOption($option, $value)
461
    {
462 2
        $this->formOptions[$option] = $value;
463
464 2
        return $this;
465
    }
466
467
    /**
468
     * Set form options
469
     *
470
     * @param array $formOptions
471
     * @return $this
472
     */
473 104
    public function setFormOptions($formOptions)
474
    {
475 104
        $this->formOptions = $this->formHelper->mergeOptions($this->formOptions, $formOptions);
476 104
        $this->checkIfNamedForm();
477 104
        $this->pullFromOptions('data', 'addData');
478 104
        $this->pullFromOptions('model', 'setupModel');
479 104
        $this->pullFromOptions('errors_enabled', 'setErrorsEnabled');
480 104
        $this->pullFromOptions('client_validation', 'setClientValidationEnabled');
481 104
        $this->pullFromOptions('template_prefix', 'setTemplatePrefix');
482 104
        $this->pullFromOptions('language_name', 'setLanguageName');
483
484 104
        return $this;
485
    }
486
487
    /**
488
     * Get an option from provided options and call method with that value
489
     *
490
     * @param $name
491
     * @param $method
492
     */
493 104
    protected function pullFromOptions($name, $method)
494
    {
495 104
        if (array_get($this->formOptions, $name) !== null) {
496 15
            $this->{$method}(array_pull($this->formOptions, $name));
497 15
        }
498 104
    }
499
500
    /**
501
     * Get form http method
502
     *
503
     * @return string
504
     */
505 3
    public function getMethod()
506
    {
507 3
        return $this->formOptions['method'];
508
    }
509
510
    /**
511
     * Set form http method
512
     *
513
     * @param string $method
514
     * @return $this
515
     */
516 1
    public function setMethod($method)
517
    {
518 1
        $this->formOptions['method'] = $method;
519
520 1
        return $this;
521
    }
522
523
    /**
524
     * Get form action url
525
     *
526
     * @return string
527
     */
528 3
    public function getUrl()
529
    {
530 3
        return $this->formOptions['url'];
531
    }
532
533
    /**
534
     * Set form action url
535
     *
536
     * @param string $url
537
     * @return $this
538
     */
539 1
    public function setUrl($url)
540
    {
541 1
        $this->formOptions['url'] = $url;
542
543 1
        return $this;
544
    }
545
546
    /**
547
     * @return string|null
548
     */
549 54
    public function getName()
550
    {
551 54
        return $this->name;
552
    }
553
554
    /**
555
     * @param string $name
556
     * @param bool $rebuild
557
     *
558
     * @return $this
559
     */
560 10
    public function setName($name, $rebuild = true)
561
    {
562 10
        $this->name = $name;
563
564 10
        if ($rebuild) {
565 10
            $this->rebuildForm();
566 10
        }
567
568 10
        return $this;
569
    }
570
571
    /**
572
     * Get model that is bind to form object
573
     *
574
     * @return mixed
575
     */
576 78
    public function getModel()
577
    {
578 78
        return $this->model;
579
    }
580
581
    /**
582
     * Set model to form object
583
     *
584
     * @param mixed $model
585
     * @return $this
586
     * @deprecated deprecated since 1.6.31, will be removed in 1.7 - pass model as option when creating a form
587
     */
588
    public function setModel($model)
589
    {
590
        $this->model = $model;
591
592
        $this->setupNamedModel();
593
594
        $this->rebuildForm();
595
596
        return $this;
597
    }
598
599
    /**
600
     * Setup model for form, add namespace if needed for child forms
601
     * @return $this
602
     */
603 9
    protected function setupModel($model)
604
    {
605 9
        $this->model = $model;
606
607 9
        $this->setupNamedModel();
608
609 9
        return $this;
610
    }
611
612
    /**
613
     * Get all fields
614
     *
615
     * @return FormField[]
616
     */
617 20
    public function getFields()
618
    {
619 20
        return $this->fields;
620
    }
621
622
    /**
623
     * Get field dynamically
624
     *
625
     * @param $name
626
     * @return FormField
627
     */
628 19
    public function __get($name)
629
    {
630 19
        if ($this->has($name)) {
631 18
            return $this->getField($name);
632
        }
633 3
    }
634
635
    /**
636
     * Set the Event Dispatcher to fire Laravel events
637
     *
638
     * @param EventDispatcher $eventDispatcher
639
     * @return $this
640
     */
641 104
    public function setEventDispatcher(EventDispatcher $eventDispatcher)
642
    {
643 104
        $this->eventDispatcher = $eventDispatcher;
644
645 104
        return $this;
646
    }
647
648
    /**
649
     * Set the form helper only on first instantiation
650
     *
651
     * @param FormHelper $formHelper
652
     * @return $this
653
     */
654 104
    public function setFormHelper(FormHelper $formHelper)
655
    {
656 104
        $this->formHelper = $formHelper;
657
658 104
        return $this;
659
    }
660
661
    /**
662
     * Get form helper
663
     *
664
     * @return FormHelper
665
     */
666 82
    public function getFormHelper()
667
    {
668 82
        return $this->formHelper;
669
    }
670
671
    /**
672
     * Add custom field
673
     *
674
     * @param $name
675
     * @param $class
676
     */
677 2
    public function addCustomField($name, $class)
678
    {
679 2
        $this->formHelper->addCustomField($name, $class);
680 2
    }
681
682
    /**
683
     * Should form errors be shown under every field ?
684
     *
685
     * @return bool
686
     */
687 82
    public function haveErrorsEnabled()
688
    {
689 82
        return $this->showFieldErrors;
690
    }
691
692
    /**
693
     * Enable or disable showing errors under fields
694
     *
695
     * @param boolean $enabled
696
     * @return $this
697
     */
698 1
    public function setErrorsEnabled($enabled)
699
    {
700 1
        $this->showFieldErrors = (boolean) $enabled;
701
702 1
        return $this;
703
    }
704
705
    /**
706
     * Is client validation enabled?
707
     *
708
     * @return boolean
709
     */
710 18
    public function clientValidationEnabled()
711
    {
712 18
        return $this->clientValidationEnabled;
713
    }
714
715
    /**
716
     * Enable/disable client validation
717
     *
718
     * @param boolean $enable
719
     * @return $this
720
     */
721 2
    public function setClientValidationEnabled($enable)
722
    {
723 2
        $this->clientValidationEnabled = (boolean) $enable;
724
725 2
        return $this;
726
    }
727
728
    /**
729
     * Add any aditional data that field needs (ex. array of choices)
730
     *
731
     * @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
732
     * will be switched to protected in 1.7
733
     * @param string $name
734
     * @param mixed $data
735
     */
736
    public function setData($name, $data)
737
    {
738
        $this->data[$name] = $data;
739
    }
740
741
    /**
742
     * Get single additional data
743
     *
744
     * @param string $name
745
     * @param null   $default
746
     * @return mixed
747
     */
748 15
    public function getData($name = null, $default = null)
749
    {
750 15
        if (is_null($name)) {
751 14
            return $this->data;
752
        }
753
754 1
        return array_get($this->data, $name, $default);
755
    }
756
757
    /**
758
     * Add multiple peices of data at once
759
     *
760
     * @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
761
     * will be switched to protected in 1.7
762
     * @param $data
763
     * @return $this
764
     **/
765
    public function addData(array $data)
766
    {
767
        foreach ($data as $key => $value) {
768
            $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...
769
        }
770
771
        return $this;
772
    }
773
774
    /**
775
     * Get current request
776
     *
777
     * @return \Illuminate\Http\Request
778
     */
779 82
    public function getRequest()
780
    {
781 82
        return $this->request;
782
    }
783
784
    /**
785
     * Set request on form
786
     *
787
     * @param Request $request
788
     * @return $this
789
     */
790 104
    public function setRequest(Request $request)
791
    {
792 104
        $this->request = $request;
793
794 104
        return $this;
795
    }
796
797
    /**
798
     * Get template prefix that is prepended to all template paths
799
     *
800
     * @return string
801
     */
802 36
    public function getTemplatePrefix()
803
    {
804 36
        if ($this->templatePrefix !== null) {
805 4
            return $this->templatePrefix;
806
        }
807
808 32
        return $this->formHelper->getConfig('template_prefix');
809
    }
810
811
    /**
812
     * Set a template prefix for the form and its fields
813
     *
814
     * @param string $prefix
815
     * @return $this
816
     */
817 4
    public function setTemplatePrefix($prefix)
818
    {
819 4
        $this->templatePrefix = (string) $prefix;
820
821 4
        return $this;
822
    }
823
824
    /**
825
     * Get the language name
826
     *
827
     * @return string
828
     */
829 80
    public function getLanguageName()
830
    {
831 80
        return $this->languageName;
832
    }
833
834
    /**
835
     * Set a language name, used as prefix for translated strings
836
     *
837
     * @param string $prefix
838
     * @return $this
839
     */
840 11
    public function setLanguageName($prefix)
841
    {
842 11
        $this->languageName = (string) $prefix;
843
844 11
        return $this;
845
    }
846
847
    /**
848
     * Render the form
849
     *
850
     * @param $options
851
     * @param $fields
852
     * @param boolean $showStart
853
     * @param boolean $showFields
854
     * @param boolean $showEnd
855
     * @return string
856
     */
857 9
    protected function render($options, $fields, $showStart, $showFields, $showEnd)
858
    {
859 9
        $formOptions = $this->formHelper->mergeOptions($this->formOptions, $options);
860
861 9
        $this->setupNamedModel();
862
863 9
        return $this->formHelper->getView()
864 9
            ->make($this->getTemplate())
865 9
            ->with(compact('showStart', 'showFields', 'showEnd'))
866 9
            ->with('formOptions', $formOptions)
867 9
            ->with('fields', $fields)
868 9
            ->with('model', $this->getModel())
869 9
            ->with('exclude', $this->exclude)
870 9
            ->with('form', $this)
871 9
            ->render();
872
    }
873
874
    /**
875
     * Get template from options if provided, otherwise fallback to config
876
     *
877
     * @return mixed
878
     */
879 9
    protected function getTemplate()
880
    {
881 9
        return $this->getTemplatePrefix() . $this->getFormOption('template', $this->formHelper->getConfig('form'));
882
    }
883
884
    /**
885
     * Get all fields that are not rendered
886
     *
887
     * @return array
888
     */
889 2
    protected function getUnrenderedFields()
890
    {
891 2
        $unrenderedFields = [];
892
893 2
        foreach ($this->fields as $field) {
894 2
            if (!$field->isRendered()) {
895 2
                $unrenderedFields[] = $field;
896 2
                continue;
897
            }
898 2
        }
899
900 2
        return $unrenderedFields;
901
    }
902
903
    /**
904
     * Prevent adding fields with same name
905
     *
906
     * @param string $name
907
     */
908 45
    protected function preventDuplicate($name)
909
    {
910 45
        if ($this->has($name)) {
911 1
            throw new \InvalidArgumentException('Field ['.$name.'] already exists in the form '.get_class($this));
912
        }
913 45
    }
914
915
    /**
916
     * @param string $type
917
     * @return string
918
     */
919 49
    protected function getFieldType($type)
920
    {
921 49
        $fieldType = $this->formHelper->getFieldType($type);
922
923 48
        return $fieldType;
924
    }
925
926
    /**
927
     * Check if form is named form
928
     */
929 104
    protected function checkIfNamedForm()
930
    {
931 104
        if ($this->getFormOption('name')) {
932 5
            $this->name = array_pull($this->formOptions, 'name', $this->name);
933 5
        }
934 104
    }
935
936
    /**
937
     * Set up options on single field depending on form options
938
     *
939
     * @param string $name
940
     * @param $options
941
     */
942 49
    protected function setupFieldOptions($name, &$options)
943
    {
944 49
        $options['real_name'] = $name;
945 49
    }
946
947
    /**
948
     * Set namespace to model if form is named so the data is bound properly
949
     * Returns true if model is changed, otherwise false
950
     *
951
     * @return bool
952
     */
953 29
    protected function setupNamedModel()
954
    {
955 29
        if (!$this->getModel() || !$this->getName()) {
956 28
            return false;
957
        }
958
959 4
        $dotName = $this->formHelper->transformToDotSyntax($this->getName());
960 4
        $model = $this->formHelper->convertModelToArray($this->getModel());
961
962 4
        if (!array_get($model, $dotName)) {
963 4
            $newModel = [];
964 4
            array_set($newModel, $dotName, $model);
965 4
            $this->model = $newModel;
966
967 4
            return true;
968
        }
969
970 3
        return false;
971
    }
972
973
974
    /**
975
     * Set form builder instance on helper so we can use it later
976
     *
977
     * @param FormBuilder $formBuilder
978
     * @return $this
979
     */
980 104
    public function setFormBuilder(FormBuilder $formBuilder)
981
    {
982 104
        $this->formBuilder = $formBuilder;
983
984 104
        return $this;
985
    }
986
987
    /**
988
     * @return FormBuilder
989
     */
990 9
    public function getFormBuilder()
991
    {
992 9
        return $this->formBuilder;
993
    }
994
995
    /**
996
     * @param ValidatorFactory $validator
997
     * @return $this
998
     */
999 104
    public function setValidator(ValidatorFactory $validator)
1000
    {
1001 104
        $this->validatorFactory = $validator;
1002
1003 104
        return $this;
1004
    }
1005
1006
    /**
1007
     * Exclude some fields from rendering
1008
     *
1009
     * @return $this
1010
     */
1011
    public function exclude(array $fields)
1012
    {
1013
        $this->exclude = array_merge($this->exclude, $fields);
1014
1015
        return $this;
1016
    }
1017
1018
1019
    /**
1020
     * If form is named form, modify names to be contained in single key (parent[child_field_name])
1021
     *
1022
     * @param string $name
1023
     * @return string
1024
     */
1025 49
    protected function getFieldName($name)
1026
    {
1027 49
        $formName = $this->getName();
1028 49
        if ($formName !== null) {
1029 12
            if (strpos($formName, '[') !== false || strpos($formName, ']') !== false) {
1030 6
                return $this->formHelper->transformToBracketSyntax(
1031 6
                    $this->formHelper->transformToDotSyntax(
1032 6
                        $formName . '[' . $name . ']'
1033 6
                    )
1034 6
                );
1035
            }
1036
1037 9
            return $formName . '[' . $name . ']';
1038
        }
1039
1040 49
        return $name;
1041
    }
1042
1043
    /**
1044
     * Disable all fields in a form
1045
     */
1046 1
    public function disableFields()
1047
    {
1048 1
        foreach ($this->fields as $field) {
1049 1
            $field->disable();
1050 1
        }
1051 1
    }
1052
1053
    /**
1054
     * Enable all fields in a form
1055
     */
1056 1
    public function enableFields()
1057
    {
1058 1
        foreach ($this->fields as $field) {
1059 1
            $field->enable();
1060 1
        }
1061 1
    }
1062
1063
    /**
1064
     * Validate the form
1065
     *
1066
     * @param array $validationRules
1067
     * @param array $messages
1068
     * @return Validator
1069
     */
1070 7
    public function validate($validationRules = [], $messages = [])
1071
    {
1072 7
        $fieldRules = $this->formHelper->mergeFieldsRules($this->fields);
1073 7
        $rules = array_merge($fieldRules['rules'], $validationRules);
1074 7
        $messages = array_merge($fieldRules['error_messages'], $messages);
1075
1076 7
        $this->validator = $this->validatorFactory->make($this->getRequest()->all(), $rules, $messages);
1077 7
        $this->validator->setAttributeNames($fieldRules['attributes']);
1078
1079 7
        $this->eventDispatcher->fire(new BeforeFormValidation($this, $this->validator));
1080
1081 7
        return $this->validator;
1082
    }
1083
1084
    /**
1085
     * Get validatdion rules for the form
1086
     *
1087
     * @param array $overrideRules
1088
     * @return array
1089
     */
1090 1
    public function getRules($overrideRules = [])
1091
    {
1092 1
        $fieldRules = $this->formHelper->mergeFieldsRules($this->fields);
1093
1094 1
        return array_merge($fieldRules['rules'], $overrideRules);
1095
    }
1096
1097 2
    public function redirectIfNotValid($destination = null)
1098
    {
1099 2
        if (! $this->isValid()) {
1100 2
            $response = redirect($destination);
1101
1102 2
            if (is_null($destination)) {
1103 1
                $response = $response->back();
1104 1
            }
1105
1106 2
            $response = $response->withErrors($this->getErrors())->withInput();
1107
1108 2
            throw new HttpResponseException($response);
1109
        }
1110
    }
1111
1112
    /**
1113
     * Get all form field attributes, including child forms, in a flat array.
1114
     *
1115
     * @return array
1116
     */
1117 1
    public function getAllAttributes()
1118
    {
1119 1
        return $this->formHelper->mergeAttributes($this->fields);
1120
    }
1121
1122
    /**
1123
     * Check if the form is valid
1124
     *
1125
     * @return bool
1126
     */
1127 7
    public function isValid()
1128
    {
1129 7
        if (!$this->validator) {
1130 6
            $this->validate();
1131 6
        }
1132
1133 7
        $isValid = !$this->validator->fails();
1134
1135 7
        $this->eventDispatcher->fire(new AfterFormValidation($this, $this->validator, $isValid));
1136
1137 7
        return $isValid;
1138
    }
1139
1140
    /**
1141
     * Get validation errors
1142
     *
1143
     * @return array
1144
     */
1145 6
    public function getErrors()
1146
    {
1147 6
        if (!$this->validator || !$this->validator instanceof Validator) {
1148 1
            throw new \InvalidArgumentException(
1149 1
                sprintf(
1150 1
                    'Form %s was not validated. To validate it, call "isValid" method before retrieving the errors',
1151 1
                    get_class($this)
1152 1
                )
1153 1
            );
1154
        }
1155
1156 5
        return $this->validator->getMessageBag()->getMessages();
1157
    }
1158
1159
    /**
1160
     * Get all Request values from all fields, and nothing else.
1161
     *
1162
     * @return array
1163
     */
1164 1
    public function getFieldValues($with_nulls = true)
1165
    {
1166 1
        $request_values = $this->getRequest()->all();
1167
1168 1
        $values = [];
1169 1
        foreach ($this->getAllAttributes() as $attribute) {
1170 1
            $value = Arr::get($request_values, $attribute);
1171 1
            if ($with_nulls || $value !== null) {
1172 1
                Arr::set($values, $attribute, $value);
1173 1
            }
1174 1
        }
1175
1176 1
        return $values;
1177
    }
1178
1179
    /**
1180
     * Throw an exception indicating a field does not exist on the class
1181
     *
1182
     * @param string $name
1183
     * @throws \InvalidArgumentException
1184
     */
1185 2
    protected function fieldDoesNotExist($name)
1186
    {
1187 2
        throw new \InvalidArgumentException('Field ['.$name.'] does not exist in '.get_class($this));
1188
    }
1189
}
1190