Completed
Pull Request — v3 (#246)
by
unknown
01:40
created

Template::e()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
crap 2
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
    const SECTION_MODE_REWRITE = 1;
17
    const SECTION_MODE_PREPEND = 2;
18
    const SECTION_MODE_APPEND = 3;
19
20
    /**
21
     * Instance of the template engine.
22
     * @var Engine
23
     */
24
    protected $engine;
25
26
    /**
27
     * The name of the template.
28
     * @var Name
29
     */
30
    protected $name;
31
32
    /**
33
     * The data assigned to the template.
34
     * @var array
35
     */
36
    protected $data = array();
37
38
    /**
39
     * An array of section content.
40
     * @var array
41
     */
42
    protected $sections = array();
43
44
    /**
45
     * The name of the section currently being rendered.
46
     * @var string
47
     */
48
    protected $sectionName;
49
50
    /**
51
     * Whether the section should be appended or not.
52
     * @deprecated stayed for backward compatibility, use $sectionMode instead
53
     * @var boolean
54
     */
55
    protected $appendSection;
56
57
    /**
58
     * The name of the template layout.
59
     * @var string
60
     */
61
    protected $layoutName;
62
63
    /**
64
     * The data assigned to the template layout.
65
     * @var array
66
     */
67
    protected $layoutData;
68 62
69
    /**
70 62
     * Set section content mode: rewrite/append/prepend
71 62
     * @var int
72
     */
73 62
    protected $sectionMode = self::SECTION_MODE_REWRITE;
74 62
75
    /**
76
     * Create new Template instance.
77
     * @param Engine $engine
78
     * @param string $name
79
     */
80
    public function __construct(Engine $engine, $name)
81
    {
82 4
        $this->engine = $engine;
83
        $this->name = new Name($engine, $name);
84 4
85
        $this->data($this->engine->getData($name));
86
    }
87
88
    /**
89
     * Magic method used to call extension functions.
90
     * @param  string $name
91
     * @param  array  $arguments
92
     * @return mixed
93 2
     */
94
    public function __call($name, $arguments)
95 2
    {
96
        return $this->engine->getFunction($name)->call($this, $arguments);
97
    }
98
99
    /**
100
     * Alias for render() method.
101
     * @throws \Throwable
102
     * @throws \Exception
103 62
     * @return string
104
     */
105 62
    public function __toString()
106 2
    {
107
        return $this->render();
108
    }
109 62
110 62
    /**
111
     * Assign or get template data.
112
     * @param  array $data
113
     * @return mixed
114
     */
115
    public function data(array $data = null)
116 54
    {
117
        if (is_null($data)) {
118 54
            return $this->data;
119
        }
120
121
        $this->data = array_merge($this->data, $data);
122
    }
123
124
    /**
125 52
     * Check if the template exists.
126
     * @return boolean
127 52
     */
128
    public function exists()
129
    {
130
        return $this->name->doesPathExist();
131
    }
132
133
    /**
134
     * Get the template path.
135
     * @return string
136
     */
137 50
    public function path()
138
    {
139 50
        return $this->name->getPath();
140 50
    }
141 50
142
    /**
143 50
     * Render the template and layout.
144 2
     * @param  array  $data
145 2
     * @throws \Throwable
146 2
     * @throws \Exception
147
     * @return string
148
     */
149
    public function render(array $data = array())
150 48
    {
151 48
        $this->data($data);
152
        unset($data);
153 48
        extract($this->data);
154
155 38
        if (!$this->exists()) {
156
            throw new LogicException(
157 38
                'The template "' . $this->name->getName() . '" could not be found at "' . $this->path() . '".'
158 12
            );
159 12
        }
160 12
161 12
        try {
162
            $level = ob_get_level();
163 38
            ob_start();
164 10
165
            include $this->path();
166
167
            $content = ob_get_clean();
168
169
            if (isset($this->layoutName)) {
170 10
                $layout = $this->engine->make($this->layoutName);
171 10
                $layout->sections = array_merge($this->sections, array('content' => $content));
172 10
                $content = $layout->render($this->layoutData);
173 10
            }
174
175 10
            return $content;
176
        } 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...
177
            while (ob_get_level() > $level) {
178
                ob_end_clean();
179
            }
180
181
            throw $e;
182
        } catch (Exception $e) {
183
            while (ob_get_level() > $level) {
184
                ob_end_clean();
185 12
            }
186
187 12
            throw $e;
188 12
        }
189 12
    }
190
191
    /**
192
     * Set the template's layout.
193
     * @param  string $name
194
     * @param  array  $data
195
     * @return null
196 12
     */
197
    public function layout($name, array $data = array())
198 12
    {
199 2
        $this->layoutName = $name;
200
        $this->layoutData = $data;
201 2
    }
202
203
    /**
204 10
     * Start a new section block.
205 2
     * @param  string  $name
206
     * @return null
207
     */
208 10
    public function start($name)
209
    {
210 10
        if ($name === 'content') {
211 10
            throw new LogicException(
212
                'The section name "content" is reserved.'
213
            );
214
        }
215
216
        if ($this->sectionName) {
217
            throw new LogicException('You cannot nest sections within other sections.');
218 4
        }
219
220 4
        $this->sectionName = $name;
221
222 4
        ob_start();
223 4
    }
224
225
    /**
226
     * Start a new section block in APPEND mode.
227
     * @param  string $name
228
     * @return null
229 10
     */
230
    public function push($name)
231 10
    {
232 2
        $this->appendSection = true; // for backward compatibility
0 ignored issues
show
Deprecated Code introduced by
The property League\Plates\Template\Template::$appendSection has been deprecated with message: stayed for backward compatibility, use $sectionMode instead

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
233
        $this->sectionMode = self::SECTION_MODE_APPEND;
234 2
        $this->start($name);
235
    }
236
237 8
    /**
238 8
     * Start a new section block in PREPEND mode.
239 8
     * @param  string $name
240
     * @return null
241 8
     */
242 8
    public function unshift($name)
243 8
    {
244 8
        $this->appendSection = false; // for backward compatibility
0 ignored issues
show
Deprecated Code introduced by
The property League\Plates\Template\Template::$appendSection has been deprecated with message: stayed for backward compatibility, use $sectionMode instead

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
245
        $this->sectionMode = self::SECTION_MODE_PREPEND;
246
        $this->start($name);
247
    }
248
249
    /**
250 4
     * Stop the current section block.
251
     * @return null
252 4
     */
253 4
    public function stop()
254
    {
255
        if (is_null($this->sectionName)) {
256
            throw new LogicException(
257
                'You must start a section before you can stop it.'
258
            );
259
        }
260
261 12
        if (!isset($this->sections[$this->sectionName])) {
262
            $this->sections[$this->sectionName] = '';
263 12
        }
264 4
265
        switch ($this->sectionMode) {
266
267 8
            case self::SECTION_MODE_REWRITE:
268
                $this->sections[$this->sectionName] = ob_get_clean();
269
                break;
270
271
            case self::SECTION_MODE_APPEND:
272
                $this->sections[$this->sectionName] .= ob_get_clean();
273
                break;
274
275
            case self::SECTION_MODE_PREPEND:
276 2
                $this->sections[$this->sectionName] = ob_get_clean().$this->sections[$this->sectionName];
277
                break;
278 2
279
        }
280
        $this->sectionName = null;
281
        $this->sectionMode = self::SECTION_MODE_REWRITE;
282
        $this->appendSection = false; // for backward compatibility
0 ignored issues
show
Deprecated Code introduced by
The property League\Plates\Template\Template::$appendSection has been deprecated with message: stayed for backward compatibility, use $sectionMode instead

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
283
    }
284
285
    /**
286
     * Alias of stop().
287 2
     * @return null
288
     */
289 2
    public function end()
290 2
    {
291
        $this->stop();
292
    }
293
294
    /**
295
     * Returns the content for a section block.
296
     * @param  string      $name    Section name
297
     * @param  string      $default Default section content
298 6
     * @return string|null
299
     */
300 6
    public function section($name, $default = null)
301 6
    {
302 2
        if (!isset($this->sections[$name])) {
303 6
            return $default;
304 4
        }
305 4
306 2
        return $this->sections[$name];
307 2
    }
308 2
309
    /**
310 4
     * Fetch a rendered template.
311
     * @param  string $name
312 4
     * @param  array  $data
313
     * @return string
314
     */
315
    public function fetch($name, array $data = array())
316
    {
317
        return $this->engine->render($name, $data);
318
    }
319
320
    /**
321 6
     * Output a rendered template.
322
     * @param  string $name
323 6
     * @param  array  $data
324
     * @return null
325 6
     */
326 2
    public function insert($name, array $data = array())
327 2
    {
328
        echo $this->engine->render($name, $data);
329 6
    }
330 2
331 2
    /**
332
     * Apply multiple functions to variable.
333 6
     * @param  mixed  $var
334
     * @param  string $functions
335
     * @return mixed
336
     */
337
    public function batch($var, $functions)
338
    {
339
        foreach (explode('|', $functions) as $function) {
340
            if ($this->engine->doesFunctionExist($function)) {
341
                $var = call_user_func(array($this, $function), $var);
342 2
            } elseif (is_callable($function)) {
343
                $var = call_user_func($function, $var);
344 2
            } else {
345
                throw new LogicException(
346
                    'The batch function could not find the "' . $function . '" function.'
347
                );
348
            }
349
        }
350
351
        return $var;
352
    }
353
354
    /**
355
     * Escape string.
356
     * @param  string      $string
357
     * @param  null|string $functions
358
     * @return string
359
     */
360
    public function escape($string, $functions = null)
361
    {
362
        static $flags;
363
364
        if (!isset($flags)) {
365
            $flags = ENT_QUOTES | (defined('ENT_SUBSTITUTE') ? ENT_SUBSTITUTE : 0);
366
        }
367
368
        if ($functions) {
369
            $string = $this->batch($string, $functions);
370
        }
371
372
        return htmlspecialchars($string, $flags, 'UTF-8');
373
    }
374
375
    /**
376
     * Alias to escape function.
377
     * @param  string      $string
378
     * @param  null|string $functions
379
     * @return string
380
     */
381
    public function e($string, $functions = null)
382
    {
383
        return $this->escape($string, $functions);
384
    }
385
}
386