Twig_Node_For::compile PHP Method

compile() public method

Compiles the node to PHP.
public compile ( $compiler )
    public function compile($compiler)
    {
        $compiler
            ->addDebugInfo($this)
            // the (array) cast bypasses a PHP 5.2.6 bug
            ->write('$context[\'_parent\'] = (array) $context;'."\n")
        ;

        if (null !== $this->getNode('else')) {
            $compiler->write("\$context['_iterated'] = false;\n");
        }

        $compiler
            ->write("\$context['_seq'] = twig_iterator_to_array(")
            ->subcompile($this->getNode('seq'))
            ->raw(");\n")
        ;

        if ($this->getAttribute('with_loop')) {
            $compiler
                ->write("\$countable = is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof Countable);\n")
                ->write("\$length = \$countable ? count(\$context['_seq']) : null;\n")

                ->write("\$context['loop'] = array(\n")
                ->write("  'parent' => \$context['_parent'],\n")
                ->write("  'index0' => 0,\n")
                ->write("  'index'  => 1,\n")
                ->write("  'first'  => true,\n")
                ->write(");\n")
                ->write("if (\$countable) {\n")
                ->indent()
                ->write("\$context['loop']['revindex0'] = \$length - 1;\n")
                ->write("\$context['loop']['revindex'] = \$length;\n")
                ->write("\$context['loop']['length'] = \$length;\n")
                ->write("\$context['loop']['last'] = 1 === \$length;\n")
                ->outdent()
                ->write("}\n")
            ;
        }

        if (null !== $this->getNode('joined_with')) {
            $compiler->write("\$context['_first_iteration'] = true;\n");
        }

        $compiler
            ->write("foreach (\$context['_seq'] as ")
            ->subcompile($this->getNode('key_target'))
            ->raw(" => ")
            ->subcompile($this->getNode('value_target'))
            ->raw(") {\n")
            ->indent()
        ;

        if (null !== $this->getNode('else')) {
            $compiler->write("\$context['_iterated'] = true;\n");
        }

        if (null !== $this->getNode('joined_with')) {
            $compiler
                ->write("if (\$context['_first_iteration']) {\n")
                ->indent()
                ->write("\$context['_first_iteration'] = false;\n")
                ->outdent()
                ->write("} else {\n")
                ->indent()
                ->write("echo ")
                ->subcompile($this->getNode('joined_with'))
                ->raw(";\n")
                ->outdent()
                ->write("}\n");
        }

        $compiler->subcompile($this->getNode('body'));

        if ($this->getAttribute('with_loop')) {
            $compiler
                ->write("++\$context['loop']['index0'];\n")
                ->write("++\$context['loop']['index'];\n")
                ->write("\$context['loop']['first'] = false;\n")
                ->write("if (\$countable) {\n")
                ->indent()
                ->write("--\$context['loop']['revindex0'];\n")
                ->write("--\$context['loop']['revindex'];\n")
                ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n")
                ->outdent()
                ->write("}\n")
            ;
        }

        $compiler
            ->outdent()
            ->write("}\n")
        ;

        if (null !== $this->getNode('else')) {
            $compiler
                ->write("if (!\$context['_iterated']) {\n")
                ->indent()
                ->subcompile($this->getNode('else'))
                ->outdent()
                ->write("}\n")
            ;
        }

        $compiler->write('$_parent = $context[\'_parent\'];'."\n");

        // remove some "private" loop variables (needed for nested loops)
        $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");

        /// keep the values set in the inner context for variables defined in the outer context
        $compiler->write('$context = array_merge($_parent, array_intersect_key($context, $_parent));'."\n");
    }

Usage Example

コード例 #1
0
ファイル: Nav_Node.php プロジェクト: kentonquatman/portfolio
 /**
  * Compiles the node to PHP.
  *
  * @param \Twig_Compiler $compiler
  *
  * @return null
  */
 public function compile(\Twig_Compiler $compiler)
 {
     // Remember what 'nav' was set to before
     $compiler->write("if (isset(\$context['nav'])) {\n")->indent()->write("\$_nav = \$context['nav'];\n")->outdent()->write("}\n");
     parent::compile($compiler);
     $compiler->write("if (isset(\$_thisItemLevel)) {\n")->indent()->write("\$_tmpContext = \$context;\n")->write("if (\$_thisItemLevel > \$_firstItemLevel) {\n")->indent()->write("for (\$_i = \$_thisItemLevel; \$_i > \$_firstItemLevel; \$_i--) {\n")->indent()->write("if (isset(\$_contextsByLevel[\$_i])) {\n")->indent()->write("\$context = \$_contextsByLevel[\$_i];\n")->subcompile($this->navItemNode->getNode('lower_body'), false)->subcompile($this->navItemNode->getNode('outdent'), false)->outdent()->write("}\n")->outdent()->write("}\n")->outdent()->write("}\n")->write("\$context = \$_contextsByLevel[\$_firstItemLevel];\n")->subcompile($this->navItemNode->getNode('lower_body'), false)->write("\$context = \$_tmpContext;\n")->write("unset(\$_thisItemLevel, \$_firstItemLevel, \$_i, \$_contextsByLevel, \$_tmpContext);\n")->outdent()->write("}\n")->write("if (isset(\$_nav)) {\n")->indent()->write("\$context['nav'] = \$_nav;\n")->write("unset(\$_nav);\n")->outdent()->write("}\n");
 }