Seditio Source
Root |
./othercms/xenForo 2.2.8/src/XF/Template/Compiler/Tag/ForeachTag.php
<?php

namespace XF\Template\Compiler\Tag;

use
XF\Template\Compiler\Syntax\Tag;
use
XF\Template\Compiler;

class
ForeachTag extends AbstractTag
{
    public function
compile(Tag $tag, Compiler $compiler, array $context, $inlineExpected)
    {
       
$callback = function($type, array $blocks) use ($compiler, $context)
        {
           
$compiler->traverseBlockChildren($blocks, $context);
        };

        return
$this->compileToCallback($tag, $compiler, $context, $callback, $inlineExpected);
    }

    public function
compileToCallback(
       
Tag $tag, Compiler $compiler, array $context, \Closure $blockHandler, $inlineExpected = false
   
)
    {
       
$attributes = $tag->attributes;

       
$tag->assertAttribute('loop');
       
$tag->assertAttribute('value');

        if (
$inlineExpected)
        {
           
$compiler->pushTempVar();
        }

       
$loopContext = $context;
       
$loopContext['escape'] = false;

       
$loopExpression = $compiler->forceToExpression($attributes['loop']);
        if (
$loopExpression instanceof Compiler\Syntax\Variable && $loopExpression->isSimple())
        {
           
$loop = $loopExpression->compile($compiler, $loopContext, true);
        }
        else
        {
           
$loop = $compiler->getTempVar();
           
$loopValue = $loopExpression->compile($compiler, $loopContext, true);
           
$compiler->write("$loop = $loopValue;");
        }

       
$value = $compiler->compileSimpleVariable($attributes['value'], $loopContext);

        if (!empty(
$attributes['key']))
        {
           
$key = $compiler->compileSimpleVariable($attributes['key'], $loopContext);
        }
        else
        {
           
$key = null;
        }

        if (!empty(
$attributes['i']))
        {
           
$i = $compiler->compileSimpleVariable($attributes['i'], $loopContext);
        }
        else
        {
           
$i = null;
        }

        if (!empty(
$attributes['if']))
        {
           
$if = $compiler->compileForcedExpression($attributes['if'], $loopContext);
        }
        else
        {
           
$if = null;
        }

       
$hasElse = false;

       
$parts = [
           
'foreach' => [],
           
'else' => []
        ];
       
$partId = 'foreach';

        foreach (
$tag->children AS $child)
        {
            if (
$this->isNamedTag($child, 'else'))
            {
               
/** @var $child Tag */

               
if ($hasElse)
                {
                    throw
$child->exception(\XF::phrase('only_one_else_tag_is_allowed_per_foreach_tag'));
                }

               
$hasElse = true;
               
$partId = 'else';
            }
            else
            {
               
$parts[$partId][] = $child;
            }
        }

        if (
$hasElse)
        {
           
$elseTriggerVar = $compiler->getTempVar();
           
$compiler->write("$elseTriggerVar = true;");
        }
        else
        {
           
$elseTriggerVar = null;
        }

        if (
$i)
        {
            if (!empty(
$attributes['istart']))
            {
               
$iStartExpression = $compiler->forceToExpression($attributes['istart']);
                if (
$iStartExpression instanceof Compiler\Syntax\Variable && $iStartExpression->isSimple())
                {
                   
$iStart = $iStartExpression->compile($compiler, $loopContext, true);
                }
                else
                {
                   
$iStart = $compiler->getTempVar();
                   
$iStartValue = $iStartExpression->compile($compiler, $loopContext, true);
                   
$compiler->write("$iStart = $iStartValue + 0;");
                }
            }
            else
            {
               
$iStart = 0;
            }

           
$compiler->write("$i = $iStart;");
        }

       
$compiler
           
->write("if ({$compiler->templaterVariable}->isTraversable({$loop})) {")->pushIndent()
            ->
write("foreach ($loop AS " . ($key ? "$key => " : '') . "$value) {")->pushIndent();

        if (
$if)
        {
           
$compiler->write("if ($if) {")->pushIndent();
        }

        if (
$hasElse)
        {
           
$compiler->write("$elseTriggerVar = false;");
        }
        if (
$i)
        {
           
$compiler->write("{$i}++;");
        }

       
$blockHandler('foreach', $parts['foreach']);

        if (
$if)
        {
           
$compiler->popIndent()->write('}');
        }

       
$compiler
           
->popIndent()->write('}') // close the foreach
           
->popIndent()->write('}'); // close the outer if


       
if ($hasElse)
        {
           
$compiler->write("if ($elseTriggerVar) {")->pushIndent();
           
$blockHandler('else', $parts['else']);
           
$compiler->popIndent()->write('}'); // close the if
       
}

        if (
$inlineExpected)
        {
            return
$compiler->popVar();
        }
        else
        {
            return
false;
        }
    }
}