Compare commits
10
Commits
46535c2734
...
tokens_v2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
acd9f8c72e | ||
|
|
afeb8789b5 | ||
|
|
ded3d5e907 | ||
|
|
9ea4856f49 | ||
|
|
84020a871c | ||
|
|
2dc16de7c3 | ||
|
|
af212b07ca | ||
|
|
58766decaf | ||
|
|
08211282c2 | ||
|
|
58f73d914b |
No files matched your search
+2
-2
@@ -30,7 +30,7 @@ Using `print` or `echo`, which are, by default, made safer by using PHP's native
|
||||
|
||||
**[PHP]** Would yield internally:
|
||||
|
||||
```php
|
||||
```html
|
||||
<?php echo htmlspecialchars((string) "Hello World !", 3, 'UTF-8', true) ?>
|
||||
|
||||
<?php echo htmlspecialchars((string) "This is another way to output <safe> content", 3, 'UTF-8', true) ?>
|
||||
@@ -63,7 +63,7 @@ Those tokens represents the equivalent of the printf() function from PHP.
|
||||
|
||||
**[PHP]** Would render internally as :
|
||||
|
||||
```php
|
||||
```html
|
||||
<?php
|
||||
$num = 5;
|
||||
$location = 'tree';
|
||||
|
||||
@@ -119,4 +119,52 @@ We could use the previous file `path/home` and generate, let's say, the same pag
|
||||
</html>
|
||||
```
|
||||
|
||||
Notice that the `<header>` tag is now empty, since we've redeclared it in our navless view.
|
||||
Notice that the `<header>` tag is now empty, since we've redeclared it in our navless view.
|
||||
|
||||
## Overview of `section` (string $name, array $options)
|
||||
|
||||
In your `$name` variable, accepted characters are alpha-numeric and those specific caracters : `.-_:`, so
|
||||
names suches as :
|
||||
|
||||
`body.content`
|
||||
`my-cool-section:heading`
|
||||
`MyOtherSection`
|
||||
`_another_accepted_name`
|
||||
|
||||
Allowed options are :
|
||||
|
||||
string `action` : allowed are `prepend`, `default`, `append`
|
||||
int `order` : if you must
|
||||
|
||||
### Actions can also be passed using specials tokens :
|
||||
|
||||
`section.prepend` and `section.append` can also be used without passing an `action` option.
|
||||
|
||||
*path/home-nav.phtml*
|
||||
```html
|
||||
{% extends "path/home" %}
|
||||
|
||||
{% section "header" %}
|
||||
<a href="#mylink">First link here !</a>
|
||||
{% endsection %}
|
||||
```
|
||||
|
||||
*path/home-admin-nav.phtml*
|
||||
```html
|
||||
{% extends "path/home-nav" %}
|
||||
|
||||
{% section.prepend "header" %}
|
||||
<h4>My new NAV header</h4>
|
||||
{% endsection %}
|
||||
|
||||
{% section.append "header" %}
|
||||
<a href="#mylink">Second link here !</a>
|
||||
{% endsection %}
|
||||
```
|
||||
|
||||
**[HTML]** Would render as such :
|
||||
```html
|
||||
<h4>My new NAV header</h4>
|
||||
<a href="#mylink">First link here !</a>
|
||||
<a href="#mylink">Second link here !</a>
|
||||
```
|
||||
Whitespace-only changes.
@@ -0,0 +1,4 @@
|
||||
# Extension - Creating an extension
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# Extension - `json`, `json.pretty`, `json.html`
|
||||
|
||||
This extension
|
||||
|
||||
@@ -7,7 +7,7 @@ It also insert `Tell` inside the LanguageHandler which handles the `{% _ 'relati
|
||||
```php
|
||||
use function DI\autowire, DI\create, DI\get;
|
||||
|
||||
use Zend\Diactoros\Response\HtmlResponse;
|
||||
use Laminas\Diactoros\Response\HtmlResponse;
|
||||
|
||||
use Picea\{ Picea, Caching\Cache, Caching\Opcache, Compiler, Compiler\Context, Compiler\BaseContext, FileFetcher, Language\DefaultRegistrations, Method\Request };
|
||||
use Picea\Extension\{ LanguageHandler, LanguageExtension, TitleExtension, MoneyExtension, UrlExtension };
|
||||
|
||||
@@ -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%<?php
|
||||
} )->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;
|
||||
}
|
||||
|
||||
@@ -54,7 +70,7 @@ if (! class_exists("%NAMESPACE%\%CLASSNAME%", false) ) {
|
||||
$result = [];
|
||||
|
||||
foreach([ 'prepend', 'default', 'append' ] as $item) {
|
||||
if ( ! is_array($this->sectionList[$name][$item]) ) continue;
|
||||
if ( !isset($this->sectionList[$name][$item]) || ! is_array($this->sectionList[$name][$item]) ) continue;
|
||||
|
||||
usort($this->sectionList[$name][$item], fn($a, $b) => $a['order'] <=> $b['order']);
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Picea\Builder;
|
||||
|
||||
class ClassTemplateEvent
|
||||
{
|
||||
use \Picea\EventTrait;
|
||||
}
|
||||
+27
-10
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Picea;
|
||||
|
||||
use Picea\Exception\RegisterExtensionToken;
|
||||
use Picea\Extension\FunctionExtension;
|
||||
use Picea\Language\LanguageRegistration;
|
||||
|
||||
@@ -47,18 +48,19 @@ class Compiler
|
||||
$matches[2] = trim($matches[2]);
|
||||
|
||||
list($token, $arguments) = array_pad(array_filter(explode(' ', $matches[2], 2), 'strlen'), 2, null);
|
||||
|
||||
|
||||
$token = strtolower(trim($token));
|
||||
$tokenName = explode('.', $token, 2)[0];
|
||||
|
||||
# @TODO Refractor this parts to allows registration to the tag's name
|
||||
if ( $this->tagList[$token] ?? false ) {
|
||||
return $this->tagList[$token]->parse($context, $arguments, $token);
|
||||
if ( $this->tagList[$tokenName] ?? false ) {
|
||||
return $this->tagList[$tokenName]->parse($context, $arguments, $token);
|
||||
}
|
||||
elseif ( $this->extensionList[$token] ?? false ) {
|
||||
return $this->extensionList[$token]->parse($context, $arguments, $token);
|
||||
elseif ( $this->extensionList[$tokenName] ?? false ) {
|
||||
return $this->extensionList[$tokenName]->parse($context, $arguments, $token);
|
||||
}
|
||||
else {
|
||||
throw new \LogicException("Impossible to find token `$token` declared in `{$matches[2]}`. Perhapse you forgot to add a custom token to Picea's engine ?");
|
||||
throw new \LogicException("Impossible to find token `$tokenName` declared in `{$matches[2]}`. Perhapse you forgot to add a custom token to Picea's engine ?");
|
||||
}
|
||||
|
||||
}, $this->sourceCode);
|
||||
@@ -87,6 +89,10 @@ class Compiler
|
||||
public function registerControlStructure(ControlStructure\ControlStructure $controlStructureObject) : self
|
||||
{
|
||||
foreach($controlStructureObject->tokens ?? (array) ( $controlStructureObject->token ?? [] ) as $token) {
|
||||
if ( strpos($token, '.') !== false ) {
|
||||
throw new RegisterExtensionToken(sprintf("Could not register token '%s' from control structure '%s' in this version. Options are now delt by extensions themselve instead.", $token, $controlStructureObject::class));
|
||||
}
|
||||
|
||||
$this->tagList[strtolower($token)] = $controlStructureObject;
|
||||
}
|
||||
|
||||
@@ -98,6 +104,10 @@ class Compiler
|
||||
$tokens = $extension->tokens ?? (array) ( $extension->token ?? [] );
|
||||
|
||||
foreach($tokens as $token) {
|
||||
if ( strpos($token, '.') !== false ) {
|
||||
throw new RegisterExtensionToken(sprintf("Could not register token '%s' from extension '%s' in this version. Options are now delt by extensions themselve instead.", $token, $extension::class));
|
||||
}
|
||||
|
||||
$this->extensionList[strtolower($token)] = $extension;
|
||||
}
|
||||
|
||||
@@ -122,15 +132,22 @@ class Compiler
|
||||
|
||||
}
|
||||
|
||||
public function __toString() : string
|
||||
{
|
||||
return "WHATAFAK";
|
||||
}
|
||||
|
||||
public function getExtensionFromToken(string $name) : Extension\Extension
|
||||
{
|
||||
if ( false === $this->extensionList[$name] ?? false ) {
|
||||
$tokenName = explode('.', $name)[0];
|
||||
|
||||
if ( ! isset($this->extensionList[$tokenName]) ) {
|
||||
throw new \InvalidArgumentException(<<<MSG
|
||||
Requested extension from token `$name` could not be found from loaded Picea compiler's extension.
|
||||
Requested extension from token `$tokenName` could not be found from loaded Picea compiler's extension.
|
||||
MSG);
|
||||
}
|
||||
|
||||
return $this->extensionList[$name];
|
||||
|
||||
return $this->extensionList[$tokenName];
|
||||
}
|
||||
|
||||
public function exportFunctions() : void
|
||||
|
||||
@@ -14,6 +14,8 @@ abstract class Context {
|
||||
|
||||
public string $compiledSource = "";
|
||||
|
||||
public ? string $sectionAction = null;
|
||||
|
||||
public string $viewPath = "";
|
||||
|
||||
public string $filePath = "";
|
||||
@@ -86,6 +88,14 @@ abstract class Context {
|
||||
|
||||
}
|
||||
|
||||
public function tokenOptions(string $token, bool $export = false) : array|string
|
||||
{
|
||||
$options = explode('.', strtolower($token));
|
||||
array_shift($options);
|
||||
|
||||
return $export ? var_export($options, true) : $options;
|
||||
}
|
||||
|
||||
public function pushFunction($name, Callable $callable) : void
|
||||
{
|
||||
$this->functionStack[$name] = $callable;
|
||||
|
||||
@@ -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 <<<PHP
|
||||
<?php \$this->printSlot($name, function($definition array \$___using = []) use (\$picea) { extract(\$___using, \EXTR_SKIP); ?>
|
||||
<?php \$this->printSlot($name, function($definition array \$___using = []) use (\$picea $loops) { extract(\$___using, \EXTR_SKIP); ?>
|
||||
PHP;
|
||||
}
|
||||
else {
|
||||
@@ -71,7 +73,7 @@ class BlockToken implements ControlStructure {
|
||||
}
|
||||
|
||||
return <<<PHP
|
||||
<?php (\$___block ?? \$this)->slotIsSet($name) || \$___block->setSlot($name, function($definition array \$___using = []) use (\$picea) { extract(\$___using, \EXTR_SKIP); ?>
|
||||
<?php (\$___block ?? \$this)->slotIsSet($name) || \$___block->setSlot($name, function($definition array \$___using = []) use (\$picea $loops) { extract(\$___using, \EXTR_SKIP); ?>
|
||||
PHP;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,11 +6,21 @@ class SectionToken implements ControlStructure {
|
||||
|
||||
public array $token = [ "section", "endsection" ];
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token)
|
||||
{
|
||||
$opt = $context->tokenOptions($token);
|
||||
|
||||
if (in_array('prepend', $opt)) {
|
||||
$context->sectionAction = "prepend";
|
||||
}
|
||||
elseif (in_array('append', $opt)) {
|
||||
$context->sectionAction = "append";
|
||||
}
|
||||
|
||||
switch($token) {
|
||||
case "section":
|
||||
return $this->printSection($context, $arguments);
|
||||
|
||||
|
||||
case "endsection":
|
||||
if ( empty($context->sections) ) {
|
||||
throw new \RuntimeException("A section closing tag {% endsection %} was found without an opening {% section %} tag");
|
||||
@@ -28,7 +38,7 @@ class SectionToken implements ControlStructure {
|
||||
$options = eval("return $options;");
|
||||
}
|
||||
|
||||
if ( ! ctype_alnum(str_replace([".", "\"", "'", "-", "_"], "", $name)) ) {
|
||||
if ( ! ctype_alnum(str_replace([".", "\"", "'", "-", "_", ":"], "", $name)) ) {
|
||||
throw new \RuntimeException("Your section named `{$name}` contains invalid character. Allowed are only letters, numbers, dashes, underscores and dots");
|
||||
}
|
||||
|
||||
@@ -37,7 +47,9 @@ class SectionToken implements ControlStructure {
|
||||
'options' => $options,
|
||||
];
|
||||
|
||||
$action = $options['action'] ?? "default";
|
||||
$action = $options['action'] ?? $context->sectionAction ?? "default";
|
||||
|
||||
unset($context->sectionAction);
|
||||
|
||||
if (! in_array($action, ['prepend', 'append', 'default'])) {
|
||||
throw new \RuntimeException("An unsupported action `$action` was given as an option of a {% section %} tag");
|
||||
@@ -46,14 +58,26 @@ class SectionToken implements ControlStructure {
|
||||
$order = $options['order'] ?? "count(\$___class__template->sectionList[$name]['$action'])";
|
||||
|
||||
return "<?php \$___class__template->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 "<?php array_pop(\$___class__template->sectionStack); }]; $build?>";
|
||||
$build = $context->extendFrom ? "!empty(\$___class__template->sectionStack) && \$___class__template->renderSection({$section['name']}, false);" : "\$___class__template->renderSection({$section['name']}, false);";
|
||||
|
||||
return <<<PHP
|
||||
<?php
|
||||
\$__event->eventExecute(\Picea\Event\Builder\ClassTemplateRenderSectionDone::class, {$section['name']});
|
||||
array_pop(\$___class__template->sectionStack); }];
|
||||
$build
|
||||
?>
|
||||
PHP;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Picea\Event\Builder;
|
||||
|
||||
interface ClassTemplateOutputDone {
|
||||
public function execute(string $name, array $variablesList) : mixed;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Picea\Event\Builder;
|
||||
|
||||
interface ClassTemplateOutputing {
|
||||
public function execute(string $name, array $variablesList) : mixed;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Picea\Event\Builder;
|
||||
|
||||
interface ClassTemplateRenderSection {
|
||||
public function execute(string $name) : mixed;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Picea\Event\Builder;
|
||||
|
||||
interface ClassTemplateRenderSectionDone {
|
||||
public function execute(string $section) : mixed;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Picea;
|
||||
|
||||
trait EventTrait
|
||||
{
|
||||
protected $_eventTraitMethod = "execute";
|
||||
|
||||
public array $_eventList = [];
|
||||
|
||||
protected array $_returnList = [];
|
||||
|
||||
public function eventRegister(object $event) : void
|
||||
{
|
||||
$this->_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Picea\Exception;
|
||||
|
||||
use Picea\Picea;
|
||||
|
||||
class RegisterExtensionToken extends \Exception {}
|
||||
@@ -6,21 +6,22 @@ use Picea\Compiler\Context;
|
||||
|
||||
class JsonExtension implements Extension, FunctionExtension {
|
||||
|
||||
public array $token = [ "json", "json.pretty", "json.html" ];
|
||||
public array $token = [ "json" ];
|
||||
|
||||
public int $flags = JSON_HEX_TAG | \JSON_HEX_QUOT | \JSON_THROW_ON_ERROR | \JSON_UNESCAPED_UNICODE;
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token)
|
||||
{
|
||||
$opt = $context->tokenOptions($token);
|
||||
|
||||
$flag = $this->flags;
|
||||
|
||||
switch ($token) {
|
||||
case "json.pretty":
|
||||
$flag |= \JSON_PRETTY_PRINT;
|
||||
break;
|
||||
if ( in_array('pretty', $opt) ) {
|
||||
$flag |= \JSON_PRETTY_PRINT;
|
||||
}
|
||||
|
||||
case "json.html":
|
||||
return "<?php echo htmlentities(json_encode($arguments, {$this->flags}), ENT_QUOTES, 'UTF-8') ?>";
|
||||
if ( in_array('html', $opt) ) {
|
||||
return "<?php echo htmlentities(json_encode($arguments, $flag), ENT_QUOTES, 'UTF-8') ?>";
|
||||
}
|
||||
|
||||
$cls = static::class;
|
||||
@@ -32,7 +33,7 @@ class JsonExtension implements Extension, FunctionExtension {
|
||||
{
|
||||
return [
|
||||
'json' => function($arguments, ? int $flags = null) {
|
||||
return json_encode($arguments, \JSON_FORCE_OBJECT);
|
||||
return json_encode($arguments, $flags ?? $this->flags);
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
namespace Picea\Extension;
|
||||
|
||||
use Picea\Compiler\Context;
|
||||
use Picea\Event\Builder\ClassTemplateRenderSectionDone;
|
||||
|
||||
class LanguageExtension implements Extension, FunctionExtension {
|
||||
|
||||
public array $tokens = [ "lang", "lang.raw", "_", "_.raw", "language.set" ];
|
||||
public array $tokens = [ "lang", "_", "language" ];
|
||||
|
||||
public string $currentLanguage = "";
|
||||
|
||||
@@ -26,21 +27,40 @@ class LanguageExtension implements Extension, FunctionExtension {
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string
|
||||
{
|
||||
switch($token) {
|
||||
case "language.set":
|
||||
return "<?php \$picea->compiler->getExtensionFromToken('$token')->currentLanguage = $arguments; ?>";
|
||||
$opt = $context->tokenOptions($token);
|
||||
|
||||
switch(explode('.', $token)[0]) {
|
||||
case "language":
|
||||
$cls = $this::class;
|
||||
|
||||
return <<<PHP
|
||||
<?php
|
||||
(function(\\$cls \$ext) use (\$___class__template, \$__event) {
|
||||
#\$extends = \$___class__template->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":
|
||||
if ( in_array('raw', $opt) ) {
|
||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->absoluteLang($arguments) ?>";
|
||||
}
|
||||
|
||||
return "<?php echo htmlspecialchars(\$picea->compiler->getExtensionFromToken('$token')->absoluteLang($arguments), \ENT_QUOTES, ini_get('default_charset'), true) ?>";
|
||||
|
||||
case "lang.raw":
|
||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->absoluteLang($arguments) ?>";
|
||||
|
||||
case "_":
|
||||
return "<?php echo htmlspecialchars(\$picea->compiler->getExtensionFromToken('$token')->relativeLang($arguments), \ENT_QUOTES, ini_get('default_charset'), true) ?>";
|
||||
if ( in_array('raw', $opt) ) {
|
||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->relativeLang($arguments) ?>";
|
||||
}
|
||||
|
||||
case "_.raw":
|
||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->relativeLang($arguments) ?>";
|
||||
return "<?php echo htmlspecialchars(\$picea->compiler->getExtensionFromToken('$token')->relativeLang($arguments), \ENT_QUOTES, ini_get('default_charset'), true) ?>";
|
||||
}
|
||||
|
||||
return "";
|
||||
@@ -59,4 +79,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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ namespace Picea\Extension;
|
||||
|
||||
use Picea\Compiler\Context;
|
||||
|
||||
class MoneyExtension implements Extension {
|
||||
class MoneyExtension implements Extension, FunctionExtension {
|
||||
|
||||
public string $token = "money";
|
||||
|
||||
@@ -14,17 +14,18 @@ class MoneyExtension implements Extension {
|
||||
|
||||
public \NumberFormatter $formatter;
|
||||
|
||||
public function __construct(Context $context) {
|
||||
$this->register($context);
|
||||
public function __construct() {
|
||||
$this->locale = explode('.', \Locale::getDefault())[0];
|
||||
$this->formatter = new \NumberFormatter($this->locale, \NumberFormatter::CURRENCY);
|
||||
}
|
||||
|
||||
public function register(Context $context) : void
|
||||
public function exportFunctions(): array
|
||||
{
|
||||
$context->pushFunction("money", [ $this, 'money' ]);
|
||||
return [
|
||||
"money" => [ $this, 'money' ]
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
|
||||
return "<?php echo money($arguments) ?>";
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use Picea\Compiler\Context;
|
||||
|
||||
class PrintExtension implements Extension {
|
||||
|
||||
public array $token = [ "echo", "echo.raw", "print", "print.raw", "printf", "printf.raw" ];
|
||||
public array $token = [ "echo", "print", "printf" ];
|
||||
|
||||
public int $flag = \ENT_QUOTES;
|
||||
|
||||
@@ -20,6 +20,8 @@ class PrintExtension implements Extension {
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string
|
||||
{
|
||||
$opt = $context->tokenOptions($token);
|
||||
|
||||
switch($token) {
|
||||
case 'echo':
|
||||
case 'print':
|
||||
|
||||
@@ -2,25 +2,27 @@
|
||||
|
||||
namespace Picea\Extension;
|
||||
|
||||
use Picea\Compiler\Context;
|
||||
|
||||
class TitleExtension implements Extension {
|
||||
class TitleExtension implements Extension, FunctionExtension {
|
||||
|
||||
public string $token = "title";
|
||||
|
||||
public string $title = "";
|
||||
|
||||
public function __construct(Context $context) {
|
||||
$this->register($context);
|
||||
|
||||
public function exportFunctions(): array
|
||||
{
|
||||
return [
|
||||
"title" => [$this, 'handleTitle'],
|
||||
];
|
||||
}
|
||||
|
||||
public function register(Context $context) : void
|
||||
{
|
||||
$context->pushFunction("title", [ $this, 'handleTitle' ]);
|
||||
}
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
|
||||
return "<?php echo title($arguments) ?>";
|
||||
return <<<PHP
|
||||
<?php
|
||||
if ( null !== \$title = title($arguments) ) {
|
||||
echo \$title;
|
||||
}
|
||||
?>
|
||||
PHP;
|
||||
}
|
||||
|
||||
public function handleTitle(? string $set = null, ...$arguments) : ? string
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Picea\Extension;
|
||||
|
||||
use Picea\Compiler\Context;
|
||||
|
||||
class UrlExtension implements Extension {
|
||||
class UrlExtension implements Extension, FunctionExtension {
|
||||
|
||||
public const URLIZE_PATTERN_URL = <<<PATTERN
|
||||
~(?<!href=['"])https?://[\w/._\-&?]*(?!</a>)(?=[^\w/._\-&])~s
|
||||
@@ -22,16 +22,17 @@ PATTERN;
|
||||
|
||||
protected array $routesTarget;
|
||||
|
||||
public array $tokens = [ "url" , "route", "route.cacheless", "asset", "url.current", "url.parameters", "slug" ];
|
||||
public array $tokens = [ "url" , "route", "asset", "slug" ];
|
||||
|
||||
public function __construct(Context $context, string $urlBase = "", string $assetToken = "") {
|
||||
public function __construct(string $urlBase = "", string $assetToken = "") {
|
||||
$this->urlBase = trim($urlBase, "/");
|
||||
$this->assetToken = $assetToken;
|
||||
$this->register($context);
|
||||
}
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : ?string
|
||||
{
|
||||
$opt = $context->tokenOptions($token);
|
||||
|
||||
switch($token) {
|
||||
case "asset":
|
||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->buildAssetUrl($arguments) ?>";
|
||||
@@ -40,29 +41,32 @@ PATTERN;
|
||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->buildRouteUrl($arguments) ?>";
|
||||
|
||||
case "url":
|
||||
if ( in_array('parameters', $opt) ) {
|
||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->setUrlParameters($arguments) ?>";
|
||||
}
|
||||
elseif ( in_array('current', $opt) ) {
|
||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->currentUrl($arguments) ?>";
|
||||
}
|
||||
|
||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->buildUrl($arguments) ?>";
|
||||
|
||||
case "url.current":
|
||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->currentUrl($arguments) ?>";
|
||||
|
||||
case "url.parameters":
|
||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->setUrlParameters($arguments) ?>";
|
||||
|
||||
case "slug":
|
||||
return \Transliterator::createFromRules(':: Any-Latin;:: NFD;:: [:Nonspacing Mark:] Remove;:: NFC;:: [:Punctuation:] Remove;:: Lower();[:Separator:] > \'-\'')->transliterate( $arguments );
|
||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->slug($arguments) ?>";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function register(Context $context) : void
|
||||
|
||||
public function exportFunctions(): array
|
||||
{
|
||||
$context->pushFunction("url", [ $this, 'buildUrl' ]);
|
||||
$context->pushFunction("current_url", [ $this, 'currentUrl' ]);
|
||||
$context->pushFunction("asset", [ $this, 'buildAssetUrl' ]);
|
||||
$context->pushFunction("route", [ $this, 'buildRouteUrl' ]);
|
||||
$context->pushFunction("slug", [ $this, 'slug' ]);
|
||||
$context->pushFunction("urlize", [ $this, 'urlize' ]);
|
||||
return [
|
||||
"url" => [ $this, 'buildUrl' ],
|
||||
"current_url" => [ $this, 'currentUrl' ],
|
||||
"asset" => [ $this, 'buildAssetUrl' ],
|
||||
"route" => [ $this, 'buildRouteUrl' ],
|
||||
"slug" => [ $this, 'slug' ],
|
||||
"urlize" => [ $this, 'urlize' ]
|
||||
];
|
||||
}
|
||||
|
||||
public function getRouteList(bool $full = false) : array
|
||||
@@ -120,9 +124,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//IGNORE', $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
|
||||
@@ -194,7 +203,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']);
|
||||
|
||||
|
||||
+11
-9
@@ -7,10 +7,11 @@ use Picea\Extension\Extension,
|
||||
|
||||
use Picea\Compiler\Context;
|
||||
|
||||
use Picea\Extension\FunctionExtension;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class Request implements Extension {
|
||||
class Request implements Extension, FunctionExtension {
|
||||
use ExtensionTrait;
|
||||
|
||||
public array $tokens;
|
||||
@@ -21,20 +22,21 @@ class Request implements Extension {
|
||||
|
||||
public function __construct(ServerRequestInterface $request, Context $context) {
|
||||
$this->request = $request;
|
||||
$this->register($context);
|
||||
}
|
||||
|
||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string { }
|
||||
|
||||
public function register(Context $context) : void
|
||||
public function exportFunctions(): array
|
||||
{
|
||||
$context->pushFunction("cookie", [ $this, 'cookie' ]);
|
||||
$context->pushFunction("get", [ $this, 'get' ]);
|
||||
$context->pushFunction("post", [ $this, 'post' ]);
|
||||
$context->pushFunction("request", [ $this, 'request' ]);
|
||||
$context->pushFunction("server", [ $this, 'server' ]);
|
||||
return [
|
||||
"cookie" => [ $this, 'cookie' ],
|
||||
"get" => [ $this, 'get' ],
|
||||
"post" => [ $this, 'post' ],
|
||||
"request" => [ $this, 'request' ],
|
||||
"server" => [ $this, 'server' ],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function cookie(? string $variableName = null, $default = null)
|
||||
{
|
||||
return $variableName === null ? $this->request->getCookieParams() : static::arrayGet($this->request->getCookieParams(), $variableName) ?? $default;
|
||||
|
||||
+2
-2
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user