Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. ForNode.php

function ForNode::compile

Overrides Node::compile

File

vendor/twig/twig/src/Node/ForNode.php, line 42

Class

ForNode
Represents a for node.

Namespace

Twig\Node

Code

public function compile(Compiler $compiler) : void {
    $compiler->addDebugInfo($this)
        ->write("\$context['_parent'] = \$context;\n")
        ->write("\$context['_seq'] = CoreExtension::ensureTraversable(")
        ->subcompile($this->getNode('seq'))
        ->raw(");\n");
    if ($this->hasNode('else')) {
        $compiler->write("\$context['_iterated'] = false;\n");
    }
    if ($this->getAttribute('with_loop')) {
        $compiler->write("\$context['loop'] = [\n")
            ->write("  'parent' => \$context['_parent'],\n")
            ->write("  'index0' => 0,\n")
            ->write("  'index'  => 1,\n")
            ->write("  'first'  => true,\n")
            ->write("];\n")
            ->write("if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof \\Countable)) {\n")
            ->indent()
            ->write("\$length = count(\$context['_seq']);\n")
            ->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");
    }
    $this->loop
        ->setAttribute('else', $this->hasNode('else'));
    $this->loop
        ->setAttribute('with_loop', $this->getAttribute('with_loop'));
    $compiler->write("foreach (\$context['_seq'] as ")
        ->subcompile($this->getNode('key_target'))
        ->raw(' => ')
        ->subcompile($this->getNode('value_target'))
        ->raw(") {\n")
        ->indent()
        ->subcompile($this->getNode('body'))
        ->outdent()
        ->write("}\n");
    if ($this->hasNode('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[\'' . $this->getNode('key_target')
        ->getAttribute('name') . '\'], $context[\'' . $this->getNode('value_target')
        ->getAttribute('name') . '\'], $context[\'_parent\']');
    if ($this->hasNode('else')) {
        $compiler->raw(', $context[\'_iterated\']');
    }
    if ($this->getAttribute('with_loop')) {
        $compiler->raw(', $context[\'loop\']');
    }
    $compiler->raw(");\n");
    // keep the values set in the inner context for variables defined in the outer context
    $compiler->write("\$context = array_intersect_key(\$context, \$_parent) + \$_parent;\n");
}
RSS feed
Powered by Drupal