10 Commits
26 changed files with 348 additions and 97 deletions

No files matched your search

+2 -2
View File
@@ -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 &lt;safe&gt; 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';
+49 -1
View File
@@ -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>
```
View File
Whitespace-only changes.
+4
View File
@@ -0,0 +1,4 @@
# Extension - Creating an extension
+4
View File
@@ -0,0 +1,4 @@
# Extension - `json`, `json.pretty`, `json.html`
This extension
+1 -1
View File
@@ -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 };
+19 -3
View File
@@ -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']);
+8
View File
@@ -0,0 +1,8 @@
<?php declare(strict_types=1);
namespace Picea\Builder;
class ClassTemplateEvent
{
use \Picea\EventTrait;
}
+27 -10
View File
@@ -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
+10
View File
@@ -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;
+5 -3
View File
@@ -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;
}
+32 -8
View File
@@ -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;
}
+29
View File
@@ -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);
}
}
}
+7
View File
@@ -0,0 +1,7 @@
<?php
namespace Picea\Exception;
use Picea\Picea;
class RegisterExtensionToken extends \Exception {}
+9 -8
View File
@@ -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);
},
];
}
+47 -10
View File
@@ -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;
}
};
}
}
+7 -6
View File
@@ -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) ?>";
}
+3 -1
View File
@@ -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':
+14 -12
View File
@@ -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
+30 -21
View File
@@ -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
View File
@@ -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
View File
@@ -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);