source: pro-violet-viettel/sourcecode/application/third_party/Twig/Node/For.php @ 345

Last change on this file since 345 was 345, checked in by quyenla, 11 years ago

collaborator page

File size: 4.4 KB
Line 
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2009 Fabien Potencier
7 * (c) 2009 Armin Ronacher
8 *
9 * For the full copyright and license information, please view the LICENSE
10 * file that was distributed with this source code.
11 */
12
13/**
14 * Represents a for node.
15 *
16 * @package    twig
17 * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
18 */
19class Twig_Node_For extends Twig_Node
20{
21    public function __construct(Twig_Node_Expression_AssignName $keyTarget, Twig_Node_Expression_AssignName $valueTarget, Twig_Node_Expression $seq, Twig_NodeInterface $body, Twig_NodeInterface $else = null, $lineno, $tag = null)
22    {
23        parent::__construct(array('key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body, 'else' => $else), array('with_loop' => true), $lineno, $tag);
24    }
25
26    /**
27     * Compiles the node to PHP.
28     *
29     * @param Twig_Compiler A Twig_Compiler instance
30     */
31    public function compile(Twig_Compiler $compiler)
32    {
33        $compiler
34            ->addDebugInfo($this)
35            // the (array) cast bypasses a PHP 5.2.6 bug
36            ->write("\$context['_parent'] = (array) \$context;\n")
37            ->write("\$context['_seq'] = twig_ensure_traversable(")
38            ->subcompile($this->getNode('seq'))
39            ->raw(");\n")
40        ;
41
42        if (null !== $this->getNode('else')) {
43            $compiler->write("\$context['_iterated'] = false;\n");
44        }
45
46        if ($this->getAttribute('with_loop')) {
47            $compiler
48                ->write("\$context['loop'] = array(\n")
49                ->write("  'parent' => \$context['_parent'],\n")
50                ->write("  'index0' => 0,\n")
51                ->write("  'index'  => 1,\n")
52                ->write("  'first'  => true,\n")
53                ->write(");\n")
54                ->write("if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof Countable)) {\n")
55                ->indent()
56                ->write("\$length = count(\$context['_seq']);\n")
57                ->write("\$context['loop']['revindex0'] = \$length - 1;\n")
58                ->write("\$context['loop']['revindex'] = \$length;\n")
59                ->write("\$context['loop']['length'] = \$length;\n")
60                ->write("\$context['loop']['last'] = 1 === \$length;\n")
61                ->outdent()
62                ->write("}\n")
63            ;
64        }
65
66        $compiler
67            ->write("foreach (\$context['_seq'] as ")
68            ->subcompile($this->getNode('key_target'))
69            ->raw(" => ")
70            ->subcompile($this->getNode('value_target'))
71            ->raw(") {\n")
72            ->indent()
73        ;
74
75        $compiler->subcompile($this->getNode('body'));
76
77        if (null !== $this->getNode('else')) {
78            $compiler->write("\$context['_iterated'] = true;\n");
79        }
80
81        if ($this->getAttribute('with_loop')) {
82            $compiler
83                ->write("++\$context['loop']['index0'];\n")
84                ->write("++\$context['loop']['index'];\n")
85                ->write("\$context['loop']['first'] = false;\n")
86                ->write("if (isset(\$context['loop']['length'])) {\n")
87                ->indent()
88                ->write("--\$context['loop']['revindex0'];\n")
89                ->write("--\$context['loop']['revindex'];\n")
90                ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n")
91                ->outdent()
92                ->write("}\n")
93            ;
94        }
95
96        $compiler
97            ->outdent()
98            ->write("}\n")
99        ;
100
101        if (null !== $this->getNode('else')) {
102            $compiler
103                ->write("if (!\$context['_iterated']) {\n")
104                ->indent()
105                ->subcompile($this->getNode('else'))
106                ->outdent()
107                ->write("}\n")
108            ;
109        }
110
111        $compiler->write("\$_parent = \$context['_parent'];\n");
112
113        // remove some "private" loop variables (needed for nested loops)
114        $compiler->write('unset($context[\'_seq\'], $context[\'_iterated\'], $context[\''.$this->getNode('key_target')->getAttribute('name').'\'], $context[\''.$this->getNode('value_target')->getAttribute('name').'\'], $context[\'_parent\'], $context[\'loop\']);'."\n");
115
116        // keep the values set in the inner context for variables defined in the outer context
117        $compiler->write("\$context = array_merge(\$_parent, array_intersect_key(\$context, \$_parent));\n");
118    }
119}
Note: See TracBrowser for help on using the repository browser.