Yaffs site version 1.1
[yaffs-website] / vendor / twig / twig / lib / Twig / NodeVisitor / SafeAnalysis.php
1 <?php
2
3 /*
4  * This file is part of Twig.
5  *
6  * (c) Fabien Potencier
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 /**
13  * @final
14  */
15 class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor
16 {
17     protected $data = array();
18     protected $safeVars = array();
19
20     public function setSafeVars($safeVars)
21     {
22         $this->safeVars = $safeVars;
23     }
24
25     public function getSafe(Twig_NodeInterface $node)
26     {
27         $hash = spl_object_hash($node);
28         if (!isset($this->data[$hash])) {
29             return;
30         }
31
32         foreach ($this->data[$hash] as $bucket) {
33             if ($bucket['key'] !== $node) {
34                 continue;
35             }
36
37             if (in_array('html_attr', $bucket['value'])) {
38                 $bucket['value'][] = 'html';
39             }
40
41             return $bucket['value'];
42         }
43     }
44
45     protected function setSafe(Twig_NodeInterface $node, array $safe)
46     {
47         $hash = spl_object_hash($node);
48         if (isset($this->data[$hash])) {
49             foreach ($this->data[$hash] as &$bucket) {
50                 if ($bucket['key'] === $node) {
51                     $bucket['value'] = $safe;
52
53                     return;
54                 }
55             }
56         }
57         $this->data[$hash][] = array(
58             'key' => $node,
59             'value' => $safe,
60         );
61     }
62
63     protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
64     {
65         return $node;
66     }
67
68     protected function doLeaveNode(Twig_Node $node, Twig_Environment $env)
69     {
70         if ($node instanceof Twig_Node_Expression_Constant) {
71             // constants are marked safe for all
72             $this->setSafe($node, array('all'));
73         } elseif ($node instanceof Twig_Node_Expression_BlockReference) {
74             // blocks are safe by definition
75             $this->setSafe($node, array('all'));
76         } elseif ($node instanceof Twig_Node_Expression_Parent) {
77             // parent block is safe by definition
78             $this->setSafe($node, array('all'));
79         } elseif ($node instanceof Twig_Node_Expression_Conditional) {
80             // intersect safeness of both operands
81             $safe = $this->intersectSafe($this->getSafe($node->getNode('expr2')), $this->getSafe($node->getNode('expr3')));
82             $this->setSafe($node, $safe);
83         } elseif ($node instanceof Twig_Node_Expression_Filter) {
84             // filter expression is safe when the filter is safe
85             $name = $node->getNode('filter')->getAttribute('value');
86             $args = $node->getNode('arguments');
87             if (false !== $filter = $env->getFilter($name)) {
88                 $safe = $filter->getSafe($args);
89                 if (null === $safe) {
90                     $safe = $this->intersectSafe($this->getSafe($node->getNode('node')), $filter->getPreservesSafety());
91                 }
92                 $this->setSafe($node, $safe);
93             } else {
94                 $this->setSafe($node, array());
95             }
96         } elseif ($node instanceof Twig_Node_Expression_Function) {
97             // function expression is safe when the function is safe
98             $name = $node->getAttribute('name');
99             $args = $node->getNode('arguments');
100             $function = $env->getFunction($name);
101             if (false !== $function) {
102                 $this->setSafe($node, $function->getSafe($args));
103             } else {
104                 $this->setSafe($node, array());
105             }
106         } elseif ($node instanceof Twig_Node_Expression_MethodCall) {
107             if ($node->getAttribute('safe')) {
108                 $this->setSafe($node, array('all'));
109             } else {
110                 $this->setSafe($node, array());
111             }
112         } elseif ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name) {
113             $name = $node->getNode('node')->getAttribute('name');
114             // attributes on template instances are safe
115             if ('_self' == $name || in_array($name, $this->safeVars)) {
116                 $this->setSafe($node, array('all'));
117             } else {
118                 $this->setSafe($node, array());
119             }
120         } else {
121             $this->setSafe($node, array());
122         }
123
124         return $node;
125     }
126
127     protected function intersectSafe(array $a = null, array $b = null)
128     {
129         if (null === $a || null === $b) {
130             return array();
131         }
132
133         if (in_array('all', $a)) {
134             return $b;
135         }
136
137         if (in_array('all', $b)) {
138             return $a;
139         }
140
141         return array_intersect($a, $b);
142     }
143
144     public function getPriority()
145     {
146         return 0;
147     }
148 }
149
150 class_alias('Twig_NodeVisitor_SafeAnalysis', 'Twig\NodeVisitor\SafeAnalysisNodeVisitor', false);