diff --git a/src/ControlStructure/BlockToken.php b/src/ControlStructure/BlockToken.php index 258f846..8b728b5 100644 --- a/src/ControlStructure/BlockToken.php +++ b/src/ControlStructure/BlockToken.php @@ -8,17 +8,22 @@ class BlockToken implements ControlStructure { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string { + static $depth = 0; static $slotDefinitions = []; + # dump($depth, $token, $arguments, $slotDefinitions); + switch($token) { case "block": $slotDefinitions[] = $this->slotDefinitions(); - + $depth++; + return ""; - + case "endblock": + $depth--; return "render(\$___class__template); unset(\$___block); ?>"; - + case "arguments": $class = static::class; @@ -36,19 +41,19 @@ class BlockToken implements ControlStructure { } /*%EXCEPTION_LINE_BASE%*/?> PHP; - + case "define": list($name, $definition) = array_pad(explode(',', $arguments, 2), 2, ""); - - end($slotDefinitions)->setDefinition(eval("return $name;"), $definition); - + + ( $slotDefinitions[$depth] ?? end($slotDefinitions) )->setDefinition(eval("return $name;"), $definition); + return <<defineSlot($name, function($definition) {}); ?> PHP; - + case "slot": - $def = end($slotDefinitions); - + $def = ( $slotDefinitions[$depth] ?? end($slotDefinitions) ); + list($name, $definition) = array_pad(explode(',', $arguments, 2), 2, ""); $loops = count($context->iterationStack ?? []) ? ",". implode(', ', array_filter(array_column($context->iterationStack, 'uid'), fn($e) => strpos($e, '[') === false)) : null; @@ -57,7 +62,7 @@ class BlockToken implements ControlStructure { $slotName = eval("return $name;"); $def->currentSlot = $slotName; $def->setDefinitionVars($slotName, $definition); - + $definition = $def->printDefinition($slotName); if ($definition) { @@ -72,18 +77,18 @@ class BlockToken implements ControlStructure { if ($definition) { $definition .= ","; } - + return <<slotIsSet($name) || \$___block->setSlot($name, function($definition array \$___using = []) use (\$picea $loops) { extract(\$___using, \EXTR_SKIP); ?> + slotIsSet($name) || (\$___block ?? \$this)->setSlot($name, function($definition array \$___using = []) use (\$picea $loops) { extract(\$___using, \EXTR_SKIP); ?> PHP; } - + case "endslot": - $def =end($slotDefinitions); - + $def = ( $slotDefinitions[$depth] ?? end($slotDefinitions) ); + if ($def->hasDefinitions() ) { $definition = $def->getCurrentSlotDefinitionVars(); - + if ($definition) { $definition .= ","; } @@ -95,23 +100,23 @@ class BlockToken implements ControlStructure { else { return ""; } - + case "using": return "setUsing($arguments); ?>"; } } - - + + public function inlineHtml(? object $proxy, string $viewPath, ... $variables) { return $this->renderHtml($viewPath, [ 'inlineVariables' => $variables ], $proxy); } - + public static function parseSlotArguments(Callable $method) : array { - #return + #return } - - + + public static function parseArguments(Callable $method, array $arguments) : array { try{ @@ -119,10 +124,10 @@ class BlockToken implements ControlStructure { } catch(\TypeError $ex) { throw $ex; - } - + } + $parameters = []; - + foreach((new \ReflectionFunction($method))->getParameters() as $key => $value) { if ( isset($arguments[$key]) ) { $parameters[ $value->getName() ] = $arguments[$key]; @@ -137,114 +142,114 @@ class BlockToken implements ControlStructure { $parameters[ $value->getName() ] = null; } } - + return $parameters; } - + public static function slotDefinitions() { return new class() { - + public array $definitions = []; - + public array $variables = []; - + public bool $rendering = false; - + public string $currentSlot; - - public function setDefinition(string $name, string $definition) : self + + public function setDefinition(string $name, string $definition) : self { $this->definitions[$name] = $definition; - + return $this; } - + public function setDefinitionVars(string $name, string $variables) : self { $this->variables[$name] = $variables; - + return $this; } - + public function getDefinitionVars(string $name) : string { return $this->variables[$name] ?? ""; } - + public function getCurrentSlotDefinitionVars() : string { return $this->getDefinitionVars($this->currentSlot); } - + public function hasDefinitions() : bool { return count($this->definitions) > 0; } - + public function printDefinition(string $name) : string { if ( ! isset($this->definitions[$name]) ) { throw new \Exception("Slot definition for `$name` was not found. Have you defined it in your block header using something like '{% define \"$name\", ...\$arguments %}' ?"); } - + return $this->definitions[$name]; } - + public function render() : void { $this->rendering = true; } }; } - - public static function instanciateBlock(string $viewPath, ... $arguments) + + public static function instanciateBlock(string $viewPath, ... $arguments) { return new class($viewPath, ...$arguments) { - + public bool $rendering = false; - + public string $viewPath; - + public array $using = []; - + public array $arguments = []; - + public array $slots = []; - + public array $definition = []; - + public function __construct(string $viewPath, ...$arguments) { $this->viewPath = $viewPath; $this->arguments = $arguments; } - + public function render(object $classTemplate) : string { $this->rendering = true; return $classTemplate->picea->inlineBlock($this, $this->viewPath, ...$this->arguments); } - + public function setSlot(string $name, Callable $method) : void { $this->slots[$name] = $method; } - + public function defineSlot(string $name, Callable $method) : void { $this->definition[$name] = $method; } - + public function slotIsSet(string $name) : bool { return ! empty($this->slots[$name]); } - + public function printSlot(string $name, Callable $default) { return $this->slotIsSet($name) ? $this->slots[$name] : $default; } - + public function setUsing(array $variables) { $this->using = $variables; }