Completed
Pull Request — master (#125)
by Mike
02:39
created

Template::start()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3.1406

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 9
cts 12
cp 0.75
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 9
nc 3
nop 2
crap 3.1406
1
<?php
2
3
namespace League\Plates\Template;
4
5
use League\Plates\Engine;
6
use LogicException;
7
8
/**
9
 * Container which holds template data and provides access to template functions.
10
 */
11
class Template
12
{
13
    /**
14
     * Instance of the template engine.
15
     * @var Engine
16
     */
17
    protected $engine;
18
19
    /**
20
     * The name of the template.
21
     * @var Name
22
     */
23
    protected $name;
24
25
    /**
26
     * The data assigned to the template.
27
     * @var array
28
     */
29
    protected $data = array();
30
31
    /**
32
     * An array of section content.
33
     * @var array
34
     */
35
    protected $sections = array();
36
37
    /**
38
     * The name of the template layout.
39
     * @var string
40
     */
41
    protected $layoutName;
42
43
    /**
44
     * The data assigned to the template layout.
45
     * @var array
46
     */
47
    protected $layoutData;
48
49
    /**
50
     * Create new Template instance.
51
     * @param Engine $engine
52
     * @param string $name
53
     */
54 84
    public function __construct(Engine $engine, $name)
55
    {
56 84
        $this->engine = $engine;
57 84
        $this->name = new Name($engine, $name);
58
59 84
        $this->data($this->engine->getData($name));
60 84
    }
61
62
    /**
63
     * Magic method used to call extension functions.
64
     * @param  string $name
65
     * @param  array  $arguments
66
     * @return mixed
67
     */
68 8
    public function __call($name, $arguments)
69
    {
70 8
        return $this->engine->getFunction($name)->call($this, $arguments);
71
    }
72
73
    /**
74
     * Assign data to template object.
75
     * @param  array $data
76
     * @return null
77
     */
78 84
    public function data(array $data)
79
    {
80 84
        $this->data = array_merge($this->data, $data);
81 84
    }
82
83
    /**
84
     * Check if the template exists.
85
     * @return boolean
86
     */
87 72
    public function exists()
88
    {
89 72
        return $this->name->doesPathExist();
90
    }
91
92
    /**
93
     * Get the template path.
94
     * @return string
95
     */
96 68
    public function path()
97
    {
98 68
        return $this->name->getPath();
99
    }
100
101
    /**
102
     * Render the template and layout.
103
     * @param  array  $data
104
     * @return string
105
     */
106 64
    public function render(array $data = array())
107
    {
108
        try {
109 64
            $this->data($data);
110
111 64
            unset($data);
112
113 64
            extract($this->data);
114
115 64
            ob_start();
116
117 64
            if (!$this->exists()) {
118
                throw new LogicException(
119
                    'The template "' . $this->name->getName() . '" could not be found at "' . $this->path() . '".'
120
                );
121
            }
122
123 64
            include $this->path();
124
125 64
            $content = ob_get_clean();
126
127 64
            if (isset($this->layoutName)) {
128 16
                $layout = $this->engine->make($this->layoutName);
129 16
                $layout->sections = array_merge($this->sections, array('content' => $content));
130 16
                $content = $layout->render($this->layoutData);
131 12
            }
132
133 64
            return $content;
134
        } catch (LogicException $e) {
135
            if (ob_get_length() > 0) {
136
                ob_end_clean();
137
            }
138
139
            throw $e;
140
        }
141
    }
142
143
    /**
144
     * Set the template's layout.
145
     * @param  string $name
146
     * @param  array  $data
147
     * @return null
148
     */
149 16
    protected function layout($name, array $data = array())
150
    {
151 16
        $this->layoutName = $name;
152 16
        $this->layoutData = $data;
153 16
    }
154
155
    /**
156
     * Start a new section block.
157
     * @param  string  $name
158
     * @param  boolean $append
159
     * @return null
160
     */
161 8
    protected function start($name, $append = false)
162
    {
163 8
        if ($name === 'content') {
164
            throw new LogicException(
165
                'The section name "content" is reserved.'
166
            );
167
        }
168
169 8
        $sectionContent = $this->section($name, '');
170 8
        $this->sections[$name] = '';
171
172 8
        ob_start();
173 8
        if ($append) {
174 4
            echo $sectionContent;
175 3
        }
176 8
    }
177
178
    /**
179
     * Stop the current section block.
180
     * @return null
181
     */
182 8
    protected function stop()
183
    {
184 8
        if (empty($this->sections)) {
185
            throw new LogicException(
186
                'You must start a section before you can stop it.'
187
            );
188
        }
189
190 8
        end($this->sections);
191
192 8
        $this->sections[key($this->sections)] = ob_get_clean();
193 8
    }
194
195
    /**
196
     * Returns the content for a section block.
197
     * @param  string      $name    Section name
198
     * @param  string      $default Default section content
199
     * @return string|null
200
     */
201 16
    protected function section($name, $default = null)
202
    {
203 16
        if (!isset($this->sections[$name])) {
204 16
            return $default;
205
        }
206
207 8
        return $this->sections[$name];
208
    }
209
210
    /**
211
     * Fetch a rendered template.
212
     * @param  string $name
213
     * @param  array  $data
214
     * @return string
215
     */
216 4
    protected function fetch($name, array $data = array())
217
    {
218 4
        return $this->engine->render($name, $data);
219
    }
220
221
    /**
222
     * Output a rendered template.
223
     * @param  string $name
224
     * @param  array  $data
225
     * @return null
226
     */
227 4
    protected function insert($name, array $data = array())
228
    {
229 4
        echo $this->engine->render($name, $data);
230 4
    }
231
232
    /**
233
     * Apply multiple functions to variable.
234
     * @param  mixed  $var
235
     * @param  string $functions
236
     * @return mixed
237
     */
238 8
    protected function batch($var, $functions)
239
    {
240 8
        foreach (explode('|', $functions) as $function) {
241 8
            if ($this->engine->doesFunctionExist($function)) {
242 4
                $var = call_user_func(array($this, $function), $var);
243 8
            } elseif (is_callable($function)) {
244 8
                $var = call_user_func($function, $var);
245 6
            } else {
246
                throw new LogicException(
247 2
                    'The batch function could not find the "' . $function . '" function.'
248
                );
249
            }
250 6
        }
251
252 8
        return $var;
253
    }
254
255
    /**
256
     * Escape string.
257
     * @param  string      $string
258
     * @param  null|string $functions
259
     * @return string
260
     */
261 12
    protected function escape($string, $functions = null)
262
    {
263 12
        static $flags;
264
265 12
        if (!isset($flags)) {
266 4
            $flags = ENT_QUOTES | (defined('ENT_SUBSTITUTE') ? ENT_SUBSTITUTE : 0);
267 3
        }
268
269 12
        if ($functions) {
270 4
            $string = $this->batch($string, $functions);
271 3
        }
272
273 12
        return htmlspecialchars($string, $flags, 'UTF-8');
274
    }
275
276
    /**
277
     * Alias to escape function.
278
     * @param  string      $string
279
     * @param  null|string $functions
280
     * @return string
281
     */
282 4
    protected function e($string, $functions = null)
283
    {
284 4
        return $this->escape($string, $functions);
285
    }
286
}
287