Completed
Push — master ( 5874ba...b1684b )
by Jonathan
9s
created

Template::escape()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 9
cts 9
cp 1
rs 9.2
c 0
b 0
f 0
cc 4
eloc 7
nc 6
nop 2
crap 4
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 2
            );
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 12
            }
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 10
            while (ob_get_level() > $level) {
166 10
                ob_end_clean();
167
            }
168
169 10
            throw $e;
170 10
        } catch (Exception $e) {
171 10
            while (ob_get_level() > $level) {
172 10
                ob_end_clean();
173 10
            }
174
175 10
            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
     * @return null
195
     */
196 24
    public function start($name)
197
    {
198 24
        if ($name === 'content') {
199 4
            throw new LogicException(
200 2
                'The section name "content" is reserved.'
201 2
            );
202
        }
203
204 20
        if ($this->sectionName) {
205 4
            throw new LogicException('You cannot nest sections within other sections.');
206
        }
207
208 20
        $this->sectionName = $name;
209
210 20
        ob_start();
211 20
    }
212
213
    /**
214
     * Start a new append section block.
215
     * @param  string $name
216
     * @return null
217
     */
218 8
    public function push($name)
219
    {
220 8
        $this->appendSection = true;
221
222 8
        $this->start($name);
223 8
    }
224
225
    /**
226
     * Stop the current section block.
227
     * @return null
228
     */
229 20
    public function stop()
230
    {
231 20
        if (is_null($this->sectionName)) {
232 4
            throw new LogicException(
233 2
                'You must start a section before you can stop it.'
234 2
            );
235
        }
236
237 16
        if (!isset($this->sections[$this->sectionName])) {
238 16
            $this->sections[$this->sectionName] = '';
239 8
        }
240
241 16
        $this->sections[$this->sectionName] = $this->appendSection ? $this->sections[$this->sectionName] . ob_get_clean() : ob_get_clean();
242 16
        $this->sectionName = null;
243 16
        $this->appendSection = false;
244 16
    }
245
246
    /**
247
     * Alias of stop().
248
     * @return null
249
     */
250 8
    public function end()
251
    {
252 8
        $this->stop();
253 8
    }
254
255
    /**
256
     * Returns the content for a section block.
257
     * @param  string      $name    Section name
258
     * @param  string      $default Default section content
259
     * @return string|null
260
     */
261 24
    public function section($name, $default = null)
262
    {
263 24
        if (!isset($this->sections[$name])) {
264 8
            return $default;
265
        }
266
267 16
        return $this->sections[$name];
268
    }
269
270
    /**
271
     * Fetch a rendered template.
272
     * @param  string $name
273
     * @param  array  $data
274
     * @return string
275
     */
276 4
    public function fetch($name, array $data = array())
277
    {
278 4
        return $this->engine->render($name, $data);
279
    }
280
281
    /**
282
     * Output a rendered template.
283
     * @param  string $name
284
     * @param  array  $data
285
     * @return null
286
     */
287 4
    public function insert($name, array $data = array())
288
    {
289 4
        echo $this->engine->render($name, $data);
290 4
    }
291
292
    /**
293
     * Apply multiple functions to variable.
294
     * @param  mixed  $var
295
     * @param  string $functions
296
     * @return mixed
297
     */
298 12
    public function batch($var, $functions)
299
    {
300 12
        foreach (explode('|', $functions) as $function) {
301 12
            if ($this->engine->doesFunctionExist($function)) {
302 4
                $var = call_user_func(array($this, $function), $var);
303 12
            } elseif (is_callable($function)) {
304 8
                $var = call_user_func($function, $var);
305 4
            } else {
306 4
                throw new LogicException(
307 8
                    'The batch function could not find the "' . $function . '" function.'
308 2
                );
309
            }
310 4
        }
311
312 8
        return $var;
313
    }
314
315
    /**
316
     * Escape string.
317
     * @param  string      $string
318
     * @param  null|string $functions
319
     * @return string
320
     */
321 12
    public function escape($string, $functions = null)
322
    {
323 12
        static $flags;
324
325 12
        if (!isset($flags)) {
326 4
            $flags = ENT_QUOTES | (defined('ENT_SUBSTITUTE') ? ENT_SUBSTITUTE : 0);
327 2
        }
328
329 12
        if ($functions) {
330 4
            $string = $this->batch($string, $functions);
331 2
        }
332
333 12
        return htmlspecialchars($string, $flags, 'UTF-8');
334
    }
335
336
    /**
337
     * Alias to escape function.
338
     * @param  string      $string
339
     * @param  null|string $functions
340
     * @return string
341
     */
342 4
    public function e($string, $functions = null)
343
    {
344 4
        return $this->escape($string, $functions);
345
    }
346
}
347