Twig-1.3.0/lib/Twig/NodeVisitor/SafeAnalysis.php
changeset 4 9a001a04b634
equal deleted inserted replaced
3:6d109e3804ac 4:9a001a04b634
       
     1 <?php
       
     2 
       
     3 class Twig_NodeVisitor_SafeAnalysis implements Twig_NodeVisitorInterface
       
     4 {
       
     5     protected $data = array();
       
     6 
       
     7     public function getSafe(Twig_NodeInterface $node)
       
     8     {
       
     9         $hash = spl_object_hash($node);
       
    10         if (isset($this->data[$hash])) {
       
    11             foreach($this->data[$hash] as $bucket) {
       
    12                 if ($bucket['key'] === $node) {
       
    13                     return $bucket['value'];
       
    14                 }
       
    15             }
       
    16         }
       
    17         return null;
       
    18     }
       
    19 
       
    20     protected function setSafe(Twig_NodeInterface $node, array $safe)
       
    21     {
       
    22         $hash = spl_object_hash($node);
       
    23         if (isset($this->data[$hash])) {
       
    24             foreach($this->data[$hash] as &$bucket) {
       
    25                 if ($bucket['key'] === $node) {
       
    26                     $bucket['value'] = $safe;
       
    27                     return;
       
    28                 }
       
    29             }
       
    30         }
       
    31         $this->data[$hash][] = array(
       
    32             'key' => $node,
       
    33             'value' => $safe,
       
    34         );
       
    35     }
       
    36 
       
    37     public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
       
    38     {
       
    39         return $node;
       
    40     }
       
    41 
       
    42     public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
       
    43     {
       
    44         if ($node instanceof Twig_Node_Expression_Constant) {
       
    45             // constants are marked safe for all
       
    46             $this->setSafe($node, array('all'));
       
    47         } elseif ($node instanceof Twig_Node_Expression_BlockReference) {
       
    48             // blocks are safe by definition
       
    49             $this->setSafe($node, array('all'));
       
    50         } elseif ($node instanceof Twig_Node_Expression_Parent) {
       
    51             // parent block is safe by definition
       
    52             $this->setSafe($node, array('all'));
       
    53         } elseif ($node instanceof Twig_Node_Expression_Conditional) {
       
    54             // intersect safeness of both operands
       
    55             $safe = $this->intersectSafe($this->getSafe($node->getNode('expr2')), $this->getSafe($node->getNode('expr3')));
       
    56             $this->setSafe($node, $safe);
       
    57         } elseif ($node instanceof Twig_Node_Expression_Filter) {
       
    58             // filter expression is safe when the filter is safe
       
    59             $name = $node->getNode('filter')->getAttribute('value');
       
    60             $args = $node->getNode('arguments');
       
    61             if (false !== $filter = $env->getFilter($name)) {
       
    62                 $this->setSafe($node, $filter->getSafe($args));
       
    63             } else {
       
    64                 $this->setSafe($node, array());
       
    65             }
       
    66         } elseif ($node instanceof Twig_Node_Expression_Function) {
       
    67             // function expression is safe when the function is safe
       
    68             $name = $node->getAttribute('name');
       
    69             $args = $node->getNode('arguments');
       
    70             $function = $env->getFunction($name);
       
    71             if (false !== $function) {
       
    72                 $this->setSafe($node, $function->getSafe($args));
       
    73             } else {
       
    74                 $this->setSafe($node, array());
       
    75             }
       
    76         } else {
       
    77             $this->setSafe($node, array());
       
    78         }
       
    79 
       
    80         return $node;
       
    81     }
       
    82 
       
    83     protected function intersectSafe(array $a = null, array $b = null)
       
    84     {
       
    85         if (null === $a || null === $b) {
       
    86             return array();
       
    87         }
       
    88 
       
    89         if (in_array('all', $a)) {
       
    90             return $b;
       
    91         }
       
    92 
       
    93         if (in_array('all', $b)) {
       
    94             return $a;
       
    95         }
       
    96 
       
    97         return array_intersect($a, $b);
       
    98     }
       
    99 
       
   100     /**
       
   101      * {@inheritdoc}
       
   102      */
       
   103     public function getPriority()
       
   104     {
       
   105         return 0;
       
   106     }
       
   107 }