Completed
Pull Request — master (#293)
by
unknown
04:27
created

Form::compose()   B

Complexity

Conditions 5
Paths 7

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 9.2876

Importance

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

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $isValid is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1190 3
    {
1191 3
        // return ['name' => ['Some other error about the Name field.']];
1192 3
    }
1193 3
1194 3
    /**
1195
     * Get validation errors
1196
     *
1197 3
     * @return array
1198 1
     */
1199 1
    public function getErrors()
1200 1
    {
1201
        if (!$this->validator || !$this->validator instanceof Validator) {
1202
            throw new \InvalidArgumentException(
1203 3
                sprintf(
1204
                    'Form %s was not validated. To validate it, call "isValid" method before retrieving the errors',
1205 3
                    get_class($this)
1206
                )
1207
            );
1208
        }
1209
1210
        return $this->validator->getMessageBag()->getMessages();
1211 3
    }
1212
1213 3
    /**
1214
     * Get all Request values from all fields, and nothing else.
1215
     *
1216
     * @return array
1217
     */
1218
    public function getFieldValues($with_nulls = true)
1219
    {
1220
        $request_values = $this->getRequest()->all();
1221 2
1222
        $values = [];
1223 2
        foreach ($this->getAllAttributes() as $attribute) {
1224
            $value = Arr::get($request_values, $attribute);
1225
            if ($with_nulls || $value !== null) {
1226
                Arr::set($values, $attribute, $value);
1227
            }
1228
        }
1229
1230
        // If this form is a child form, cherry pick a part
1231
        if ($prefix = $this->getName()) {
1232
            $prefix = $this->formHelper->transformToDotSyntax($prefix);
1233
            $values = Arr::get($values, $prefix);
1234
        }
1235
1236
        // Allow form-specific value alters
1237
        $this->formHelper->alterFieldValues($this, $values);
1238
1239
        return $values;
1240
    }
1241
1242
    /**
1243
     * Optionally mess with this form's $values before it's returned from getFieldValues()
1244
     */
1245
    public function alterFieldValues(array &$values)
0 ignored issues
show
Unused Code introduced by
The parameter $values is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1246
    {
1247
    }
1248
1249
    /**
1250
     * Throw an exception indicating a field does not exist on the class
1251
     *
1252
     * @param string $name
1253
     * @throws \InvalidArgumentException
1254
     */
1255
    protected function fieldDoesNotExist($name)
1256
    {
1257
        throw new \InvalidArgumentException('Field ['.$name.'] does not exist in '.get_class($this));
1258
    }
1259
}
1260