Completed
Push — v3 ( 00116a...976d1a )
by
unknown
27:27 queued 12:33
created

Template::unshift()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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