Dotclear

source: inc/libs/twig/NodeVisitor/Escaper.php @ 991:e42f791e0975

Revision 991:e42f791e0975, 5.4 KB checked in by Dsls <dsls@…>, 13 years ago (diff)

New twig branch. 1st step : add twig 1.11.1

Line 
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2009 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 * Twig_NodeVisitor_Escaper implements output escaping.
14 *
15 * @package    twig
16 * @author     Fabien Potencier <fabien@symfony.com>
17 */
18class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
19{
20    protected $statusStack = array();
21    protected $blocks = array();
22    protected $safeAnalysis;
23    protected $traverser;
24    protected $defaultStrategy = false;
25    protected $safeVars = array();
26
27    public function __construct()
28    {
29        $this->safeAnalysis = new Twig_NodeVisitor_SafeAnalysis();
30    }
31
32    /**
33     * Called before child nodes are visited.
34     *
35     * @param Twig_NodeInterface $node The node to visit
36     * @param Twig_Environment   $env  The Twig environment instance
37     *
38     * @return Twig_NodeInterface The modified node
39     */
40    public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
41    {
42        if ($node instanceof Twig_Node_Module) {
43            if ($env->hasExtension('escaper') && $defaultStrategy = $env->getExtension('escaper')->getDefaultStrategy($node->getAttribute('filename'))) {
44                $this->defaultStrategy = $defaultStrategy;
45            }
46            $this->safeVars = array();
47        } elseif ($node instanceof Twig_Node_AutoEscape) {
48            $this->statusStack[] = $node->getAttribute('value');
49        } elseif ($node instanceof Twig_Node_Block) {
50            $this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env);
51        } elseif ($node instanceof Twig_Node_Import) {
52            $this->safeVars[] = $node->getNode('var')->getAttribute('name');
53        }
54
55        return $node;
56    }
57
58    /**
59     * Called after child nodes are visited.
60     *
61     * @param Twig_NodeInterface $node The node to visit
62     * @param Twig_Environment   $env  The Twig environment instance
63     *
64     * @return Twig_NodeInterface The modified node
65     */
66    public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
67    {
68        if ($node instanceof Twig_Node_Module) {
69            $this->defaultStrategy = false;
70            $this->safeVars = array();
71        } elseif ($node instanceof Twig_Node_Expression_Filter) {
72            return $this->preEscapeFilterNode($node, $env);
73        } elseif ($node instanceof Twig_Node_Print) {
74            return $this->escapePrintNode($node, $env, $this->needEscaping($env));
75        }
76
77        if ($node instanceof Twig_Node_AutoEscape || $node instanceof Twig_Node_Block) {
78            array_pop($this->statusStack);
79        } elseif ($node instanceof Twig_Node_BlockReference) {
80            $this->blocks[$node->getAttribute('name')] = $this->needEscaping($env);
81        }
82
83        return $node;
84    }
85
86    protected function escapePrintNode(Twig_Node_Print $node, Twig_Environment $env, $type)
87    {
88        if (false === $type) {
89            return $node;
90        }
91
92        $expression = $node->getNode('expr');
93
94        if ($this->isSafeFor($type, $expression, $env)) {
95            return $node;
96        }
97
98        $class = get_class($node);
99
100        return new $class(
101            $this->getEscaperFilter($type, $expression),
102            $node->getLine()
103        );
104    }
105
106    protected function preEscapeFilterNode(Twig_Node_Expression_Filter $filter, Twig_Environment $env)
107    {
108        $name = $filter->getNode('filter')->getAttribute('value');
109
110        if (false !== $f = $env->getFilter($name)) {
111            $type = $f->getPreEscape();
112            if (null === $type) {
113                return $filter;
114            }
115
116            $node = $filter->getNode('node');
117            if ($this->isSafeFor($type, $node, $env)) {
118                return $filter;
119            }
120
121            $filter->setNode('node', $this->getEscaperFilter($type, $node));
122
123            return $filter;
124        }
125
126        return $filter;
127    }
128
129    protected function isSafeFor($type, Twig_NodeInterface $expression, $env)
130    {
131        $safe = $this->safeAnalysis->getSafe($expression);
132
133        if (null === $safe) {
134            if (null === $this->traverser) {
135                $this->traverser = new Twig_NodeTraverser($env, array($this->safeAnalysis));
136            }
137
138            $this->safeAnalysis->setSafeVars($this->safeVars);
139
140            $this->traverser->traverse($expression);
141            $safe = $this->safeAnalysis->getSafe($expression);
142        }
143
144        return in_array($type, $safe) || in_array('all', $safe);
145    }
146
147    protected function needEscaping(Twig_Environment $env)
148    {
149        if (count($this->statusStack)) {
150            return $this->statusStack[count($this->statusStack) - 1];
151        }
152
153        return $this->defaultStrategy ? $this->defaultStrategy : false;
154    }
155
156    protected function getEscaperFilter($type, Twig_NodeInterface $node)
157    {
158        $line = $node->getLine();
159        $name = new Twig_Node_Expression_Constant('escape', $line);
160        $args = new Twig_Node(array(new Twig_Node_Expression_Constant((string) $type, $line), new Twig_Node_Expression_Constant(null, $line), new Twig_Node_Expression_Constant(true, $line)));
161
162        return new Twig_Node_Expression_Filter($node, $name, $args, $line);
163    }
164
165    /**
166     * {@inheritdoc}
167     */
168    public function getPriority()
169    {
170        return 0;
171    }
172}
Note: See TracBrowser for help on using the repository browser.

Sites map