diff --git a/src/Builder.php b/src/Builder.php index aaae8fb..69c2930 100644 --- a/src/Builder.php +++ b/src/Builder.php @@ -15,15 +15,17 @@ class Builder public function build(Compiler\Context &$context, string $compiledSource) : Compiler\Context { + $path = fn($p) => addslashes(str_replace('/', DIRECTORY_SEPARATOR, $p)); + $context->className = static::generateClassName($context->viewPath); $replace = [ '%NAMESPACE%' => $context->namespace, '%USE%' => ( $uses = $context->renderUses() ) ? "use $uses;" : false, '%CLASSNAME%' => $context->className, - '%PATHNAME%' => $context->viewPath, - '%FULLPATH%' => $context->filePath, - '%TEMPLATE%' => $this->templatePath, + '%PATHNAME%' => $path($context->viewPath), + '%FULLPATH%' => $path($context->filePath), + '%TEMPLATE%' => $path($this->templatePath), '%EXTENDS%' => $context->extendFrom ? "extends " . static::TEMPLATE_CLASSNAME_PREFIX . static::generateClassUID($context->extendFrom) : '', '%EXTENDS_TEMPLATE%' => $context->extendFrom, '%CONTENT%' => $compiledSource, diff --git a/src/Builder/ClassTemplate.php b/src/Builder/ClassTemplate.php index 8a15530..47b28bd 100644 --- a/src/Builder/ClassTemplate.php +++ b/src/Builder/ClassTemplate.php @@ -67,7 +67,7 @@ if (! class_exists("%NAMESPACE%\%CLASSNAME%", false) ) { $sourceFile = file_get_contents("%TEMPLATE%"); if ( $sourceFile ) { - foreach(explode(PHP_EOL, $sourceFile) as $line => $content) { + foreach(explode("\n", $sourceFile) as $line => $content) { if ( strpos($content, str_replace('$', '%', '$CONTENT$')) !== false ) { return $sourceLine - $line; } diff --git a/src/Compiler/Context.php b/src/Compiler/Context.php index c72218f..62730b6 100644 --- a/src/Compiler/Context.php +++ b/src/Compiler/Context.php @@ -15,6 +15,8 @@ abstract class Context { public string $compiledSource = ""; public string $viewPath = ""; + + public string $filePath = ""; public array $switchStack = []; diff --git a/src/ControlStructure/BlockToken.php b/src/ControlStructure/BlockToken.php index db881e4..84d1854 100644 --- a/src/ControlStructure/BlockToken.php +++ b/src/ControlStructure/BlockToken.php @@ -55,13 +55,21 @@ class BlockToken implements ControlStructure { $definition = $def->printDefinition($slotName); + if ($definition) { + $definition .= ","; + } + return <<printSlot($name, function($definition, array \$___using = []) { extract(\$___using, \EXTR_SKIP); ?> + printSlot($name, function($definition array \$___using = []) use (\$picea) { extract(\$___using, \EXTR_SKIP); ?> PHP; } else { + if ($definition) { + $definition .= ","; + } + return <<slotIsSet($name) || \$___block->setSlot($name, function($definition, array \$___using = []) { extract(\$___using, \EXTR_SKIP); ?> + slotIsSet($name) || \$___block->setSlot($name, function($definition array \$___using = []) use (\$picea) { extract(\$___using, \EXTR_SKIP); ?> PHP; } @@ -72,11 +80,11 @@ class BlockToken implements ControlStructure { $definition = $def->getCurrentSlotDefinitionVars(); if ($definition) { - $definition = "$definition,"; + $definition .= ","; } return <<call(\$this, $definition \$this->using); ?> + call(\$this, $definition array_merge(get_defined_vars(), \$this->using)); ?> PHP; } else { @@ -207,7 +215,7 @@ class BlockToken implements ControlStructure { { $this->rendering = true; - return $classTemplate->picea->inlineHtml($this, $this->viewPath, ...$this->arguments); + return $classTemplate->picea->inlineBlock($this, $this->viewPath, ...$this->arguments); } public function setSlot(string $name, Callable $method) : void diff --git a/src/ControlStructure/ViewToken.php b/src/ControlStructure/ViewToken.php index ddf2078..e6c01b0 100644 --- a/src/ControlStructure/ViewToken.php +++ b/src/ControlStructure/ViewToken.php @@ -7,6 +7,7 @@ class ViewToken implements ControlStructure { public string $token = "view"; public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { - return "picea->renderHtml($arguments, get_defined_vars(), \$this); ?>"; + # The way this is ordered, if you provide a second arguments, being an array of variables, get_defined_vars() will not be pushed inside the view + return "picea->inlineHtml(\$this, $arguments, get_defined_vars()); ?>"; } } diff --git a/src/Extension/TitleExtension.php b/src/Extension/TitleExtension.php index 30560a0..6389159 100644 --- a/src/Extension/TitleExtension.php +++ b/src/Extension/TitleExtension.php @@ -23,7 +23,7 @@ class TitleExtension implements Extension { return ""; } - public function handleTitle(? string $set = null) : ? string + public function handleTitle(? string $set = null, ...$arguments) : ? string { if ( $set === null ) { return $this->title; @@ -31,7 +31,7 @@ class TitleExtension implements Extension { else { # Fixed a bug where template inheritance was rewriting title if ( empty($this->title) ) { - $this->title = $set; + $this->title = $arguments ? sprintf($set, ...$arguments) : $set; } } diff --git a/src/Picea.php b/src/Picea.php index bdff992..0a693e8 100644 --- a/src/Picea.php +++ b/src/Picea.php @@ -64,6 +64,7 @@ class Picea implements LanguageRegistration } catch(\Throwable $ex) { # Temporary class for an experiment + throw $ex; throw new class($object, $this, "An error occurred trying to render HTML view `$viewPath` : " . $ex->getMessage(), 911, $ex) extends \Exception { protected Picea $picea; @@ -75,30 +76,25 @@ class Picea implements LanguageRegistration $this->picea = $picea; # $template = $this->getTemplateFile( $previous->getFile() ); - $this->fromPrevious($previous, $compiledObject); + $this->defineError($previous, $compiledObject); } - protected function fromPrevious(\Throwable $previous, object $compiledObject) : void + protected function defineError(\Throwable $previous, object $compiledObject) : void { $loadedTemplates = array_flip($this->picea->loadedTemplateFile); foreach($previous->getTrace() as $trace) { - if ( isset($trace['file'], $loadedTemplates[$trace['file']]) ) { $class = $loadedTemplates[ $trace['file'] ]; + $content = include($trace['file']); - + $this->file = $content['view']; - $this->line = $compiledObject->getSourceLineFromException($trace['line']); + $this->line = $class::getSourceLineFromException($trace['line']); return; } } - - - #if ( $template ) { - # $this->redefineErrorState($classContent); - #} } protected function getTemplateFile(string $filePath) : ? array @@ -123,10 +119,14 @@ class Picea implements LanguageRegistration * @param array $variables * @return type */ - public function inlineHtml(? object $proxy, string $viewPath, ... $variables) { - return $this->renderHtml($viewPath, [ 'inlineVariables' => $variables ], $proxy); + public function inlineHtml(? object $proxy, string $viewPath, array $variables) { + return $this->renderHtml($viewPath, $variables, $proxy); } + public function inlineBlock(? object $proxy, string $viewPath, ... $variables) { + return $this->renderHtml($viewPath, [ 'inlineVariables' => $variables ], $proxy); + } + public function inlineContent(string $viewPath) { return $this->fileFetcher->getFileContent($viewPath); } @@ -140,21 +140,6 @@ class Picea implements LanguageRegistration return $object; } - #public function outputHtml(string $viewPath, array $variables) : ResponseInterface - #{ - # if ( $this->response ?? false ) { - # if ( false === $content = $this->cache->handle($viewPath) ) { - # - # } - - # $source = $this->compileSource($source ?? "test"); - # $response = $this->response; - # return $response("abc"); - # } - - # throw new \InvalidArgumentException("No \Psr\Http\Message\ResponseInterface closure provided. Please provide one using the constructor or assigning it to the class variable `responseHtml`."); - #} - public function compileSource(string $source) : array { $this->compiler->loadSourceCode($source);