Form::removeAllPlugins()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 6
c 0
b 0
f 0
rs 9.4285
ccs 0
cts 0
cp 0
cc 2
eloc 3
nc 2
nop 0
crap 6
1
<?php 
2
3
namespace Helmut\Forms;
4
5
use Helmut\Forms\Utility\Str;
6
use Helmut\Forms\Utility\Reflect;
7
8
abstract class Form {
9
10
    /**
11
     * The request implementation used by the form.
12
     *
13
     * @var \Helmut\Forms\Request
14
     */
15
    protected $request;
16
    
17
    /**
18
     * The renderer used by the form.
19
     *
20
     * @var \Helmut\Forms\Renderer
21
     */
22
    protected $renderer;
23
24
    /**
25
     * The unique id of the form.
26
     *
27
     * @var string
28
     */
29
    public $id; 
30
31
    /**
32
     * The action for the form.
33
     *
34
     * @var string
35
     */
36
    public $action = '';    
37
38
    /**
39
     * Array containing all the form fields.
40
     *
41
     * @var array
42
     */
43
    protected $fields = [];
44
45
    /**
46
     * Array of button keys.
47
     *
48
     * @var array
49
     */
50
    protected $buttons = [];    
51
52
    /**
53
     * Array of models.
54
     *
55
     * @var array
56
     */
57
    protected $models = []; 
58
59
    /**
60
     * The active template package.
61
     *
62
     * @var string
63
     */
64
    protected $template;
65
66
    /**
67
     * The active language used.
68
     *
69
     * @var string
70
     */
71
    protected $lang = 'en'; 
72
73
    /**
74
     * A cache of language translations.
75
     *
76
     * @var array
77
     */
78
    protected $translations = [];   
79
80
    /**
81
     * An array of plugins.
82
     *
83
     * @var array
84
     */
85
    protected $plugins = [];    
86
87
    /**
88
     * An array of namespaces for class loading.
89
     *
90
     * @var array
91
     */
92
    protected $namespaces = [];
93
94
    /**
95
     * An array of paths for autoloading.
96
     *
97
     * @var array
98
     */
99
    protected $paths = [];  
100
101
    /**
102
     * The static instantiation counter. Used
103
     * to make sure each form implementation can
104
     * have a unique id.
105
     *
106
     * @var integer
107
     */
108
    protected static $count = 0;
109
  
110
    /**
111
     * Create a new form.
112
     *
113
     * @param  \Helmut\Forms\Request  $request
114
     * @param  \Helmut\Forms\Renderer  $renderer
115
     */
116
    public function __construct(Request $request = null, Renderer $renderer = null)
117
    {
118
        $this->request = $request ?: new Requests\Globals;
119
        $this->renderer = $renderer ?: new Renderer;
120 134
121
        $this->loadNamespaces();
122 134
    
123 134
        $this->setId();
124
        $this->loadDefaults();
125 134
        $this->triggerDefinition();
126
    }
127 134
128 134
    /**
129 134
     * Load namespaces.
130 134
     *
131
     * @return void
132
     */
133
    public function loadNamespaces()
134
    {
135
        $class = get_class($this);
136
137 134
        $classes = [$class];
138
139 134
        while ($class = get_parent_class($class)) {
140
            $classes[] = $class;
141 134
        }
142
143 134
        $classes = array_reverse($classes);
144 134
145
        foreach ($classes as $class) {
146
            $this->addNamespaceForClass($class);
147 134
        }
148
    }
149 134
150 134
    /**
151
     * Set a unique id.
152 134
     *
153
     * @return void
154
     */
155
    public function setId()
156
    {
157
        self::$count++;
158
        $id = substr(md5(self::$count), 0, 5);
159 134
        $this->id = 'form_'.$id;
160
    }
161 134
162 134
    /**
163 134
     * Load form defaults
164 134
     *
165
     * @return void
166
     */
167
    public function loadDefaults()
168
    {
169
        if (is_null($this->template)) {
170
            $this->setTemplate('bootstrap');
171 134
        }
172
    }
173 134
174 134
    /**
175
     * Trigger the definition.
176 134
     *
177
     * @return void
178
     */
179
    public function triggerDefinition()
180
    {
181
        if (method_exists($this, 'define')) {
182
            call_user_func_array([$this, 'define'], []);
183 134
        }
184
185 134
        $this->broadcast('define');
186 1
    }    
187
188
    /**
189 134
     * Add a new field.
190 134
     *
191
     * @param  string  $type
192
     * @param  string  $name
193
     * @return \Helmut\Forms\Fields\Field
194
     */
195
    public function addField($type, $name)
196
    {
197
        if ( ! isset($this->fields[$name])) { 
198
            $class = $this->typeToClass($type);
199 118
            $field = new $class($this, $type, $name);
200
            foreach ($field->buttons() as $button) {
201 118
                $this->addButton($button);
202 118
            }
203 118
            $this->fields[$name] = $field;
204 118
        }
205 19
        return $this->fields[$name];
206
    }
207 118
208
    /**
209 118
     * Set all the field values.
210
     *
211
     * @return void
212
     */
213
    public function setValues()
214
    {
215
        foreach ($this->fields as $field)
216
        {
217 113
            // Set values from defaults
218
            $field->setFromDefault();
219 113
220
            // Then load values from models
221
            foreach ($this->models as $model) {
222 111
                $field->setFromModel($model);
223
            }
224
225 111
            // Then from the current request if submitted
226 9
            if ($this->submitted()) {
227
                $field->setFromRequest($this->request);
228
            }
229
        }
230 111
    }
231 111
232
    /**
233
     * Add default models to the form.
234 113
     *
235
     * @return void
236
     */
237
    public function defaults() 
238
    {
239
        $models = func_get_args();
240
        
241
        foreach ($models as $model) {
242 9
            $this->models[] = (object) $model;
243
        }
244 9
245
    }
246 9
247 9
    /**
248
     * Fetch all fields or just those matching
249
     * the names provided.
250 9
     *
251
     * @param  array  $names
252
     * @return array
253
     */
254
    public function fields($names = null)
255
    {
256
        if (is_null($names)) {
257
            return $this->fields;
258
        }
259 15
260
        return array_filter($this->fields, function($field) use ($names) {
261 15
            return in_array($field->name, $names);
262
        });
263
    }   
264
265
    /**
266
     * Get a field matching name.
267
     *
268
     * @param  string  $name
269
     * @return \Helmut\Forms\Field
270
     */
271
    public function field($name)
272
    {
273
        if (isset($this->fields[$name])) {
274 26
            return $this->fields[$name];
275
        }
276 26
    }   
277 26
278
    /**
279
     * Fetch all of the field keys.
280
     *
281
     * @return array
282
     */
283
    public function keys()
284
    {
285
        $keys = [];
286 1
287
        foreach ($this->fields as $field) {
288 1
            $keys = array_merge($keys, $field->keys());
289
        }
290 1
        
291 1
        return $keys;
292
    }
293
294 1
    /**
295
     * Fetch all of the field values.
296
     *
297
     * @return array
298
     */
299
    public function all()
300
    {
301
        $this->setValues();
302 1
303
        $values = [];
304 1
305
        foreach ($this->fields as $field) {
306 1
            $values = array_merge($values, $field->values());
307
        }
308 1
309 1
        return $values;
310
    }
311
    
312 1
    /**
313
     * Fetch the value of a field.
314
     *
315
     * @param  string  $name
316
     * @param  string  $key
317
     * @return array
318
     */
319
    public function get($name, $key = null)
320
    {
321
        $this->setValues();
322 25
323
        $field = $this->field($name);
324 25
325
        if ( ! is_null($field)) {
326 25
            return $field->value($key);
327
        }
328 25
    }
329 25
330
    /**
331
     * Fill a model with values.
332
     *
333
     * @param  object  $model
334
     * @param  array  $names
335
     */
336
    public function fill($model, $names = null)
337
    {
338
        $this->setValues();
339 13
340
        $fields = $this->fields($names);
341 13
342
        foreach ($fields as $field) {
343 13
            $field->fillModel($model);
344
        }
345 13
    }
346 13
347
    /**
348 13
     * Check if a form has been submitted and valid in one
349
     * quick and easy step.
350
     *
351
     * @param  string  $name
352
     * @return bool
353
     */
354
    public function completed($name = null)
355
    {
356
        if($this->submitted($name) && $this->valid()) {
357
            $this->broadcast('completed');
358
            return true;
359
        }
360
        return false;
361
    }
362
363
    /**
364
     * Check if a form has been submitted. If no specific name
365
     * is requested check for any button.
366
     *
367
     * @param  string  $name
368
     * @return bool
369
     */
370
    public function submitted($name = null) 
371
    {
372
        $buttons = is_null($name) ? $this->buttons : [$name];
373 116
374
        foreach ($buttons as $button) {
375 116
            if ($this->request->get($button) == true) {
376
                $this->broadcast('submitted');
377 116
                return true;
378 116
            }
379 9
        }
380 116
381
        return false;
382
    }
383
384 108
    /**
385
     * Add a button.
386
     *
387
     * @param  string  $name
388
     * @return void
389
     */
390
    public function addButton($name)
391
    {
392
        $this->buttons[] = $name;
393 134
    }
394
395 134
    /**
396 134
     * Add a new namespace.
397
     *
398
     * @param  string  $namespace
399
     * @return void
400
     */
401
    public function addNamespace($namespace)
402
    {
403
        if ( ! in_array($namespace, $this->namespaces)) {
404 134
            array_unshift($this->namespaces, $namespace);
405
        }
406 134
    }
407 134
408
    /**
409 134
     * Get namespaces.
410
     *
411
     * @return array
412
     */
413
    public function namespaces()
414
    {
415
        return $this->namespaces;
416 2
    }
417
418 2
    /**
419
     * Add a new autoload path.
420
     *
421
     * @param  string  $path
422
     * @return void
423
     */
424
    public function addPath($path)
425
    {
426
        $path = rtrim($path, '/').'/';
427 134
428
        if ( ! in_array($path, $this->paths) && is_dir($path)) {
429 134
            array_unshift($this->paths, $path);
430
        }
431 134
    }
432 134
433
    /**
434 134
     * Find and add a new namespace using a class.
435
     *
436
     * @param  string  $class
437
     * @return void
438
     */
439
    public function addNamespaceForClass($class)
440
    {
441
        $namespace = Reflect::getNamespace($class);
442 134
443
        if ( ! is_null($namespace)) {
444 134
            $this->addNamespace($namespace);
445
        }
446 134
447
        $directory = Reflect::getDirectory($class);
448 134
  
449 134
        if ( ! is_null($directory) && is_dir($directory)) {
450
            $this->addPath($directory);
451
        }
452 134
    }   
453 134
454
    /**
455
     * Check if a type exists.
456
     *
457
     * @param  string  $type
458
     * @return string
459
     */
460
    public function typeExists($type)
461 118
    {
462
        return ! is_null($this->typeToClass($type));
463 118
    }
464
465
    /**
466
     * Convert a string type to full class name.
467
     *
468
     * @param  string  $type
469
     * @return string
470
     */
471
    public function typeToClass($type)
472 118
    {
473
        $class = Str::studly($type);
474 118
475
        $class = '\\Fields\\'.ucwords($class).'\\'.ucwords($class);
476 118
477
        foreach ($this->namespaces as $namespace) {
478 118
            if (class_exists($namespace.$class)) {
479 118
                return $namespace.$class;
480
            }
481 10
        }
482
    }
483
484
    /**
485
     * Get the validation errors. With option to
486
     * get only for a specific field.
487
     *
488
     * @param  string  $name
489
     * @return array     
490
     */
491
    public function errors($name = null)
492
    {
493
        if ($this->submitted()) {
494
            $this->validate();
495
        }
496
497
        if ( ! is_null($name)) {
498
            return $this->field($name)->errors();
499
        }
500
501
        $errors = [];
502
503
        foreach ($this->fields as $field) {
504
            foreach($field->errors() as $error) {
505
                $errors[] = $error;
506
            }
507
        }
508
509
        return $errors;
510
    }
511
512 28
    /**
513
     * Perform validation on the form. 
514 28
     *
515
     * @return void
516 28
     */
517
    public function validate()
518 28
    {
519 28
        $this->setValues();
520
521
        $this->broadcast('validate');
522 28
523 28
        foreach ($this->fields as $field) {
524
            $field->runValidations();
525
        }
526
527
        $this->broadcast('validated');
528
    }
529
530
    /**
531
     * Perform validation on the form. With option
532 27
     * to check if a particular field is valid.
533
     *
534 27
     * @param  string  $name
535
     * @return bool
536 27
     */
537
    public function valid($name = null)
538 27
    {
539
        $this->validate();
540 27
541 26
        $fields = is_null($name) ? $this->fields : [$this->field($name)];
542 27
543
        foreach ($fields as $field) {
544
545
            if ($field->isInvalid()) {
546 27
                $this->broadcast('invalid');
547 27
                return false;
548
            }
549
        }
550
551
        $this->broadcast('valid');
552
        return true;
553
    }
554
555
    /**
556
     * The opposite of valid.
557
     *
558
     * @param  string  $name
559
     * @return bool
560
     */
561
    public function invalid($name = null)
562
    {
563
        return ! $this->valid($name);
564
    }   
565
566
    /**
567 1
     * Set the active language.
568
     *
569 1
     * @param  string  $lang
570 1
     * @return void
571
     */
572
    public function setLanguage($lang)
573
    {
574
        $this->lang = $lang;
575
    }
576
577
    /**
578 134
     * Set the template package.
579
     *
580 134
     * @param  string  $template
581 4
     * @return void
582
     */
583
    public function setTemplate($template)
584 134
    {
585
        if ( ! is_null($this->template)) {
586 134
            $this->uninstallTemplate($this->template);
587 134
        }
588
589
        $this->installTemplate($template);
590
        
591
        $this->template = $template;
592
    }
593
594
    /**
595 134
     * Get template configuration.
596
     *
597 134
     * @param  string  $template
598
     * @return array
599 134
     */
600
    public function templateConfig($template)
601 134
    {
602
        $paths = $this->paths(null, 'templates/'.$template);
603 134
604 134
        foreach ($paths as $path) {
605
            
606
            $config = $path.'config.php';
607
            
608 4
            if (file_exists($config)) {
609
                return include($config);
610
            }
611
        }
612
613
        return [];
614
    }   
615
616
    /**
617 134
     * Install template configuration.
618
     *
619 134
     * @param  string  $template
620
     * @return void
621 134
     */
622 134
    public function installTemplate($template)
623 134
    {
624
        $config = $this->templateConfig($template);
625
626 134
        if ( isset($config['plugins']) && is_array($config['plugins'])) {
627
            foreach($config['plugins'] as $key => $plugin) {
628
                if (is_array($plugin)) {
629
                    $this->addPlugin($key, $plugin);
630
                } else {
631
                    $this->addPlugin($plugin);
632
                }
633
            }
634 4
        }
635
    }
636 4
637
    /**
638 4
     * Uninstall template configuration.
639 4
     *
640 4
     * @param  string  $template
641
     * @return void
642
     */
643 4
    public function uninstallTemplate($template)
644
    {
645
        $config = $this->templateConfig($template);
646
647
        if ( isset($config['plugins']) && is_array($config['plugins'])) {
648
            foreach($config['plugins'] as $plugin) {
649
                $this->removePlugin($plugin);
650
            }
651 45
        }
652
    }
653
654 45
    /**
655 45
     * Fetch a fields properties.
656 45
     *
657 45
     * @param  \Helmut\Forms\Field  $field
658 45
     * @return string
659 45
     */
660 45
    public function fieldProperties($field) 
661 45
    {   
662
        $properties = [ 
663
            'id' => $field->id, 
664
            'form_id' => $this->id, 
665
            'type' => $field->type, 
666 45
            'name' => $field->name, 
667
            'label' => $field->label,
668 45
            'required' => $field->isRequired(),
669 44
            'valid' => $field->isValid(),
670
            'invalid' => $field->isInvalid(),
671
            'errors' => [],
672 45
            'keys' => [],
673 1
        ];
674
675 1
        $properties = array_merge($properties, $field->properties());
676
677
        foreach ($field->keys() as $key) {
678
            $properties['keys'][] = $key;
679
        }
680
681 1
        if ($field->isInvalid()) {
682
            foreach ($field->errors() as $error => $parameters) {
683 1
684
                if ($error == 'userDefined') {
685 1
                    foreach($parameters as $message) {
686 1
                        $properties['errors'][] = ['error' => $message];
687 1
                    }
688 1
                } else {
689
690 1
                    $parameters['field'] = str_replace('_', ' ', $field->name);
691
692
                    $message = $this->translate($error, $field);
693
694
                    foreach($parameters as $key => $value) {
695 45
                        if (is_object($value) && method_exists($value, '__toString')) {
696
                            $value = (string) $value;
697
                        }
698
                        if (is_array($value)) {
699
                            $value = implode(', ', $value);
700
                        }
701
                        $message = str_replace('['.$key.']', $value, $message);
702
                    }
703
704
                    $properties['errors'][] = ['error' => $message];
705 45
                }
706
            }
707 45
        }
708
709 45
        return $properties;
710
    }
711
712
    /**
713
     * Render the field using templates.
714
     *
715
     * @param  \Helmut\Forms\Field  $field
716
     * @param  array  $properties
717
     * @return string
718
     */
719 45 View Code Duplication
    public function renderField($field, $properties = null) 
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
720
    {   
721 45
        if (is_null($properties)) {
722
            $properties = $this->fieldProperties($field);
723 45
        }
724
725
        return $this->renderTemplate($field->type, $properties, $field);
726
    }
727
728
    /**
729
     * Render the field using templates.
730
     *
731
     * @param  \Helmut\Forms\Field  $field
732 47
     * @param  array  $properties
733
     * @return string
734 47
     */
735 View Code Duplication
    public function renderFieldErrors($field, $properties = null) 
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
736 47
    {   
737
        if (is_null($properties)) {
738 47
            $properties = $this->fieldProperties($field);
739
        }
740 47
741
        return $this->renderTemplate('errors', $properties, $field);
742 47
    }   
743 47
744 47
    /**
745 47
     * Render the form using templates.
746 47
     *
747
     * @param  string  $template
748 47
     * @return string
749
     */
750 47
    public function render($template = null)
751
    {
752 45
        $this->broadcast('render');
753
754 45
        $this->setValues();
755
756 45
        if ($this->submitted()) {
757 45
            $this->validate();
758
        }
759 45
760
        if ( ! is_null($template)) {
761 45
            $this->setTemplate($template);
762
        }
763
764 47
        $properties = [];
765
        $properties['id'] = $this->id;
766 47
        $properties['action'] = $this->action;
767
        $properties['csrf'] = $this->request->csrf();
768 47
        
769
        if ($this->submitted()) {
770
            $properties['valid'] = $this->valid();     
771
            $properties['invalid'] = ! $properties['valid'];
772
        }
773
774
        $properties['fields'] = [];     
775
776
        $renderered_form = $this->renderTemplate('csrf', $this->request->csrf());
777
778
        foreach ($this->fields as $field) {
779 47
780
            $field_properties = $this->fieldProperties($field);
781 47
782
            $properties['fields'][] = $field_properties;
783 47
784
            $rendered_field = $this->renderField($field, $field_properties);
785 47
            $rendered_field .= $this->renderFieldErrors($field, $field_properties);
786
787 47
            $field_properties['field'] = $rendered_field;
788
789 47
            $renderered_form .= $this->renderTemplate('field', $field_properties, $field);
790
        }
791
792
        $properties['form'] = $renderered_form;
793
794
        $renderered_template = $this->renderTemplate('form', $properties);
795 47
796
        return $renderered_template;
797
    }
798
799
    /**
800
     * Render a template.
801
     *
802
     * @param  string  $template
803
     * @param  array  $properties
804
     * @param  \Helmut\Forms\Field  $field
805 1
     * @return string
806
     */
807 1
    public function renderTemplate($template, $properties = [], $field = null)
808
    {
809 1
        $paths = $this->templatePaths($field);
810 1
811
        $properties['lang'] = $this->translations($field);
812
813
        $rendered_template = $this->renderer->render($template, $properties, $paths);
814
815
        if (count($this->plugins)) {
816
817
            $properties[$template] = $rendered_template;
818
819
            foreach ($this->plugins as $key=>$plugin) {
820
                if ($this->renderer->has($template, $plugin->templatePaths())) {
821
                    $rendered_template = $this->renderer->render($template, $properties, $plugin->templatePaths());
822 47
                    $properties[$template] = $rendered_template;
823
                }
824 47
            }
825
        }
826 47
827 47
        return $rendered_template;
828 47
    }
829
830
    /**
831 47
     * Translate a specific key.
832
     *
833 47
     * @param  string  $key
834
     * @param  \Helmut\Forms\Field  $field
835 45
     * @return string
836
     */
837 45
    public function translate($key, $field = null) 
838 45
    {
839
        $translations = $this->translations($field);
840
841 45
        if (isset($translations[$key])) {
842
            return $translations[$key];
843 45
        }
844
845
        throw new \Exception('No translation found for '.$key);
846 45
    }
847
848
    /**
849 47
     * Get translations and cache them if necessary.
850
     *
851
     * @param  \Helmut\Forms\Field  $field
852
     * @return array
853
     */
854
    public function translations($field = null) 
855
    {
856
        $lang = $this->lang;
857
858
        if ( ! isset($this->translations[$lang])) {
859 47
            $paths = $this->langPaths();
860
            $this->translations[$lang] = $this->loadTranslations($lang, $paths);
861 47
        }
862
863 47
        $translations = $this->translations[$lang];
864 47
865 47
        if ( ! is_null($field)) {
866 47
867
            if ( ! isset($this->translations[$field->type][$lang])) {
868
869
                if ( ! isset($this->translations[$field->type])) {
870 47
                    $this->translations[$field->type] = [];
871
                }
872
873
                $paths = $this->langPaths($field);
874
875
                $paths = array_reverse($paths);
876
877
                $this->translations[$field->type][$lang] = $this->loadTranslations($lang, $paths);
878
            }
879 134
880
            $translations = array_merge($translations, $this->translations[$field->type][$lang]);
881 134
882
        } 
883 134
884
        return $translations;
885 134
    }
886
887 134
    /**
888
     * Load the translations from paths.
889 134
     *
890 134
     * @param  string  $lang
891 134
     * @param  array  $paths
892
     * @return array
893 134
     */
894
    public function loadTranslations($lang, $paths) 
895
    {
896
        $translations = [];
897
898
        foreach ($paths as $path) {
899
            $file = $path.$lang.'.php';
900
            if (file_exists($file)) {
901
                $translations = array_merge($translations, include($file));
902
            }
903
        }
904 134
905
        return $translations;
906 134
    }
907 134
908
    /**
909 134
     * Add a plugin to a form.
910
     *
911
     * @param  string  $name
912
     * @param  array  $config
913
     * @return \Helmut\Forms\Plugin
914
     */
915
    public function addPlugin($name, $config = [])
916 134
    {
917
        $class = Str::studly($name);
918 134
919 134
        $class = '\\Plugins\\'.ucwords($class).'\\'.ucwords($class);
920
921 134
        foreach ($this->namespaces as $namespace) {
922
            
923
            $plugin = $namespace.$class;
924
            
925
            if (class_exists($plugin)) {
926
                $this->plugins[$name] = new $plugin($config);
927
                $this->plugins[$name]->event($this, 'load');
928
929
                return $this->plugins[$name];
930 134
            }
931
        }
932 134
    }
933 134
934
    /**
935 134
     * Remove a plugin.
936
     *
937
     * @param  string  $name
938
     * @return void
939
     */
940
    public function removePlugin($name)
941
    {
942
        if (array_key_exists($name, $this->plugins)) {
943
            unset($this->plugins[$name]);
944 47
        }
945
    }
946 47
947
    /**
948
     * Get a plugin instance.
949
     *
950
     * @param  string  $name
951
     * @return \Helmut\Forms\Plugin
952
     */
953
    public function getPlugin($name)
954
    {
955
        return $this->plugins[$name];
956 53
    }
957
958 53
    /**
959
     * Remove all plugins.
960
     *
961
     * @return void
962
     */
963
    public function removeAllPlugins()
964
    {
965
        foreach ($this->plugins as $name => $plugin) {
966
            $this->removePlugin($name);
967
        }
968
    }   
969 134
970
    /**
971 134
     * Broadcast an event.
972
     *
973 134
     * @param  string  $event
974 45
     * @param  array  $params
975
     * @return void
976
     */
977 134
    private function broadcast($event, $params = []) 
978 134
    {
979 134
        foreach($this->plugins as $plugin) {
980 134
            $plugin->event($this, $event, $params);
981
        }
982
    }
983 134
984
    /**
985
     * Get all paths to the language files or just to those
986
     * for a specific field. 
987
     *
988
     * @param  \Helmut\Forms\Field  $field
989
     * @return array
990
     */
991
    public function langPaths($field = null) 
992 45
    {
993
        return $this->paths($field, 'lang');
994 45
    }
995
996 45
    /**
997 45
     * Get all paths to template packages or just to the 
998
     * packages for a specific field.
999 45
     *
1000
     * @param  \Helmut\Forms\Field  $field
1001
     * @return array
1002
     */
1003
    public function templatePaths($field = null) 
1004
    {
1005
        return $this->paths($field, 'templates/'.$this->template);
1006
    }
1007
1008
    /**
1009
     * Get all autoload paths or just the path 
1010
     * of a specific resource.
1011
     *
1012
     * @param  \Helmut\Forms\Field  $field
1013
     * @param  string  $append
1014
     * @return array
1015
     */
1016
    public function paths($field = null, $append = null) 
1017
    {
1018
        $paths = $this->paths;
1019
1020
        if ( ! is_null($field)) {
1021
            array_unshift($paths, $this->pathForClass($field));
1022
        }
1023
1024
        if ( ! is_null($append)) {
1025
            $paths = array_map(function($path) use($append) {
1026
                return $path .= ltrim(rtrim($append, '/'), '/').'/';
1027
            }, $paths);
1028
        }
1029 1
1030
        return array_filter($paths, 'is_dir');
1031 1
    }
1032
1033
    /**
1034
     * Get autoload path for a class.
1035
     *
1036
     * @param  string|object  $class
1037
     * @return string
1038
     */
1039
    public function pathForClass($class)
1040
    {
1041
        $path = Reflect::getDirectory($class);
1042
1043
        return rtrim($path, '/').'/';
1044
    }
1045
1046
1047
    /**
1048
     * Set the form action.
1049 134
     *
1050
     * @param  string  $action     
1051 134
     * @return void
1052 134
     */
1053
    public function setAction($action)
1054
    {
1055 134
        $this->action = $action;
1056
    }
1057
1058
    /**
1059
     * Get the active template package.
1060
     *
1061
     * @return string
1062
     */
1063
    public function getTemplate()
1064
    {
1065
        return $this->template;
1066
    }
1067
1068
    /**
1069
     * Get the request implementation.
1070
     *
1071
     * @return \Helmut\Forms\Request
1072
     */
1073
    public function getRequest()
1074
    {
1075
        return $this->request;
1076 118
    }   
1077
1078 118
    /**
1079
     * Get the renderer implementation.
1080 118
     *
1081 118
     * @return \Helmut\Forms\Renderer
1082
     */
1083
    public function getRenderer()
1084 10
    {
1085
        return $this->renderer;
1086
    } 
1087
1088
    /**
1089
     * Get all of the plugins
1090
     *
1091
     * @return array
1092
     */
1093
    public function getPlugins()
1094
    {
1095
        return $this->plugins;
1096
    }
1097
1098
    /**
1099
     * Get all of the namespaces
1100
     *
1101
     * @return array
1102
     */
1103
    public function getNamespaces()
1104
    {
1105
        return $this->namespaces;
1106
    }       
1107
1108
    /**
1109
     * Requests directly on the object could be trying to
1110
     * create a field so check if type exists.
1111
     *
1112
     * @param  string  $method
1113
     * @param  array  $parameters
1114
     * @return mixed
1115
     */
1116
    public function __call($method, $parameters)
1117
    {
1118
        if ( ! method_exists($this, $method))
1119
        {
1120
            if ( $this->typeExists($method)) {
1121
                return $this->addField($method, array_shift($parameters));
1122
            }
1123
        }
1124
    }
1125
1126
    /**
1127
     * Render the form.
1128
     *
1129
     * @return string
1130
     */
1131
    public function __toString()
1132
    {
1133
        return $this->render();
1134
    }   
1135
1136
}
1137