3 class Twig_NodeVisitor_SafeAnalysis
implements Twig_NodeVisitorInterface
5 protected $data = array();
6 protected $safeVars = array();
8 public function setSafeVars($safeVars)
10 $this->safeVars
= $safeVars;
13 public function getSafe(Twig_NodeInterface
$node)
15 $hash = spl_object_hash($node);
16 if (isset($this->data
[$hash])) {
17 foreach ($this->data
[$hash] as $bucket) {
18 if ($bucket['key'] === $node) {
19 return $bucket['value'];
25 protected function setSafe(Twig_NodeInterface
$node, array $safe)
27 $hash = spl_object_hash($node);
28 if (isset($this->data
[$hash])) {
29 foreach ($this->data
[$hash] as &$bucket) {
30 if ($bucket['key'] === $node) {
31 $bucket['value'] = $safe;
37 $this->data
[$hash][] = array(
43 public function enterNode(Twig_NodeInterface
$node, Twig_Environment
$env)
48 public function leaveNode(Twig_NodeInterface
$node, Twig_Environment
$env)
50 if ($node instanceof Twig_Node_Expression_Constant
) {
51 // constants are marked safe for all
52 $this->setSafe($node, array('all'));
53 } elseif ($node instanceof Twig_Node_Expression_BlockReference
) {
54 // blocks are safe by definition
55 $this->setSafe($node, array('all'));
56 } elseif ($node instanceof Twig_Node_Expression_Parent
) {
57 // parent block is safe by definition
58 $this->setSafe($node, array('all'));
59 } elseif ($node instanceof Twig_Node_Expression_Conditional
) {
60 // intersect safeness of both operands
61 $safe = $this->intersectSafe($this->getSafe($node->getNode('expr2')), $this->getSafe($node->getNode('expr3')));
62 $this->setSafe($node, $safe);
63 } elseif ($node instanceof Twig_Node_Expression_Filter
) {
64 // filter expression is safe when the filter is safe
65 $name = $node->getNode('filter')->getAttribute('value');
66 $args = $node->getNode('arguments');
67 if (false !== $filter = $env->getFilter($name)) {
68 $safe = $filter->getSafe($args);
70 $safe = $this->intersectSafe($this->getSafe($node->getNode('node')), $filter->getPreservesSafety());
72 $this->setSafe($node, $safe);
74 $this->setSafe($node, array());
76 } elseif ($node instanceof Twig_Node_Expression_Function
) {
77 // function expression is safe when the function is safe
78 $name = $node->getAttribute('name');
79 $args = $node->getNode('arguments');
80 $function = $env->getFunction($name);
81 if (false !== $function) {
82 $this->setSafe($node, $function->getSafe($args));
84 $this->setSafe($node, array());
86 } elseif ($node instanceof Twig_Node_Expression_MethodCall
) {
87 if ($node->getAttribute('safe')) {
88 $this->setSafe($node, array('all'));
90 $this->setSafe($node, array());
92 } elseif ($node instanceof Twig_Node_Expression_GetAttr
&& $node->getNode('node') instanceof Twig_Node_Expression_Name
) {
93 $name = $node->getNode('node')->getAttribute('name');
94 // attributes on template instances are safe
95 if ('_self' == $name || in_array($name, $this->safeVars
)) {
96 $this->setSafe($node, array('all'));
98 $this->setSafe($node, array());
101 $this->setSafe($node, array());
107 protected function intersectSafe(array $a = null, array $b = null)
109 if (null === $a || null === $b) {
113 if (in_array('all', $a)) {
117 if (in_array('all', $b)) {
121 return array_intersect($a, $b);
127 public function getPriority()