- Added a loop index in AbstractLoop control struct.

This commit is contained in:
Dave Mc Nicoll 2025-10-03 18:34:32 +00:00
parent e737e82d7e
commit ef95576d74
10 changed files with 73 additions and 36 deletions

View File

@ -4,30 +4,18 @@ namespace Picea\ControlStructure;
abstract class AbstractLoop implements ControlStructure { abstract class AbstractLoop implements ControlStructure {
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string protected function openLoop(\Picea\Compiler\Context &$context, ?string $arguments, string $token,) : string
{ {
switch($token) { $name = "$".uniqid("{$token}_");
case "while":
case "foreach":
$name = "$".uniqid("{$token}_");
$stack = array_filter($context->iterationStack ?? [], function($item) {
return ! $item['or'];
});
$count = count($stack);
if ( $count > 0 ) { $stack = array_filter($context->iterationStack ?? [], function($item) {
$name .= "[" . end($stack)['uid'] . "]"; return ! $item['or'];
} });
$context->iterationStack[] = [ $count = count($stack);
'or' => false,
'uid' => $name,
'token' => "end{$token}",
];
return "<?php $token ($arguments): $name = ( $name ?? 0 ) + 1; ?>"; <<<<<<< HEAD
return "<?php $token ($arguments): \$__loop_index = $name = ( $name ?? 0 ) + 1; ?>";
case "endwhile": case "endwhile":
case "endforeach": case "endforeach":
@ -43,6 +31,34 @@ abstract class AbstractLoop implements ControlStructure {
array_pop($context->iterationStack); array_pop($context->iterationStack);
return $output; return $output;
=======
if ( $count > 0 ) {
$name .= "[" . end($stack)['uid'] . "]";
>>>>>>> 579a917 (- Added a loop index in AbstractLoop control struct.)
} }
$context->iterationStack[] = [
'or' => false,
'uid' => $name,
'token' => "end{$token}",
];
return "<?php $token ($arguments): \$__loop_index = $name = ( $name ?? 0 ) + 1; ?>";
}
protected function closeLoop(\Picea\Compiler\Context &$context, ?string $arguments, string $token,) : string
{
$last = end($context->iterationStack);
if ( $last['or'] === false ) {
$output = "<?php $token; ?>";
}
else {
$output = "<?php endif; if ( isset({$last['uid']}) ) unset({$last['uid']}); ?>";
}
array_pop($context->iterationStack);
return $output;
} }
} }

View File

@ -4,7 +4,7 @@ namespace Picea\ControlStructure;
class BlockToken implements ControlStructure { class BlockToken implements ControlStructure {
public array $token = [ "arguments", "block", "endblock", "define", "slot", "endslot", "using" ]; public array $token = [ "arguments", "block", "endblock", "/block", "define", "slot", "endslot", "/slot", "using" ];
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
{ {
@ -20,6 +20,7 @@ class BlockToken implements ControlStructure {
return "<?php \$___block = \Picea\ControlStructure\BlockToken::instanciateBlock($arguments); ?>"; return "<?php \$___block = \Picea\ControlStructure\BlockToken::instanciateBlock($arguments); ?>";
case "/block":
case "endblock": case "endblock":
$depth--; $depth--;
return "<?php echo \$___block->render(\$___class__template); unset(\$___block); ?>"; return "<?php echo \$___block->render(\$___class__template); unset(\$___block); ?>";
@ -83,6 +84,7 @@ class BlockToken implements ControlStructure {
PHP; PHP;
} }
case "/slot":
case "endslot": case "endslot":
$def = ( $slotDefinitions[$depth] ?? end($slotDefinitions) ); $def = ( $slotDefinitions[$depth] ?? end($slotDefinitions) );
@ -106,7 +108,6 @@ class BlockToken implements ControlStructure {
} }
} }
public function inlineHtml(? object $proxy, string $viewPath, ... $variables) { public function inlineHtml(? object $proxy, string $viewPath, ... $variables) {
return $this->renderHtml($viewPath, [ 'inlineVariables' => $variables ], $proxy); return $this->renderHtml($viewPath, [ 'inlineVariables' => $variables ], $proxy);
} }

View File

@ -4,7 +4,7 @@ namespace Picea\ControlStructure;
class ForToken implements ControlStructure { class ForToken implements ControlStructure {
public array $token = [ "for", "endfor" ]; public array $token = [ "for", "endfor", "/for" ];
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string {
switch($token) { switch($token) {
@ -18,7 +18,8 @@ class ForToken implements ControlStructure {
]; ];
return "<?php for ($arguments): {$uid} = 1; ?>"; return "<?php for ($arguments): {$uid} = 1; ?>";
case "/for":
case "endfor": case "endfor":
$last = end($context->iterationStack); $last = end($context->iterationStack);

View File

@ -5,5 +5,17 @@ namespace Picea\ControlStructure;
use DI\Definition\Source\AnnotationBasedAutowiring; use DI\Definition\Source\AnnotationBasedAutowiring;
class ForeachToken extends AbstractLoop { class ForeachToken extends AbstractLoop {
public array $token = [ "foreach", "endforeach" ]; public array $token = [ "foreach", "endforeach", "/foreach" ];
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
{
switch($token) {
case "foreach":
return $this->openLoop($context, $arguments, $token);
case "endforeach":
case "/foreach":
return $this->closeLoop($context, $arguments, $token);
}
}
} }

View File

@ -4,7 +4,7 @@ namespace Picea\ControlStructure;
class IfToken implements ControlStructure { class IfToken implements ControlStructure {
public array $token = [ "if", "else", "elseif", "endif" ]; public array $token = [ "if", "else", "elseif", "endif", "/if" ];
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string {
switch($token) { switch($token) {
@ -16,7 +16,8 @@ class IfToken implements ControlStructure {
case "elseif": case "elseif":
return "<?php elseif ($arguments): ?>"; return "<?php elseif ($arguments): ?>";
case "/if":
case "endif": case "endif":
return "<?php endif ?>"; return "<?php endif ?>";
} }

View File

@ -11,7 +11,7 @@ enum PrintActionEnum : string {
class SectionToken implements ControlStructure { class SectionToken implements ControlStructure {
public array $token = [ "section", "endsection" ]; public array $token = [ "section", "endsection", "/section" ];
protected PrintActionEnum $action = PrintActionEnum::default; protected PrintActionEnum $action = PrintActionEnum::default;
@ -29,6 +29,7 @@ class SectionToken implements ControlStructure {
return $this->printSection($context, $arguments); return $this->printSection($context, $arguments);
case "endsection": case "endsection":
case "/endsection":
if ( empty($context->sections) ) { if ( empty($context->sections) ) {
throw new \RuntimeException("A section closing tag {% endsection %} was found without an opening {% section %} tag"); throw new \RuntimeException("A section closing tag {% endsection %} was found without an opening {% section %} tag");
} }

View File

@ -23,11 +23,13 @@ class SwitchToken implements ControlStructure {
} }
return ( $output ?? "" ) . "case $arguments: ?>"; return ( $output ?? "" ) . "case $arguments: ?>";
case "endcase": case "endcase":
case "/case":
return "<?php break; ?>"; return "<?php break; ?>";
case "endswitch": case "endswitch":
case "/switch":
return "<?php endswitch; ?>"; return "<?php endswitch; ?>";
} }
} }

View File

@ -4,12 +4,11 @@ namespace Picea\ControlStructure;
class TryCatchToken implements ControlStructure { class TryCatchToken implements ControlStructure {
public array $token = [ "try", "catch", "finally", "endtry" ]; public array $token = [ "try", "catch", "finally", "endtry", "/try" ];
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string {
switch($token) { switch($token) {
case "try": case "try":
return "<?php try { ?>"; return "<?php try { ?>";
case "catch": case "catch":
@ -19,6 +18,7 @@ class TryCatchToken implements ControlStructure {
return "<?php } finally { ?>"; return "<?php } finally { ?>";
case "endtry": case "endtry":
case "/try":
return "<?php } ?>"; return "<?php } ?>";
} }
} }

View File

@ -3,7 +3,7 @@
namespace Picea\ControlStructure; namespace Picea\ControlStructure;
class WhileToken extends AbstractLoop { class WhileToken extends AbstractLoop {
public array $token = [ "do", "while", "endwhile", ]; public array $token = [ "do", "while", "endwhile", "/while" ];
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string {
switch($token) { switch($token) {
@ -23,10 +23,13 @@ class WhileToken extends AbstractLoop {
return "<?php } while($arguments); ?>"; return "<?php } while($arguments); ?>";
} }
} }
return $this->openLoop($context, $arguments, $token);
case "endwhile":
case "/while":
return $this->closeLoop($context, $arguments, $token);
} }
return parent::parse($context, $arguments, $token);
} }
} }

View File

@ -31,7 +31,7 @@ PATTERN;
public array $tokens = [ "url" , "route", "asset", "slug" ]; public array $tokens = [ "url" , "route", "asset", "slug" ];
##[\Deprecated] ##[\Deprecated]
protected bool $enforceExistingArguments = true; public bool $enforceExistingArguments = true;
public function __construct(string $urlBase = "", string $assetToken = "", array $appUrl = [], bool $forceSSL = false) { public function __construct(string $urlBase = "", string $assetToken = "", array $appUrl = [], bool $forceSSL = false) {
$this->urlBase = trim($urlBase, "/"); $this->urlBase = trim($urlBase, "/");