Verzeichnisstruktur phpBB-3.1.0
- Veröffentlicht
- 27.10.2014
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
Optimizer.php
001 <?php
002
003 /*
004 * This file is part of Twig.
005 *
006 * (c) 2010 Fabien Potencier
007 *
008 * For the full copyright and license information, please view the LICENSE
009 * file that was distributed with this source code.
010 */
011
012 /**
013 * Twig_NodeVisitor_Optimizer tries to optimizes the AST.
014 *
015 * This visitor is always the last registered one.
016 *
017 * You can configure which optimizations you want to activate via the
018 * optimizer mode.
019 *
020 * @author Fabien Potencier <fabien@symfony.com>
021 */
022 class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
023 {
024 const OPTIMIZE_ALL = -1;
025 const OPTIMIZE_NONE = 0;
026 const OPTIMIZE_FOR = 2;
027 const OPTIMIZE_RAW_FILTER = 4;
028 const OPTIMIZE_VAR_ACCESS = 8;
029
030 protected $loops = array();
031 protected $optimizers;
032 protected $prependedNodes = array();
033 protected $inABody = false;
034
035 /**
036 * Constructor.
037 *
038 * @param integer $optimizers The optimizer mode
039 */
040 public function __construct($optimizers = -1)
041 {
042 if (!is_int($optimizers) || $optimizers > 2) {
043 throw new InvalidArgumentException(sprintf('Optimizer mode "%s" is not valid.', $optimizers));
044 }
045
046 $this->optimizers = $optimizers;
047 }
048
049 /**
050 * {@inheritdoc}
051 */
052 public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
053 {
054 if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
055 $this->enterOptimizeFor($node, $env);
056 }
057
058 if (!version_compare(phpversion(), '5.4.0RC1', '>=') && self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('sandbox')) {
059 if ($this->inABody) {
060 if (!$node instanceof Twig_Node_Expression) {
061 if (get_class($node) !== 'Twig_Node') {
062 array_unshift($this->prependedNodes, array());
063 }
064 } else {
065 $node = $this->optimizeVariables($node, $env);
066 }
067 } elseif ($node instanceof Twig_Node_Body) {
068 $this->inABody = true;
069 }
070 }
071
072 return $node;
073 }
074
075 /**
076 * {@inheritdoc}
077 */
078 public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
079 {
080 $expression = $node instanceof Twig_Node_Expression;
081
082 if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
083 $this->leaveOptimizeFor($node, $env);
084 }
085
086 if (self::OPTIMIZE_RAW_FILTER === (self::OPTIMIZE_RAW_FILTER & $this->optimizers)) {
087 $node = $this->optimizeRawFilter($node, $env);
088 }
089
090 $node = $this->optimizePrintNode($node, $env);
091
092 if (self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('sandbox')) {
093 if ($node instanceof Twig_Node_Body) {
094 $this->inABody = false;
095 } elseif ($this->inABody) {
096 if (!$expression && get_class($node) !== 'Twig_Node' && $prependedNodes = array_shift($this->prependedNodes)) {
097 $nodes = array();
098 foreach (array_unique($prependedNodes) as $name) {
099 $nodes[] = new Twig_Node_SetTemp($name, $node->getLine());
100 }
101
102 $nodes[] = $node;
103 $node = new Twig_Node($nodes);
104 }
105 }
106 }
107
108 return $node;
109 }
110
111 protected function optimizeVariables($node, $env)
112 {
113 if ('Twig_Node_Expression_Name' === get_class($node) && $node->isSimple()) {
114 $this->prependedNodes[0][] = $node->getAttribute('name');
115
116 return new Twig_Node_Expression_TempName($node->getAttribute('name'), $node->getLine());
117 }
118
119 return $node;
120 }
121
122 /**
123 * Optimizes print nodes.
124 *
125 * It replaces:
126 *
127 * * "echo $this->render(Parent)Block()" with "$this->display(Parent)Block()"
128 *
129 * @param Twig_NodeInterface $node A Node
130 * @param Twig_Environment $env The current Twig environment
131 */
132 protected function optimizePrintNode($node, $env)
133 {
134 if (!$node instanceof Twig_Node_Print) {
135 return $node;
136 }
137
138 if (
139 $node->getNode('expr') instanceof Twig_Node_Expression_BlockReference ||
140 $node->getNode('expr') instanceof Twig_Node_Expression_Parent
141 ) {
142 $node->getNode('expr')->setAttribute('output', true);
143
144 return $node->getNode('expr');
145 }
146
147 return $node;
148 }
149
150 /**
151 * Removes "raw" filters.
152 *
153 * @param Twig_NodeInterface $node A Node
154 * @param Twig_Environment $env The current Twig environment
155 */
156 protected function optimizeRawFilter($node, $env)
157 {
158 if ($node instanceof Twig_Node_Expression_Filter && 'raw' == $node->getNode('filter')->getAttribute('value')) {
159 return $node->getNode('node');
160 }
161
162 return $node;
163 }
164
165 /**
166 * Optimizes "for" tag by removing the "loop" variable creation whenever possible.
167 *
168 * @param Twig_NodeInterface $node A Node
169 * @param Twig_Environment $env The current Twig environment
170 */
171 protected function enterOptimizeFor($node, $env)
172 {
173 if ($node instanceof Twig_Node_For) {
174 // disable the loop variable by default
175 $node->setAttribute('with_loop', false);
176 array_unshift($this->loops, $node);
177 } elseif (!$this->loops) {
178 // we are outside a loop
179 return;
180 }
181
182 // when do we need to add the loop variable back?
183
184 // the loop variable is referenced for the current loop
185 elseif ($node instanceof Twig_Node_Expression_Name && 'loop' === $node->getAttribute('name')) {
186 $this->addLoopToCurrent();
187 }
188
189 // block reference
190 elseif ($node instanceof Twig_Node_BlockReference || $node instanceof Twig_Node_Expression_BlockReference) {
191 $this->addLoopToCurrent();
192 }
193
194 // include without the only attribute
195 elseif ($node instanceof Twig_Node_Include && !$node->getAttribute('only')) {
196 $this->addLoopToAll();
197 }
198
199 // the loop variable is referenced via an attribute
200 elseif ($node instanceof Twig_Node_Expression_GetAttr
201 && (!$node->getNode('attribute') instanceof Twig_Node_Expression_Constant
202 || 'parent' === $node->getNode('attribute')->getAttribute('value')
203 )
204 && (true === $this->loops[0]->getAttribute('with_loop')
205 || ($node->getNode('node') instanceof Twig_Node_Expression_Name
206 && 'loop' === $node->getNode('node')->getAttribute('name')
207 )
208 )
209 ) {
210 $this->addLoopToAll();
211 }
212 }
213
214 /**
215 * Optimizes "for" tag by removing the "loop" variable creation whenever possible.
216 *
217 * @param Twig_NodeInterface $node A Node
218 * @param Twig_Environment $env The current Twig environment
219 */
220 protected function leaveOptimizeFor($node, $env)
221 {
222 if ($node instanceof Twig_Node_For) {
223 array_shift($this->loops);
224 }
225 }
226
227 protected function addLoopToCurrent()
228 {
229 $this->loops[0]->setAttribute('with_loop', true);
230 }
231
232 protected function addLoopToAll()
233 {
234 foreach ($this->loops as $loop) {
235 $loop->setAttribute('with_loop', true);
236 }
237 }
238
239 /**
240 * {@inheritdoc}
241 */
242 public function getPriority()
243 {
244 return 255;
245 }
246 }
247