Dotclear

source: inc/libs/twig/Template.php @ 0:54703be25dd6

Revision 0:54703be25dd6, 9.5 KB checked in by Dsls <dsls@…>, 14 years ago (diff)

2.3 branch (trunk) first checkin

Line 
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2009 Fabien Potencier
7 * (c) 2009 Armin Ronacher
8 *
9 * For the full copyright and license information, please view the LICENSE
10 * file that was distributed with this source code.
11 */
12
13/**
14 * Default base class for compiled templates.
15 *
16 * @package twig
17 * @author  Fabien Potencier <fabien.potencier@symfony-project.com>
18 */
19abstract class Twig_Template implements Twig_TemplateInterface
20{
21    static protected $cache = array();
22
23    protected $env;
24    protected $blocks;
25
26    /**
27     * Constructor.
28     *
29     * @param Twig_Environment $env A Twig_Environment instance
30     */
31    public function __construct(Twig_Environment $env)
32    {
33        $this->env = $env;
34        $this->blocks = array();
35    }
36
37    /**
38     * Returns the template name.
39     *
40     * @return string The template name
41     */
42    public function getTemplateName()
43    {
44        return null;
45    }
46
47    /**
48     * Returns the Twig environment.
49     *
50     * @return Twig_Environment The Twig environment
51     */
52    public function getEnvironment()
53    {
54        return $this->env;
55    }
56
57    /**
58     * Returns the parent template.
59     *
60     * @return Twig_TemplateInterface|false The parent template or false if there is no parent
61     */
62    public function getParent(array $context)
63    {
64        return false;
65    }
66
67    /**
68     * Displays a parent block.
69     *
70     * @param string $name    The block name to display from the parent
71     * @param array  $context The context
72     * @param array  $blocks  The current set of blocks
73     */
74    public function displayParentBlock($name, array $context, array $blocks = array())
75    {
76        if (false !== $parent = $this->getParent($context)) {
77            $parent->displayBlock($name, $context, $blocks);
78        } else {
79            throw new Twig_Error_Runtime('This template has no parent', -1, $this->getTemplateName());
80        }
81    }
82
83    /**
84     * Displays a block.
85     *
86     * @param string $name    The block name to display
87     * @param array  $context The context
88     * @param array  $blocks  The current set of blocks
89     */
90    public function displayBlock($name, array $context, array $blocks = array())
91    {
92        if (isset($blocks[$name])) {
93            $b = $blocks;
94            unset($b[$name]);
95            call_user_func($blocks[$name], $context, $b);
96        } elseif (isset($this->blocks[$name])) {
97            call_user_func($this->blocks[$name], $context, $blocks);
98        } elseif (false !== $parent = $this->getParent($context)) {
99            $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks));
100        }
101    }
102
103    /**
104     * Renders a parent block.
105     *
106     * @param string $name    The block name to render from the parent
107     * @param array  $context The context
108     * @param array  $blocks  The current set of blocks
109     *
110     * @return string The rendered block
111     */
112    public function renderParentBlock($name, array $context, array $blocks = array())
113    {
114        ob_start();
115        $this->displayParentBlock($name, $context, $blocks);
116
117        return new Twig_Markup(ob_get_clean());
118    }
119
120    /**
121     * Renders a block.
122     *
123     * @param string $name    The block name to render
124     * @param array  $context The context
125     * @param array  $blocks  The current set of blocks
126     *
127     * @return string The rendered block
128     */
129    public function renderBlock($name, array $context, array $blocks = array())
130    {
131        ob_start();
132        $this->displayBlock($name, $context, $blocks);
133
134        return new Twig_Markup(ob_get_clean());
135    }
136
137    /**
138     * Returns whether a block exists or not.
139     *
140     * @param string $name The block name
141     *
142     * @return Boolean true if the block exists, false otherwise
143     */
144    public function hasBlock($name)
145    {
146        return isset($this->blocks[$name]);
147    }
148
149    /**
150     * Returns all block names.
151     *
152     * @return array An array of block names
153     */
154    public function getBlockNames()
155    {
156        return array_keys($this->blocks);
157    }
158
159    /**
160     * Renders the template with the given context and returns it as string.
161     *
162     * @param array $context An array of parameters to pass to the template
163     *
164     * @return string The rendered template
165     */
166    public function render(array $context)
167    {
168        ob_start();
169        try {
170            $this->display($context);
171        } catch (Exception $e) {
172            // the count variable avoids an infinite loop on
173            // some Windows configurations where ob_get_level()
174            // never reaches 0
175            $count = 100;
176            while (ob_get_level() && --$count) {
177                ob_end_clean();
178            }
179
180            throw $e;
181        }
182
183        return ob_get_clean();
184    }
185
186    /**
187     * Returns a variable from the context.
188     *
189     * @param array   $context The context
190     * @param string  $item    The variable to return from the context
191     * @param integer $line    The line where the variable is get
192     *
193     * @param mixed The variable value in the context
194     *
195     * @throws Twig_Error_Runtime if the variable does not exist
196     */
197    protected function getContext($context, $item, $line = -1)
198    {
199        if (!array_key_exists($item, $context)) {
200            throw new Twig_Error_Runtime(sprintf('Variable "%s" does not exist', $item), $line, $this->getTemplateName());
201        }
202
203        return $context[$item];
204    }
205
206    /**
207     * Returns the attribute value for a given array/object.
208     *
209     * @param mixed   $object        The object or array from where to get the item
210     * @param mixed   $item          The item to get from the array or object
211     * @param array   $arguments     An array of arguments to pass if the item is an object method
212     * @param integer $type          The type of attribute (@see Twig_TemplateInterface)
213     * @param Boolean $noStrictCheck Whether to throw an exception if the item does not exist ot not
214     * @param integer $line          The line where the attribute is get
215     */
216    protected function getAttribute($object, $item, array $arguments = array(), $type = Twig_TemplateInterface::ANY_CALL, $noStrictCheck = false, $line = -1)
217    {
218        // array
219        if (Twig_TemplateInterface::METHOD_CALL !== $type) {
220            if ((is_array($object) || is_object($object) && $object instanceof ArrayAccess) && isset($object[$item])) {
221                return $object[$item];
222            }
223
224            if (Twig_TemplateInterface::ARRAY_CALL === $type) {
225                if (!$this->env->isStrictVariables() || $noStrictCheck) {
226                    return null;
227                }
228
229                if (is_object($object)) {
230                    throw new Twig_Error_Runtime(sprintf('Key "%s" in object (with ArrayAccess) of type "%s" does not exist', $item, get_class($object)), $line, $this->getTemplateName());
231                // array
232                } else {
233                    throw new Twig_Error_Runtime(sprintf('Key "%s" for array with keys "%s" does not exist', $item, implode(', ', array_keys($object))), $line, $this->getTemplateName());
234                }
235            }
236        }
237
238        if (!is_object($object)) {
239            if (!$this->env->isStrictVariables() || $noStrictCheck) {
240                return null;
241            }
242            throw new Twig_Error_Runtime(sprintf('Item "%s" for "%s" does not exist', $item, $object), $line, $this->getTemplateName());
243        }
244
245        // get some information about the object
246        $class = get_class($object);
247        if (!isset(self::$cache[$class])) {
248            $r = new ReflectionClass($class);
249            self::$cache[$class] = array('methods' => array(), 'properties' => array());
250            foreach ($r->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
251                self::$cache[$class]['methods'][strtolower($method->getName())] = true;
252            }
253
254            foreach ($r->getProperties(ReflectionProperty::IS_PUBLIC) as $property) {
255                self::$cache[$class]['properties'][$property->getName()] = true;
256            }
257        }
258
259        // object property
260        if (Twig_TemplateInterface::METHOD_CALL !== $type) {
261            if (isset(self::$cache[$class]['properties'][$item]) || isset($object->$item)) {
262                if ($this->env->hasExtension('sandbox')) {
263                    $this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item);
264                }
265
266                return $object->$item;
267            }
268        }
269
270        // object method
271        $lcItem = strtolower($item);
272        if (isset(self::$cache[$class]['methods'][$lcItem])) {
273            $method = $item;
274        } elseif (isset(self::$cache[$class]['methods']['get'.$lcItem])) {
275            $method = 'get'.$item;
276        } elseif (isset(self::$cache[$class]['methods']['is'.$lcItem])) {
277            $method = 'is'.$item;
278        } elseif (isset(self::$cache[$class]['methods']['__call'])) {
279            $method = $item;
280        } else {
281            if (!$this->env->isStrictVariables() || $noStrictCheck) {
282                return null;
283            }
284
285            throw new Twig_Error_Runtime(sprintf('Method "%s" for object "%s" does not exist', $item, get_class($object)), $line, $this->getTemplateName());
286        }
287
288        if ($this->env->hasExtension('sandbox')) {
289            $this->env->getExtension('sandbox')->checkMethodAllowed($object, $method);
290        }
291
292        $ret = call_user_func_array(array($object, $method), $arguments);
293
294        if ($object instanceof Twig_TemplateInterface) {
295            return new Twig_Markup($ret);
296        }
297
298        return $ret;
299    }
300}
Note: See TracBrowser for help on using the repository browser.

Sites map