From 08211282c2576b21f6119293ed9b9a11fbe2be58 Mon Sep 17 00:00:00 2001 From: Dave Mc Nicoll Date: Thu, 26 Jan 2023 13:32:52 +0000 Subject: [PATCH] - Added an event manager. Also, fixed some more bugs within Block and Section tokens --- src/Builder/ClassTemplate.php | 20 +++++++++-- src/Builder/ClassTemplateEvent.php | 8 +++++ src/Compiler.php | 9 +++-- src/ControlStructure/BlockToken.php | 8 +++-- src/ControlStructure/SectionToken.php | 20 ++++++++--- src/Event/Builder/ClassTemplateOutputDone.php | 7 ++++ src/Event/Builder/ClassTemplateOutputing.php | 7 ++++ .../Builder/ClassTemplateRenderSection.php | 7 ++++ .../ClassTemplateRenderSectionDone.php | 7 ++++ src/EventTrait.php | 29 +++++++++++++++ src/Extension/LanguageExtension.php | 35 ++++++++++++++++++- src/Extension/TitleExtension.php | 8 ++++- src/Extension/UrlExtension.php | 13 +++++-- src/Picea.php | 4 +-- 14 files changed, 164 insertions(+), 18 deletions(-) create mode 100644 src/Builder/ClassTemplateEvent.php create mode 100644 src/Event/Builder/ClassTemplateOutputDone.php create mode 100644 src/Event/Builder/ClassTemplateOutputing.php create mode 100644 src/Event/Builder/ClassTemplateRenderSection.php create mode 100644 src/Event/Builder/ClassTemplateRenderSectionDone.php create mode 100644 src/EventTrait.php diff --git a/src/Builder/ClassTemplate.php b/src/Builder/ClassTemplate.php index 017cdb9..44ed59c 100644 --- a/src/Builder/ClassTemplate.php +++ b/src/Builder/ClassTemplate.php @@ -8,10 +8,13 @@ namespace %NAMESPACE%; if (! class_exists("%NAMESPACE%\%CLASSNAME%", false) ) { class %CLASSNAME% %EXTENDS% { + public array $blockList = []; public array $sectionList = []; + public array $sectionStack = []; + public array $variableList = []; public ?object $thisProxy = null; @@ -24,6 +27,8 @@ if (! class_exists("%NAMESPACE%\%CLASSNAME%", false) ) { public bool $renderingInsideSection = false; + public int $depth = 0; + public function __construct(\Picea\Picea $picea, array $variablesList = [], ?object $thisProxy = null) { $this->picea = $picea; $this->variableList = $variablesList; @@ -37,15 +42,26 @@ if (! class_exists("%NAMESPACE%\%CLASSNAME%", false) ) { public function output(array $variablesList = []) : void { + $__event = new \Picea\Builder\ClassTemplateEvent(); + $this->rendering = true; - ( function($___class__template, $___global_variables, $___variables, $picea) { + $this->depth++; + + $__event->eventExecute(\Picea\Event\Builder\ClassTemplateOutputing::class, $variablesList); + + ( function($___class__template, $___global_variables, $___variables, $__event, $picea) { extract($___global_variables); extract($___variables, \EXTR_OVERWRITE); ?>%CONTENT%call($this->thisProxy ?? new class(){}, $this, $this->variableList, $variablesList, $this->picea); + } )->call($this->thisProxy ?? new class() {}, $this, $this->variableList, $variablesList, $__event, $this->picea); + + $__event->eventExecute(\Picea\Event\Builder\ClassTemplateOutputDone::class, $variablesList); + %PARENT_OUTPUT% + $this->depth--; + $this->rendering = false; } diff --git a/src/Builder/ClassTemplateEvent.php b/src/Builder/ClassTemplateEvent.php new file mode 100644 index 0000000..dcbcdfb --- /dev/null +++ b/src/Builder/ClassTemplateEvent.php @@ -0,0 +1,8 @@ +extensionList[$name] ?? false ) { + if ( ! isset($this->extensionList[$name]) ) { throw new \InvalidArgumentException(<<extensionList[$name]; } diff --git a/src/ControlStructure/BlockToken.php b/src/ControlStructure/BlockToken.php index ed581e8..5999a2f 100644 --- a/src/ControlStructure/BlockToken.php +++ b/src/ControlStructure/BlockToken.php @@ -49,7 +49,9 @@ class BlockToken implements ControlStructure { $def = 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; + if ($def->hasDefinitions() ) { $slotName = eval("return $name;"); $def->currentSlot = $slotName; @@ -62,7 +64,7 @@ class BlockToken implements ControlStructure { } return <<printSlot($name, function($definition array \$___using = []) use (\$picea) { extract(\$___using, \EXTR_SKIP); ?> + printSlot($name, function($definition array \$___using = []) use (\$picea $loops) { extract(\$___using, \EXTR_SKIP); ?> PHP; } else { @@ -71,7 +73,7 @@ class BlockToken implements ControlStructure { } return <<slotIsSet($name) || \$___block->setSlot($name, function($definition array \$___using = []) use (\$picea) { extract(\$___using, \EXTR_SKIP); ?> + slotIsSet($name) || \$___block->setSlot($name, function($definition array \$___using = []) use (\$picea $loops) { extract(\$___using, \EXTR_SKIP); ?> PHP; } diff --git a/src/ControlStructure/SectionToken.php b/src/ControlStructure/SectionToken.php index 0f0040a..1da7f68 100644 --- a/src/ControlStructure/SectionToken.php +++ b/src/ControlStructure/SectionToken.php @@ -46,14 +46,26 @@ class SectionToken implements ControlStructure { $order = $options['order'] ?? "count(\$___class__template->sectionList[$name]['$action'])"; return "sectionList[$name] ??= [ 'prepend' => [], 'append' => [], 'default' => [] ];". - "\$___class__template->sectionList[$name]['$action'][] = [ 'order' => $order, 'callback' => function() use (\$picea, \$___class__template, \$___global_variables, \$___variables) {". - "extract(\$___global_variables); extract(\$___variables, \EXTR_OVERWRITE); \$___class__template->sectionStack[] = '$name'; ?>"; + "\$___class__template->sectionList[$name]['$action'][] = [ + 'order' => $order, + 'callback' => function() use (\$picea, \$___class__template, \$___global_variables, \$___variables, \$__event) {". + "extract(\$___global_variables); extract(\$___variables, \EXTR_OVERWRITE); + \$___class__template->sectionStack[] = $name; + \$__event->eventExecute(\Picea\Event\Builder\ClassTemplateRenderSection::class, $name);?>"; } protected function printEndSection($context) : string { $section = array_pop($context->sections); - $build = $context->extendFrom ? "!empty(\$___class__template->sectionStack) && \$___class__template->renderSection({$section['name']});" : "\$___class__template->renderSection({$section['name']});"; - return "sectionStack); }]; $build?>"; + $build = $context->extendFrom ? "!empty(\$___class__template->sectionStack) && \$___class__template->renderSection({$section['name']}, false);" : "\$___class__template->renderSection({$section['name']}, false);"; + + return <<eventExecute(\Picea\Event\Builder\ClassTemplateRenderSectionDone::class, {$section['name']}); + array_pop(\$___class__template->sectionStack); }]; + $build + ?> + PHP; + } } \ No newline at end of file diff --git a/src/Event/Builder/ClassTemplateOutputDone.php b/src/Event/Builder/ClassTemplateOutputDone.php new file mode 100644 index 0000000..e44e74a --- /dev/null +++ b/src/Event/Builder/ClassTemplateOutputDone.php @@ -0,0 +1,7 @@ +_eventList[] = $event; + } + + public function eventFromType(string $type) : array + { + return array_filter($this->_eventList, fn($ev) => $ev instanceof $type); + } + + public function eventExecute(string $type, ...$arguments) : void + { + foreach($this->eventFromType($type) as $event) { + $this->_returnList[$event::class][] = call_user_func_array([ $event, $this->_eventTraitMethod ], $arguments); + } + } +} \ No newline at end of file diff --git a/src/Extension/LanguageExtension.php b/src/Extension/LanguageExtension.php index 3db89f8..fbbb7c4 100644 --- a/src/Extension/LanguageExtension.php +++ b/src/Extension/LanguageExtension.php @@ -3,6 +3,7 @@ namespace Picea\Extension; use Picea\Compiler\Context; +use Picea\Event\Builder\ClassTemplateRenderSectionDone; class LanguageExtension implements Extension, FunctionExtension { @@ -28,7 +29,22 @@ class LanguageExtension implements Extension, FunctionExtension { { switch($token) { case "language.set": - return "compiler->getExtensionFromToken('$token')->currentLanguage = $arguments; ?>"; + $cls = $this::class; + + return <<getParam('extends'); + + if ( \$___class__template->depth === 1 || \$___class__template->sectionStack ) { + \$ext->currentLanguage = $arguments; + + # @TODO Make sure this event is only registered when we output() a template, if we are in a section, we must attach it a view/section/block output event instead ! + \$__event->eventRegister(\\$cls::outputDoneEvent(\$ext)); + } + })(\$picea->compiler->getExtensionFromToken('$token')); + ?> + PHP; case "lang": return "compiler->getExtensionFromToken('$token')->absoluteLang($arguments), \ENT_QUOTES, ini_get('default_charset'), true) ?>"; @@ -59,4 +75,21 @@ class LanguageExtension implements Extension, FunctionExtension { { return $this->languageHandler->languageFromKey($key, $variables); } + + public static function outputDoneEvent(LanguageExtension $languageExtension) : ClassTemplateRenderSectionDone + { + return new class($languageExtension) implements ClassTemplateRenderSectionDone { + + protected string $current; + + public function __construct(protected LanguageExtension $languageExtension) { + $this->current = $this->languageExtension->currentLanguage; + } + + public function execute(string $name) : mixed + { + return $this->current ? $this->languageExtension->currentLanguage = $this->current : null; + } + }; + } } diff --git a/src/Extension/TitleExtension.php b/src/Extension/TitleExtension.php index 8c521df..03b4ad3 100644 --- a/src/Extension/TitleExtension.php +++ b/src/Extension/TitleExtension.php @@ -16,7 +16,13 @@ class TitleExtension implements Extension, FunctionExtension { } public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) { - return ""; + return << + PHP; } public function handleTitle(? string $set = null, ...$arguments) : ? string diff --git a/src/Extension/UrlExtension.php b/src/Extension/UrlExtension.php index 1404b0c..694bff9 100644 --- a/src/Extension/UrlExtension.php +++ b/src/Extension/UrlExtension.php @@ -48,7 +48,9 @@ PATTERN; return "compiler->getExtensionFromToken('$token')->setUrlParameters($arguments) ?>"; case "slug": - return \Transliterator::createFromRules(':: Any-Latin;:: NFD;:: [:Nonspacing Mark:] Remove;:: NFC;:: [:Punctuation:] Remove;:: Lower();[:Separator:] > \'-\'')->transliterate( $arguments ); + return "compiler->getExtensionFromToken('$token')->slug($arguments) ?>"; + + #return \Transliterator::createFromRules(':: Any-Latin;:: NFD;:: [:Nonspacing Mark:] Remove;:: NFC;:: [:Punctuation:] Remove;:: Lower();[:Separator:] > \'-\'')->transliterate( $arguments ); } return null; @@ -121,9 +123,14 @@ PATTERN; return $this->scheme() . $this->domain() . $this->base(); } + # src: https://stackoverflow.com/a/14550919 public static function slug(string $text, string $separator = '-') : string { - return trim(str_replace('-', $separator, \Transliterator::createFromRules(':: Any-Latin;:: NFD;:: [:Nonspacing Mark:] Remove;:: NFC;:: [:Punctuation:] Remove;:: Lower();[:Separator:] > \'-\'')->transliterate(str_replace('-', ' ', $text))), '-'); + $clean = iconv('UTF-8', 'ASCII//TRANSLIT', $text); + $clean = preg_replace("/[^a-zA-Z0-9\/_| -]/", '', $clean); + + return preg_replace("/[\/_| -]+/", $separator, strtolower(trim($clean, '-'))); + } public function registerRoute(string $name, string $route, string $class, string $method, array $routeMethods) : void @@ -195,7 +202,7 @@ PATTERN; $_SERVER['Front-End-Https'] ?? "", $_SERVER['X-Forwarded-Proto'] ?? "", $_SERVER['X-Forwarded-Protocol'] ?? "", - $_SERVER['HTTP_X_FORWARDED_PROTO'] ?? "", + $_SERVER['HTTP_X_FORWARDED_PROTO'] ?? "", $_SERVER['HTTP_X_FORWARDED_PROTOCOL'] ?? "", ])) || isset($_SERVER['HTTP_X_ARR_SSL']); diff --git a/src/Picea.php b/src/Picea.php index 5801a1d..5879360 100644 --- a/src/Picea.php +++ b/src/Picea.php @@ -54,7 +54,7 @@ class Picea implements LanguageRegistration $this->renderContext($this->context); } - public function gatherTemplateObject(string $viewPath, array $variables = [], ? object $proxy = null) : ? object + public function gatherCompiledObject(string $viewPath, array $variables = [], ? object $proxy = null) : ? object { if ( null === $object = $this->fetchFromCache($viewPath, $this->globalVariables + $variables, $proxy) ) { throw new \RuntimeException("An error occured while trying to save a compiled template."); @@ -65,7 +65,7 @@ class Picea implements LanguageRegistration public function renderHtml(string $viewPath, array $variables = [], ?object $proxy = null) : ? string { - $object = $this->gatherTemplateObject($viewPath, $variables, $proxy); + $object = $this->gatherCompiledObject($viewPath, $variables, $proxy); try { return call_user_func($object);