Completed
Push — master ( 04f3fb...1e991f )
by Helmut
02:48
created

Form::installTemplate()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 5

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 14
ccs 6
cts 6
cp 1
rs 8.8571
cc 5
eloc 8
nc 4
nop 1
crap 5
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)) return $this->fields;
257
258
        return array_filter($this->fields, function($field) use ($names) {
259 15
            return array_key_exists($field->name, $names);
260
        });
261 15
    }   
262
263
    /**
264
     * Get a field matching name.
265
     *
266
     * @param  string  $name
267
     * @return \Helmut\Forms\Field
268
     */
269
    public function field($name)
270
    {
271
        if (isset($this->fields[$name])) {
272
            return $this->fields[$name];
273
        }
274 26
    }   
275
276 26
    /**
277 26
     * Fetch all of the field keys.
278
     *
279
     * @return array
280
     */
281
    public function keys()
282
    {
283
        $keys = [];
284
285
        foreach ($this->fields as $field) {
286 1
            $keys = array_merge($keys, $field->keys());
287
        }
288 1
        
289
        return $keys;
290 1
    }
291 1
292
    /**
293
     * Fetch all of the field values.
294 1
     *
295
     * @return array
296
     */
297
    public function all()
298
    {
299
        $this->setValues();
300
301
        $values = [];
302 1
303
        foreach ($this->fields as $field) {
304 1
            $values = array_merge($values, $field->values());
305
        }
306 1
307
        return $values;
308 1
    }
309 1
    
310
    /**
311
     * Fetch the value of a field.
312 1
     *
313
     * @param  string  $name
314
     * @param  string  $key
315
     * @return array
316
     */
317
    public function get($name, $key = null)
318
    {
319
        $this->setValues();
320
321
        $field = $this->field($name);
322 25
323
        if ( ! is_null($field)) {
324 25
            return $field->value($key);
325
        }
326 25
    }
327
328 25
    /**
329 25
     * Fill a model with values.
330
     *
331
     * @param  object  $model
332
     * @param  array  $names
333
     */
334
    public function fill($model, $names = null)
335
    {
336
        $this->setValues();
337
338
        $fields = $this->fields($names);
339 13
340
        foreach ($fields as $field) {
341 13
            $field->fillModel($model);
342
        }
343 13
    }
344
345 13
    /**
346 13
     * Check if a form has been submitted and valid in one
347
     * quick and easy step.
348 13
     *
349
     * @param  string  $name
350
     * @return bool
351
     */
352
    public function completed($name = null)
353
    {
354
        if($this->submitted($name) && $this->valid()) {
355
            $this->broadcast('completed');
356
            return true;
357
        }
358
        return false;
359
    }
360
361
    /**
362
     * Check if a form has been submitted. If no specific name
363
     * is requested check for any button.
364
     *
365
     * @param  string  $name
366
     * @return bool
367
     */
368
    public function submitted($name = null) 
369
    {
370
        $buttons = is_null($name) ? $this->buttons : [$name];
371
372
        foreach ($buttons as $button) {
373 116
            if ($this->request->get($button) == true) {
374
                $this->broadcast('submitted');
375 116
                return true;
376
            }
377 116
        }
378 116
379 9
        return false;
380 116
    }
381
382
    /**
383
     * Add a button.
384 108
     *
385
     * @param  string  $name
386
     * @return void
387
     */
388
    public function addButton($name)
389
    {
390
        $this->buttons[] = $name;
391
    }
392
393 134
    /**
394
     * Add a new namespace.
395 134
     *
396 134
     * @param  string  $namespace
397
     * @return void
398
     */
399
    public function addNamespace($namespace)
400
    {
401
        if ( ! in_array($namespace, $this->namespaces)) {
402
            array_unshift($this->namespaces, $namespace);
403
        }
404 134
    }
405
406 134
    /**
407 134
     * Get namespaces.
408
     *
409 134
     * @return array
410
     */
411
    public function namespaces()
412
    {
413
        return $this->namespaces;
414
    }
415
416 2
    /**
417
     * Add a new autoload path.
418 2
     *
419
     * @param  string  $path
420
     * @return void
421
     */
422
    public function addPath($path)
423
    {
424
        $path = rtrim($path, '/').'/';
425
426
        if ( ! in_array($path, $this->paths) && is_dir($path)) {
427 134
            array_unshift($this->paths, $path);
428
        }
429 134
    }
430
431 134
    /**
432 134
     * Find and add a new namespace using a class.
433
     *
434 134
     * @param  string  $class
435
     * @return void
436
     */
437
    public function addNamespaceForClass($class)
438
    {
439
        $namespace = Reflect::getNamespace($class);
440
441
        if ( ! is_null($namespace)) {
442 134
            $this->addNamespace($namespace);
443
        }
444 134
445
        $directory = Reflect::getDirectory($class);
446 134
  
447
        if ( ! is_null($directory) && is_dir($directory)) {
448 134
            $this->addPath($directory);
449 134
        }
450
    }   
451
452 134
    /**
453 134
     * Check if a type exists.
454
     *
455
     * @param  string  $type
456
     * @return string
457
     */
458
    public function typeExists($type)
459
    {
460
        return ! is_null($this->typeToClass($type));
461 118
    }
462
463 118
    /**
464
     * Convert a string type to full class name.
465
     *
466
     * @param  string  $type
467
     * @return string
468
     */
469
    public function typeToClass($type)
470
    {
471
        $class = Str::studly($type);
472 118
473
        $class = '\\Fields\\'.ucwords($class).'\\'.ucwords($class);
474 118
475
        foreach ($this->namespaces as $namespace) {
476 118
            if (class_exists($namespace.$class)) return $namespace.$class;
477
        }
478 118
    }
479 118
480
    /**
481 10
     * Get the validation errors. With option to
482
     * get only for a specific field.
483
     *
484
     * @param  string  $name
485
     * @return array     
486
     */
487
    public function errors($name = null)
488
    {
489
        if ($this->submitted()) $this->validate();
490
491
        if ( ! is_null($name)) return $this->field($name)->errors();
492
493
        $errors = [];
494
495
        foreach ($this->fields as $field) {
496
            foreach($field->errors() as $error) {
497
                $errors[] = $error;
498
            }
499
        }
500
501
        return $errors;
502
    }
503
504
    /**
505
     * Perform validation on the form. 
506
     *
507
     * @return void
508
     */
509
    public function validate()
510
    {
511
        $this->setValues();
512 28
513
        $this->broadcast('validate');
514 28
515
        foreach ($this->fields as $field) {
516 28
            $field->runValidations();
517
        }
518 28
519 28
        $this->broadcast('validated');
520
    }
521
522 28
    /**
523 28
     * Perform validation on the form. With option
524
     * to check if a particular field is valid.
525
     *
526
     * @param  string  $name
527
     * @return bool
528
     */
529
    public function valid($name = null)
530
    {
531
        $this->validate();
532 27
533
        $fields = is_null($name) ? $this->fields : [$this->field($name)];
534 27
535
        foreach ($fields as $field) {
536 27
537
            if ($field->isInvalid()) {
538 27
                $this->broadcast('invalid');
539
                return false;
540 27
            }
541 26
        }
542 27
543
        $this->broadcast('valid');
544
        return true;
545
    }
546 27
547 27
    /**
548
     * The opposite of valid.
549
     *
550
     * @param  string  $name
551
     * @return bool
552
     */
553
    public function invalid($name = null)
554
    {
555
        return ! $this->valid($name);
556
    }   
557
558
    /**
559
     * Set the active language.
560
     *
561
     * @param  string  $lang
562
     * @return void
563
     */
564
    public function setLanguage($lang)
565
    {
566
        $this->lang = $lang;
567 1
    }
568
569 1
    /**
570 1
     * Set the template package.
571
     *
572
     * @param  string  $template
573
     * @return void
574
     */
575
    public function setTemplate($template)
576
    {
577
        if ( ! is_null($this->template)) {
578 134
            $this->uninstallTemplate($this->template);
579
        }
580 134
581 4
        $this->installTemplate($template);
582
        
583
        $this->template = $template;
584 134
    }
585
586 134
    /**
587 134
     * Get template configuration.
588
     *
589
     * @param  string  $template
590
     * @return array
591
     */
592
    public function templateConfig($template)
593
    {
594
        $paths = $this->paths(null, 'templates/'.$template);
595 134
596
        foreach ($paths as $path) {
597 134
            
598
            $config = $path.'config.php';
599 134
            
600
            if (file_exists($config)) {
601 134
                return include($config);
602
            }
603 134
        }
604 134
605
        return [];
606
    }   
607
608 4
    /**
609
     * Install template configuration.
610
     *
611
     * @param  string  $template
612
     * @return void
613
     */
614
    public function installTemplate($template)
615
    {
616
        $config = $this->templateConfig($template);
617 134
618
        if ( isset($config['plugins']) && is_array($config['plugins'])) {
619 134
            foreach($config['plugins'] as $key => $plugin) {
620
                if (is_array($plugin)) {
621 134
                    $this->addPlugin($key, $plugin);
622 134
                } else {
623 134
                    $this->addPlugin($plugin);
624
                }
625
            }
626 134
        }
627
    }
628
629
    /**
630
     * Uninstall template configuration.
631
     *
632
     * @param  string  $template
633
     * @return void
634 4
     */
635
    public function uninstallTemplate($template)
636 4
    {
637
        $config = $this->templateConfig($template);
638 4
639 4
        if ( isset($config['plugins']) && is_array($config['plugins'])) {
640 4
            foreach($config['plugins'] as $plugin) {
641
                $this->removePlugin($plugin);
642
            }
643 4
        }
644
    }
645
646
    /**
647
     * Fetch a fields properties.
648
     *
649
     * @param  \Helmut\Forms\Field  $field
650
     * @return string
651 45
     */
652
    public function fieldProperties($field) 
653
    {   
654 45
        $properties = [ 
655 45
            'id' => $field->id, 
656 45
            'form_id' => $this->id, 
657 45
            'type' => $field->type, 
658 45
            'name' => $field->name, 
659 45
            'label' => $field->label,
660 45
            'required' => $field->isRequired(),
661 45
            'valid' => $field->isValid(),
662
            'invalid' => $field->isInvalid(),
663
            'errors' => [],
664
            'keys' => [],
665
        ];
666 45
667
        $properties = array_merge($properties, $field->properties());
668 45
669 44
        foreach ($field->keys() as $key) {
670
            $properties['keys'][] = $key;
671
        }
672 45
673 1
        if ($field->isInvalid()) {
674
            foreach ($field->errors() as $error => $parameters) {
675 1
676
                if ($error == 'userDefined') {
677
                    foreach($parameters as $message) {
678
                        $properties['errors'][] = ['error' => $message];
679
                    }
680
                } else {
681 1
682
                    $parameters['field'] = str_replace('_', ' ', $field->name);
683 1
684
                    $message = $this->translate($error, $field);
685 1
686 1
                    foreach($parameters as $key => $value) {
687 1
                        if (is_object($value) && method_exists($value, '__toString')) $value = (string) $value;
688 1
                        if (is_array($value)) $value = implode(', ', $value);
689
                        $message = str_replace('['.$key.']', $value, $message);
690 1
                    }
691
                    $properties['errors'][] = ['error' => $message];
692
                }
693
            }
694
        }
695 45
696
        return $properties;
697
    }
698
699
    /**
700
     * Render the field using templates.
701
     *
702
     * @param  \Helmut\Forms\Field  $field
703
     * @param  array  $properties
704
     * @return string
705 45
     */
706
    public function renderField($field, $properties = null) 
707 45
    {   
708
        if (is_null($properties)) $properties = $this->fieldProperties($field);
709 45
710
        return $this->renderTemplate($field->type, $properties, $field);
711
    }
712
713
    /**
714
     * Render the field using templates.
715
     *
716
     * @param  \Helmut\Forms\Field  $field
717
     * @param  array  $properties
718
     * @return string
719 45
     */
720
    public function renderFieldErrors($field, $properties = null) 
721 45
    {   
722
        if (is_null($properties)) $properties = $this->fieldProperties($field);
723 45
724
        return $this->renderTemplate('errors', $properties, $field);
725
    }   
726
727
    /**
728
     * Render the form using templates.
729
     *
730
     * @param  string  $template
731
     * @return string
732 47
     */
733
    public function render($template = null)
734 47
    {
735
        $this->broadcast('render');
736 47
737
        $this->setValues();
738 47
739
        if ($this->submitted()) $this->validate();
740 47
741
        if ( ! is_null($template)) $this->setTemplate($template);
742 47
743 47
        $properties = [];
744 47
        $properties['id'] = $this->id;
745 47
        $properties['action'] = $this->action;
746 47
        $properties['csrf'] = $this->request->csrf();
747
        $properties['fields'] = [];     
748 47
749
        $renderered_form = $this->renderTemplate('csrf', $this->request->csrf());
750 47
751
        foreach ($this->fields as $field) {
752 45
753
            $field_properties = $this->fieldProperties($field);
754 45
755
            $properties['fields'][] = $field_properties;
756 45
757 45
            $rendered_field = $this->renderField($field, $field_properties);
758
            $rendered_field .= $this->renderFieldErrors($field, $field_properties);
759 45
760
            $field_properties['field'] = $rendered_field;
761 45
762
            $renderered_form .= $this->renderTemplate('field', $field_properties, $field);
763
        }
764 47
765
        $properties['form'] = $renderered_form;
766 47
767
        $renderered_template = $this->renderTemplate('form', $properties);
768 47
769
        return $renderered_template;
770
    }
771
772
    /**
773
     * Render a template.
774
     *
775
     * @param  string  $template
776
     * @param  array  $properties
777
     * @param  \Helmut\Forms\Field  $field
778
     * @return string
779 47
     */
780
    public function renderTemplate($template, $properties = [], $field = null)
781 47
    {
782
        $paths = $this->templatePaths($field);
783 47
784
        $properties['lang'] = $this->translations($field);
785 47
786
        $rendered_template = $this->renderer->render($template, $properties, $paths);
787 47
788
        if (count($this->plugins)) {
789 47
790
            $properties[$template] = $rendered_template;
791
792
            foreach ($this->plugins as $key=>$plugin) {
793
                if ($this->renderer->has($template, $plugin->templatePaths())) {
794
                    $rendered_template = $this->renderer->render($template, $properties, $plugin->templatePaths());
795 47
                    $properties[$template] = $rendered_template;
796
                }
797
            }
798
        }
799
800
        return $rendered_template;
801
    }
802
803
    /**
804
     * Translate a specific key.
805 1
     *
806
     * @param  string  $key
807 1
     * @param  \Helmut\Forms\Field  $field
808
     * @return string
809 1
     */
810 1
    public function translate($key, $field = null) 
811
    {
812
        $translations = $this->translations($field);
813
814
        if (isset($translations[$key])) {
815
            return $translations[$key];
816
        }
817
818
        throw new \Exception('No translation found for '.$key);
819
    }
820
821
    /**
822 47
     * Get translations and cache them if necessary.
823
     *
824 47
     * @param  \Helmut\Forms\Field  $field
825
     * @return array
826 47
     */
827 47
    public function translations($field = null) 
828 47
    {
829
        $lang = $this->lang;
830
831 47
        if ( ! isset($this->translations[$lang])) {
832
            $paths = $this->langPaths();
833 47
            $this->translations[$lang] = $this->loadTranslations($lang, $paths);
834
        }
835 45
836
        $translations = $this->translations[$lang];
837 45
838 45
        if ( ! is_null($field)) {
839
840
            if ( ! isset($this->translations[$field->type][$lang])) {
841 45
842
                if ( ! isset($this->translations[$field->type])) {
843 45
                    $this->translations[$field->type] = [];
844
                }
845
846 45
                $paths = $this->langPaths($field);
847
848
                $paths = array_reverse($paths);
849 47
850
                $this->translations[$field->type][$lang] = $this->loadTranslations($lang, $paths);
851
            }
852
853
            $translations = array_merge($translations, $this->translations[$field->type][$lang]);
854
855
        } 
856
857
        return $translations;
858
    }
859 47
860
    /**
861 47
     * Load the translations from paths.
862
     *
863 47
     * @param  string  $lang
864 47
     * @param  array  $paths
865 47
     * @return array
866 47
     */
867
    public function loadTranslations($lang, $paths) 
868
    {
869
        $translations = [];
870 47
871
        foreach ($paths as $path) {
872
            $file = $path.$lang.'.php';
873
            if (file_exists($file)) {
874
                $translations = array_merge($translations, include($file));
875
            }
876
        }
877
878
        return $translations;
879 134
    }
880
881 134
    /**
882
     * Add a plugin to a form.
883 134
     *
884
     * @param  string  $name
885 134
     * @param  array  $config
886
     * @return \Helmut\Forms\Plugin
887 134
     */
888
    public function addPlugin($name, $config = [])
889 134
    {
890 134
        $class = Str::studly($name);
891 134
892
        $class = '\\Plugins\\'.ucwords($class).'\\'.ucwords($class);
893 134
894
        foreach ($this->namespaces as $namespace) {
895
            
896
            $plugin = $namespace.$class;
897
            
898
            if (class_exists($plugin)) {
899
                $this->plugins[$name] = new $plugin($config);
900
                $this->plugins[$name]->event($this, 'load');
901
902
                return $this->plugins[$name];
903
            }
904 134
        }
905
    }
906 134
907 134
    /**
908
     * Remove a plugin.
909 134
     *
910
     * @param  string  $name
911
     * @return void
912
     */
913
    public function removePlugin($name)
914
    {
915
        if (array_key_exists($name, $this->plugins)) {
916 134
            unset($this->plugins[$name]);
917
        }
918 134
    }
919 134
920
    /**
921 134
     * Get a plugin instance.
922
     *
923
     * @param  string  $name
924
     * @return \Helmut\Forms\Plugin
925
     */
926
    public function getPlugin($name)
927
    {
928
        return $this->plugins[$name];
929
    }
930 134
931
    /**
932 134
     * Remove all plugins.
933 134
     *
934
     * @return void
935 134
     */
936
    public function removeAllPlugins()
937
    {
938
        foreach ($this->plugins as $name => $plugin) {
939
            $this->removePlugin($name);
940
        }
941
    }   
942
943
    /**
944 47
     * Broadcast an event.
945
     *
946 47
     * @param  string  $event
947
     * @param  array  $params
948
     * @return void
949
     */
950
    private function broadcast($event, $params = []) 
951
    {
952
        foreach($this->plugins as $plugin) {
953
            $plugin->event($this, $event, $params);
954
        }
955
    }
956 53
957
    /**
958 53
     * Get all paths to the language files or just to those
959
     * for a specific field. 
960
     *
961
     * @param  \Helmut\Forms\Field  $field
962
     * @return array
963
     */
964
    public function langPaths($field = null) 
965
    {
966
        return $this->paths($field, 'lang');
967
    }
968
969 134
    /**
970
     * Get all paths to template packages or just to the 
971 134
     * packages for a specific field.
972
     *
973 134
     * @param  \Helmut\Forms\Field  $field
974 45
     * @return array
975
     */
976
    public function templatePaths($field = null) 
977 134
    {
978 134
        return $this->paths($field, 'templates/'.$this->template);
979 134
    }
980 134
981
    /**
982
     * Get all autoload paths or just the path 
983 134
     * of a specific resource.
984
     *
985
     * @param  \Helmut\Forms\Field  $field
986
     * @param  string  $append
987
     * @return array
988
     */
989
    public function paths($field = null, $append = null) 
990
    {
991
        $paths = $this->paths;
992 45
993
        if ( ! is_null($field)) {
994 45
            array_unshift($paths, $this->pathForClass($field));
995
        }
996 45
997 45
        if ( ! is_null($append)) {
998
            $paths = array_map(function($path) use($append) {
999 45
                return $path .= ltrim(rtrim($append, '/'), '/').'/';
1000
            }, $paths);
1001
        }
1002
1003
        return array_filter($paths, 'is_dir');
1004
    }
1005
1006
    /**
1007
     * Get autoload path for a class.
1008
     *
1009
     * @param  string|object  $class
1010
     * @return string
1011
     */
1012
    public function pathForClass($class)
1013
    {
1014
        $path = Reflect::getDirectory($class);
1015
1016
        return rtrim($path, '/').'/';
1017
    }
1018
1019
1020
    /**
1021
     * Set the form action.
1022
     *
1023
     * @param  string  $action     
1024
     * @return void
1025
     */
1026
    public function setAction($action)
1027
    {
1028
        $this->action = $action;
1029 1
    }
1030
1031 1
    /**
1032
     * Get the active template package.
1033
     *
1034
     * @return string
1035
     */
1036
    public function getTemplate()
1037
    {
1038
        return $this->template;
1039
    }
1040
1041
    /**
1042
     * Get the request implementation.
1043
     *
1044
     * @return \Helmut\Forms\Request
1045
     */
1046
    public function getRequest()
1047
    {
1048
        return $this->request;
1049 134
    }   
1050
1051 134
    /**
1052 134
     * Get the renderer implementation.
1053
     *
1054
     * @return \Helmut\Forms\Renderer
1055 134
     */
1056
    public function getRenderer()
1057
    {
1058
        return $this->renderer;
1059
    } 
1060
1061
    /**
1062
     * Get all of the plugins
1063
     *
1064
     * @return array
1065
     */
1066
    public function getPlugins()
1067
    {
1068
        return $this->plugins;
1069
    }
1070
1071
    /**
1072
     * Get all of the namespaces
1073
     *
1074
     * @return array
1075
     */
1076 118
    public function getNamespaces()
1077
    {
1078 118
        return $this->namespaces;
1079
    }       
1080 118
1081 118
    /**
1082
     * Requests directly on the object could be trying to
1083
     * create a field so check if type exists.
1084 10
     *
1085
     * @param  string  $method
1086
     * @param  array  $parameters
1087
     * @return mixed
1088
     */
1089
    public function __call($method, $parameters)
1090
    {
1091
        if ( ! method_exists($this, $method))
1092
        {
1093
            if ( $this->typeExists($method)) {
1094
                return $this->addField($method, array_shift($parameters));
1095
            }
1096
        }
1097
    }
1098
1099
    /**
1100
     * Render the form.
1101
     *
1102
     * @return string
1103
     */
1104
    public function __toString()
1105
    {
1106
        return $this->render();
1107
    }   
1108
1109
}
1110