Completed
Pull Request — master (#138)
by Jonathan
03:27 queued 01:57
created

Template::append()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

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