Completed
Push — add_append_feature ( d2d302...e9044a )
by Jonathan
01:51
created

Template::path()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace League\Plates\Template;
4
5
use Exception;
6
use League\Plates\Engine;
7
use LogicException;
8
use Throwable;
9
10
/**
11
 * Container which holds template data and provides access to template functions.
12
 */
13
class Template
14
{
15
    /**
16
     * Instance of the template engine.
17
     * @var Engine
18
     */
19
    protected $engine;
20
21
    /**
22
     * The name of the template.
23
     * @var Name
24
     */
25
    protected $name;
26
27
    /**
28
     * The data assigned to the template.
29
     * @var array
30
     */
31
    protected $data = array();
32
33
    /**
34
     * An array of section content.
35
     * @var array
36
     */
37
    protected $sections = array();
38
39
    /**
40
     * The name of the section currently being rendered.
41
     * @var string
42
     */
43
    protected $sectionName;
44
45
    /**
46
     * Whether the section should be appended or not.
47
     * @var boolean
48
     */
49
    protected $appendSection;
50
51
    /**
52
     * The name of the template layout.
53
     * @var string
54
     */
55
    protected $layoutName;
56
57
    /**
58
     * The data assigned to the template layout.
59
     * @var array
60
     */
61
    protected $layoutData;
62
63
    /**
64
     * Create new Template instance.
65
     * @param Engine $engine
66
     * @param string $name
67
     */
68 124
    public function __construct(Engine $engine, $name)
69
    {
70 124
        $this->engine = $engine;
71 124
        $this->name = new Name($engine, $name);
72
73 124
        $this->data($this->engine->getData($name));
74 124
    }
75
76
    /**
77
     * Magic method used to call extension functions.
78
     * @param  string $name
79
     * @param  array  $arguments
80
     * @return mixed
81
     */
82 8
    public function __call($name, $arguments)
83
    {
84 8
        return $this->engine->getFunction($name)->call($this, $arguments);
85
    }
86
87
    /**
88
     * Alias for render() method.
89
     * @throws \Throwable
90
     * @throws \Exception
91
     * @return string
92
     */
93 4
    public function __toString()
94
    {
95 4
        return $this->render();
96
    }
97
98
    /**
99
     * Assign or get template data.
100
     * @param  array $data
101
     * @return mixed
102
     */
103 124
    public function data(array $data = null)
104
    {
105 124
        if (is_null($data)) {
106 4
            return $this->data;
107
        }
108
109 124
        $this->data = array_merge($this->data, $data);
110 124
    }
111
112
    /**
113
     * Check if the template exists.
114
     * @return boolean
115
     */
116 108
    public function exists()
117
    {
118 108
        return $this->name->doesPathExist();
119
    }
120
121
    /**
122
     * Get the template path.
123
     * @return string
124
     */
125 104
    public function path()
126
    {
127 104
        return $this->name->getPath();
128
    }
129
130
    /**
131
     * Render the template and layout.
132
     * @param  array  $data
133
     * @throws \Throwable
134
     * @throws \Exception
135
     * @return string
136
     */
137 100
    public function render(array $data = array())
138
    {
139 100
        $this->data($data);
140 100
        unset($data);
141 100
        extract($this->data);
142
143 100
        if (!$this->exists()) {
144 4
            throw new LogicException(
145 4
                'The template "' . $this->name->getName() . '" could not be found at "' . $this->path() . '".'
146 3
            );
147
        }
148
149
        try {
150 96
            $level = ob_get_level();
151 96
            ob_start();
152
153 96
            include $this->path();
154
155 76
            $content = ob_get_clean();
156
157 76
            if (isset($this->layoutName)) {
158 24
                $layout = $this->engine->make($this->layoutName);
159 24
                $layout->sections = array_merge($this->sections, array('content' => $content));
160 24
                $content = $layout->render($this->layoutData);
161 18
            }
162
163 76
            return $content;
164 20
        } catch (Throwable $e) {
0 ignored issues
show
Bug introduced by
The class Throwable does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
165 5
            while (ob_get_level() > $level) {
166 5
                ob_end_clean();
167
            }
168
169 5
            throw $e;
170 15
        } catch (Exception $e) {
171 15
            while (ob_get_level() > $level) {
172 15
                ob_end_clean();
173 15
            }
174
175 15
            throw $e;
176
        }
177
    }
178
179
    /**
180
     * Set the template's layout.
181
     * @param  string $name
182
     * @param  array  $data
183
     * @return null
184
     */
185 24
    public function layout($name, array $data = array())
186
    {
187 24
        $this->layoutName = $name;
188 24
        $this->layoutData = $data;
189 24
    }
190
191
    /**
192
     * Start a new section block.
193
     * @param  string  $name
194
     * @param  boolean $name
195
     * @return null
196
     */
197 24
    public function start($name)
198
    {
199 24
        if ($name === 'content') {
200 4
            throw new LogicException(
201 1
                'The section name "content" is reserved.'
202 3
            );
203
        }
204
205 20
        if ($this->sectionName) {
206 4
            throw new LogicException('You cannot nest sections within other sections.');
207
        }
208
209 20
        $this->sectionName = $name;
210
211 20
        ob_start();
212 20
    }
213
214
    /**
215
     * Start a new append section block.
216
     * @param  string $name
217
     * @return null
218
     */
219 8
    public function push($name)
220
    {
221 8
        $this->appendSection = true;
222
223 8
        $this->start($name);
224 8
    }
225
226
    /**
227
     * Stop the current section block.
228
     * @return null
229
     */
230 20
    public function stop()
231
    {
232 20
        if (is_null($this->sectionName)) {
233 4
            throw new LogicException(
234 1
                'You must start a section before you can stop it.'
235 3
            );
236
        }
237
238 16
        if (!isset($this->sections[$this->sectionName])) {
239 16
            $this->sections[$this->sectionName] = '';
240 12
        }
241
242 16
        $this->sections[$this->sectionName] = $this->appendSection ? $this->sections[$this->sectionName] . ob_get_clean() : ob_get_clean();
243 16
        $this->sectionName = null;
244 16
        $this->appendSection = false;
245 16
    }
246
247
    /**
248
     * Alias of stop().
249
     * @return null
250
     */
251 8
    public function end()
252
    {
253 8
        $this->stop();
254 8
    }
255
256
    /**
257
     * Returns the content for a section block.
258
     * @param  string      $name    Section name
259
     * @param  string      $default Default section content
260
     * @return string|null
261
     */
262 24
    public function section($name, $default = null)
263
    {
264 24
        if (!isset($this->sections[$name])) {
265 8
            return $default;
266
        }
267
268 16
        return $this->sections[$name];
269
    }
270
271
    /**
272
     * Fetch a rendered template.
273
     * @param  string $name
274
     * @param  array  $data
275
     * @return string
276
     */
277 4
    public function fetch($name, array $data = array())
278
    {
279 4
        return $this->engine->render($name, $data);
280
    }
281
282
    /**
283
     * Output a rendered template.
284
     * @param  string $name
285
     * @param  array  $data
286
     * @return null
287
     */
288 4
    public function insert($name, array $data = array())
289
    {
290 4
        echo $this->engine->render($name, $data);
291 4
    }
292
293
    /**
294
     * Apply multiple functions to variable.
295
     * @param  mixed  $var
296
     * @param  string $functions
297
     * @return mixed
298
     */
299 12
    public function batch($var, $functions)
300
    {
301 12
        foreach (explode('|', $functions) as $function) {
302 12
            if ($this->engine->doesFunctionExist($function)) {
303 4
                $var = call_user_func(array($this, $function), $var);
304 12
            } elseif (is_callable($function)) {
305 8
                $var = call_user_func($function, $var);
306 6
            } else {
307 4
                throw new LogicException(
308 6
                    'The batch function could not find the "' . $function . '" function.'
309 3
                );
310
            }
311 6
        }
312
313 8
        return $var;
314
    }
315
316
    /**
317
     * Escape string.
318
     * @param  string      $string
319
     * @param  null|string $functions
320
     * @return string
321
     */
322 12
    public function escape($string, $functions = null)
323
    {
324 12
        static $flags;
325
326 12
        if (!isset($flags)) {
327 4
            $flags = ENT_QUOTES | (defined('ENT_SUBSTITUTE') ? ENT_SUBSTITUTE : 0);
328 3
        }
329
330 12
        if ($functions) {
331 4
            $string = $this->batch($string, $functions);
332 3
        }
333
334 12
        return htmlspecialchars($string, $flags, 'UTF-8');
335
    }
336
337
    /**
338
     * Alias to escape function.
339
     * @param  string      $string
340
     * @param  null|string $functions
341
     * @return string
342
     */
343 4
    public function e($string, $functions = null)
344
    {
345 4
        return $this->escape($string, $functions);
346
    }
347
}
348