shop.balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

SafeAnalysis.php (5001B)


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