Completed
Push — master ( 425720...b3a456 )
by Adrian
03:15
created

Builder::__call()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4.0582

Importance

Changes 6
Bugs 1 Features 0
Metric Value
c 6
b 1
f 0
dl 0
loc 16
ccs 11
cts 13
cp 0.8462
rs 9.2
cc 4
eloc 10
nc 8
nop 2
crap 4.0582
1
<?php
2
namespace Sirius\Html;
3
4
class Builder
5
{
6
7
    /**
8
     * A list of configuration parameters that can be used
9
     * by tags, decorators etc when rendering
10
     *
11
     * @var array
12
     */
13
    protected $options = array();
14
15
    /**
16
     * tag-to-class name mappings
17
     *
18
     * @var array
19
     */
20
    protected $tagFactories = array(
21
        'button'      => 'Sirius\Html\Tag\Button',
22
        'checkbox'    => 'Sirius\Html\Tag\Checkbox',
23
        'file'        => 'Sirius\Html\Tag\File',
24
        'hidden'      => 'Sirius\Html\Tag\Hidden',
25
        'img'         => 'Sirius\Html\Tag\Img',
26
        'multiselect' => 'Sirius\Html\Tag\MultiSelect',
27
        'password'    => 'Sirius\Html\Tag\Password',
28
        'radio'       => 'Sirius\Html\Tag\Radio',
29
        'select'      => 'Sirius\Html\Tag\Select',
30
        'text'        => 'Sirius\Html\Tag\Text',
31
        'textarea'    => 'Sirius\Html\Tag\Textarea'
32
    );
33
34
    /**
35
     * @param array $options
36
     */
37 8
    public function __construct($options = array())
38
    {
39 8
        $this->options = $options;
40 8
    }
41
42
    /**
43
     * Sets a value of an option
44
     *
45
     * @param $name
46
     * @param $value
47
     */
48 2
    public function setOption($name, $value)
49
    {
50 2
        $this->options[$name] = $value;
51 2
    }
52
53
    /**
54
     * Get a configuration option
55
     *
56
     * @param $name
57
     *
58
     * @return null
59
     */
60 2
    public function getOption($name)
61
    {
62 2
        return isset($this->options[$name]) ? $this->options[$name] : null;
63
    }
64
65
    /**
66
     * Clones the instance and applies new set of options
67
     *
68
     * @param $options
69
     *
70
     * @return Builder
71
     */
72 1
    public function with($options)
73
    {
74 1
        $clone = clone $this;
75 1
        foreach ($options as $name => $value) {
76 1
            $clone->setOption($name, $value);
77 1
        }
78
79 1
        return $clone;
80
    }
81
82
    /**
83
     * Add an element factory (class or callback)
84
     *
85
     * @param string $name
86
     * @param mixed $classOrCallback
87
     *
88
     * @return self
89
     */
90 8
    public function registerTag($name, $classOrCallback)
91
    {
92 8
        $this->tagFactories[$name] = $classOrCallback;
93
94 8
        return $this;
95
    }
96
97
    /**
98
     * Make an HTML tag with a specific tag name (div, p, section etc)
99
     *
100
     * @param string $tag
101
     * @param mixed $props
102
     * @param mixed $content
103
     *
104
     * @throws \InvalidArgumentException
105
     * @return Tag
106
     */
107 6
    public function make($tag, $props = null, $content = null)
108
    {
109 6
        if (! isset($this->tagFactories[$tag])) {
110 2
            return Tag::create($tag, $props, $content, $this);
111
        }
112
113 4
        $constructor = $this->tagFactories[$tag];
114
115 4
        if (is_callable($constructor)) {
116
            /* @var $tag Tag */
117 3
            $tag = call_user_func($constructor, $props, $content, $this);
118 4
        } elseif (is_string($constructor) && class_exists($constructor)) {
119
            /* @var $tag Tag */
120 1
            $tag = new $constructor($props, $content, $this);
121 1
        }
122
123 4
        if (! $tag || ! $tag instanceof Tag) {
124 1
            throw  new \InvalidArgumentException(sprintf(
125 1
                'The constructor for the `%s` tag did not generate a Tag object',
126
                $tag
127 1
            ));
128
        }
129
130 3
        return $tag;
131
132
    }
133
134
    /**
135
     * Magic method for creating HTML tags
136
     *
137
     * @example
138
     * $builder->h1(null, 'Heading 1'); // <h1>Heading 1</h1>
139
     * $builder->article(['class' => 'post-body'], 'Article body');
140
     * // outputs: '<article class='post-body'>Article body</article>
141
     *
142
     * $builder->someTag(); // <some-tag></some-tag>
143
     *
144
     * @param string $method
145
     * @param array $args
146
     *
147
     * @return Tag
148
     */
149 2
    public function __call($method, $args)
150
    {
151 2
        $method = preg_replace('/([A-Z]+)/', '-\1', $method);
152 2
        $method = strtolower($method);
153 2
        if (! isset($args[0])) {
154
            $args[0] = array();
155
        }
156 2
        if (! isset($args[1])) {
157 1
            $args[1] = null;
158 1
        }
159 2
        if (! isset($args[2])) {
160 2
            $args[2] = null;
161 2
        }
162
163 2
        return $this->make($method, $args[0], $args[1]);
164
    }
165
}
166