Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 131204d838 | |||
| 562950447e | |||
| 54f209f8e2 | |||
| 28210836cd | |||
| 1f771b1932 | |||
| 778f84116b | |||
|
|
722131d801 | ||
| 210c8ae0bd | |||
|
|
c975de0557 | ||
|
|
0c0ba39072 | ||
|
|
ef95576d74 | ||
|
|
e737e82d7e | ||
| 830a643a56 | |||
|
|
b24bbbc150 | ||
|
|
3ffb69342b | ||
| fa815a506e | |||
|
|
35a7bd4cf7 | ||
|
|
7970679894 | ||
| d22d26c9c8 | |||
|
|
934643214e |
@ -15,7 +15,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"psr/http-message": "^1.0"
|
"psr/http-message": "^2.0"
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"lean": {
|
"lean": {
|
||||||
|
|||||||
68
composer.lock
generated
68
composer.lock
generated
@ -1,68 +0,0 @@
|
|||||||
{
|
|
||||||
"_readme": [
|
|
||||||
"This file locks the dependencies of your project to a known state",
|
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
|
||||||
"This file is @generated automatically"
|
|
||||||
],
|
|
||||||
"content-hash": "9771fcd7256da80520a2d0d0f95bf311",
|
|
||||||
"packages": [
|
|
||||||
{
|
|
||||||
"name": "psr/http-message",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/php-fig/http-message.git",
|
|
||||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
|
||||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.3.0"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "1.0.x-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Psr\\Http\\Message\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "PHP-FIG",
|
|
||||||
"homepage": "http://www.php-fig.org/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Common interface for HTTP messages",
|
|
||||||
"homepage": "https://github.com/php-fig/http-message",
|
|
||||||
"keywords": [
|
|
||||||
"http",
|
|
||||||
"http-message",
|
|
||||||
"psr",
|
|
||||||
"psr-7",
|
|
||||||
"request",
|
|
||||||
"response"
|
|
||||||
],
|
|
||||||
"time": "2016-08-06T14:39:51+00:00"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"packages-dev": [],
|
|
||||||
"aliases": [],
|
|
||||||
"minimum-stability": "stable",
|
|
||||||
"stability-flags": [],
|
|
||||||
"prefer-stable": false,
|
|
||||||
"prefer-lowest": false,
|
|
||||||
"platform": [],
|
|
||||||
"platform-dev": []
|
|
||||||
}
|
|
||||||
@ -96,9 +96,9 @@ You can do so by using `define` and `slot`.
|
|||||||
```html
|
```html
|
||||||
{% arguments string $name, string $anchor, int $index = 0 %}
|
{% arguments string $name, string $anchor, int $index = 0 %}
|
||||||
|
|
||||||
{% define slot %}
|
{% define "attributes" %}
|
||||||
|
|
||||||
<a {% slot "attributes" %}href="{{ $anchor }}" tabindex="{{ $index }}"{% endslot %}>{{ $name }}"</a>
|
<a {% slot "attributes" %}{% endslot %} href="{{ $anchor }}" tabindex="{{ $index }}"{% endslot %}>{{ $name }}"</a>
|
||||||
```
|
```
|
||||||
|
|
||||||
**[HTML]** Would render the same as the `view` example :
|
**[HTML]** Would render the same as the `view` example :
|
||||||
|
|||||||
@ -12,7 +12,7 @@ use Picea\{
|
|||||||
Method\Request
|
Method\Request
|
||||||
};
|
};
|
||||||
|
|
||||||
use Picea\Extension\{ LanguageHandlerInterface, LanguageExtension, TitleExtension, NumberExtension, UrlExtension };
|
use Picea\Extension\{ LanguageHandlerInterface, LanguageExtension, TitleExtension, NumberExtension, UrlExtension, DiExtension };
|
||||||
|
|
||||||
return [
|
return [
|
||||||
Picea\Picea::class => function($c) {
|
Picea\Picea::class => function($c) {
|
||||||
@ -20,7 +20,10 @@ return [
|
|||||||
},
|
},
|
||||||
|
|
||||||
Context::class => function($c) {
|
Context::class => function($c) {
|
||||||
return new BaseContext($c->get(Lean\Lean::class)->getPiceaContext());
|
return new BaseContext(
|
||||||
|
defaultNamespace: $c->get(Lean\Lean::class)->getPiceaContext(),
|
||||||
|
declare: getenv('PICEA_DECLARE') ?? 'declare(strict_types=1)'
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
Compiler::class => autowire(Compiler::class),
|
Compiler::class => autowire(Compiler::class),
|
||||||
@ -38,6 +41,7 @@ return [
|
|||||||
$c->get(LanguageExtension::class),
|
$c->get(LanguageExtension::class),
|
||||||
$c->get(TitleExtension::class),
|
$c->get(TitleExtension::class),
|
||||||
$c->get(NumberExtension::class),
|
$c->get(NumberExtension::class),
|
||||||
|
$c->get(DiExtension::class),
|
||||||
$c->get(UrlExtension::class),
|
$c->get(UrlExtension::class),
|
||||||
$c->get(Request::class),
|
$c->get(Request::class),
|
||||||
], class_exists(\Taxus\Picea\Extension::class) ? [ $c->get(\Taxus\Picea\Extension::class) ] : [],
|
], class_exists(\Taxus\Picea\Extension::class) ? [ $c->get(\Taxus\Picea\Extension::class) ] : [],
|
||||||
@ -49,6 +53,8 @@ return [
|
|||||||
|
|
||||||
NumberExtension::class => autowire(NumberExtension::class),
|
NumberExtension::class => autowire(NumberExtension::class),
|
||||||
|
|
||||||
|
DiExtension::class => autowire(DiExtension::class),
|
||||||
|
|
||||||
UrlExtension::class => create(UrlExtension::class)->constructor(getenv("URL_BASE"), get('git.commit'), explode(',', getenv('APP_URL')), (bool) getenv('FORCE_SSL')),
|
UrlExtension::class => create(UrlExtension::class)->constructor(getenv("URL_BASE"), get('git.commit'), explode(',', getenv('APP_URL')), (bool) getenv('FORCE_SSL')),
|
||||||
|
|
||||||
Cache::class => create(Opcache::class)->constructor(getenv("CACHE_PATH"), get(Context::class)),
|
Cache::class => create(Opcache::class)->constructor(getenv("CACHE_PATH"), get(Context::class)),
|
||||||
|
|||||||
@ -21,7 +21,8 @@ class Builder
|
|||||||
|
|
||||||
$replace = [
|
$replace = [
|
||||||
'%NAMESPACE%' => $context->namespace,
|
'%NAMESPACE%' => $context->namespace,
|
||||||
'%USE%' => ( $uses = $context->renderUses() ) ? "use $uses;" : false,
|
'%USE%' => ( $uses = $context->renderUses() ) ? $uses : false,
|
||||||
|
'%DECLARE%' => $context->declare ? rtrim($context->declare, ';') . ';' : "",
|
||||||
'%CLASSNAME%' => $context->className,
|
'%CLASSNAME%' => $context->className,
|
||||||
'%PATHNAME%' => $path($context->viewPath),
|
'%PATHNAME%' => $path($context->viewPath),
|
||||||
'%FULLPATH%' => $path($context->filePath),
|
'%FULLPATH%' => $path($context->filePath),
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<?php
|
<?php %DECLARE%
|
||||||
|
|
||||||
namespace %NAMESPACE%;
|
namespace %NAMESPACE%;
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,25 @@ namespace Picea\Compiler;
|
|||||||
|
|
||||||
class BaseContext extends Context {
|
class BaseContext extends Context {
|
||||||
|
|
||||||
public function __construct(?string $defaultNamespace = null) {
|
public function __construct(
|
||||||
|
?string $defaultNamespace = null,
|
||||||
|
public string $namespace = "",
|
||||||
|
public string $extendFrom = "",
|
||||||
|
public string $className = "",
|
||||||
|
public string $compiledSource = "",
|
||||||
|
public ? string $sectionAction = null,
|
||||||
|
public string $viewPath = "",
|
||||||
|
public string $filePath = "",
|
||||||
|
public string $classPath = "",
|
||||||
|
public string $declare = "declare(strict_types=1);",
|
||||||
|
public array $switchStack = [],
|
||||||
|
public array $iterationStack = [],
|
||||||
|
public array $useStack = [],
|
||||||
|
public array $sections = [],
|
||||||
|
public int $functions = 0,
|
||||||
|
public array $functionStack = [],
|
||||||
|
public array $hooks = []
|
||||||
|
) {
|
||||||
if ( $defaultNamespace !== null ) {
|
if ( $defaultNamespace !== null ) {
|
||||||
$this->namespace = $defaultNamespace;
|
$this->namespace = $defaultNamespace;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,36 +6,6 @@ use Picea\Compiler;
|
|||||||
|
|
||||||
abstract class Context {
|
abstract class Context {
|
||||||
|
|
||||||
public string $namespace = "";
|
|
||||||
|
|
||||||
public string $extendFrom = "";
|
|
||||||
|
|
||||||
public string $className = "";
|
|
||||||
|
|
||||||
public string $compiledSource = "";
|
|
||||||
|
|
||||||
public ? string $sectionAction = null;
|
|
||||||
|
|
||||||
public string $viewPath = "";
|
|
||||||
|
|
||||||
public string $filePath = "";
|
|
||||||
|
|
||||||
public string $classPath = "";
|
|
||||||
|
|
||||||
public array $switchStack = [];
|
|
||||||
|
|
||||||
public array $iterationStack = [];
|
|
||||||
|
|
||||||
public array $useStack = [];
|
|
||||||
|
|
||||||
public array $sections = [];
|
|
||||||
|
|
||||||
public int $functions = 0;
|
|
||||||
|
|
||||||
public array $functionStack = [];
|
|
||||||
|
|
||||||
public array $hooks = [];
|
|
||||||
|
|
||||||
public Compiler $compiler;
|
public Compiler $compiler;
|
||||||
|
|
||||||
public function hook(string $path, Callable $callback) : self
|
public function hook(string $path, Callable $callback) : self
|
||||||
@ -57,7 +27,7 @@ abstract class Context {
|
|||||||
|
|
||||||
public function renderUses() : string
|
public function renderUses() : string
|
||||||
{
|
{
|
||||||
return implode(",", $this->useStack ?? []);
|
return implode(PHP_EOL, array_map(fn($use) => "use $use;", $this->useStack ?? []));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renderFunctions() : string
|
public function renderFunctions() : string
|
||||||
|
|||||||
@ -4,45 +4,43 @@ namespace Picea\ControlStructure;
|
|||||||
|
|
||||||
abstract class AbstractLoop implements ControlStructure {
|
abstract class AbstractLoop implements ControlStructure {
|
||||||
|
|
||||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
|
protected function openLoop(\Picea\Compiler\Context &$context, ?string $arguments, string $token,) : string
|
||||||
{
|
{
|
||||||
switch($token) {
|
$name = "$".uniqid("{$token}_");
|
||||||
case "while":
|
|
||||||
case "foreach":
|
|
||||||
$name = "$".uniqid("{$token}_");
|
|
||||||
|
|
||||||
$stack = array_filter($context->iterationStack ?? [], function($item) {
|
$stack = array_filter($context->iterationStack ?? [], function($item) {
|
||||||
return ! $item['or'];
|
return ! $item['or'];
|
||||||
});
|
});
|
||||||
|
|
||||||
$count = count($stack);
|
$count = count($stack);
|
||||||
|
|
||||||
if ( $count > 0 ) {
|
if ( $count > 0 ) {
|
||||||
$name .= "[" . end($stack)['uid'] . "]";
|
$name .= "[" . end($stack)['uid'] . "]";
|
||||||
}
|
|
||||||
|
|
||||||
$context->iterationStack[] = [
|
|
||||||
'or' => false,
|
|
||||||
'uid' => $name,
|
|
||||||
'token' => "end{$token}",
|
|
||||||
];
|
|
||||||
|
|
||||||
return "<?php $token ($arguments): $name = ( $name ?? 0 ) + 1; ?>";
|
|
||||||
|
|
||||||
case "endwhile":
|
|
||||||
case "endforeach":
|
|
||||||
$last = end($context->iterationStack);
|
|
||||||
|
|
||||||
if ( $last['or'] === false ) {
|
|
||||||
$output = "<?php $token; ?>";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$output = "<?php endif; if ( isset({$last['uid']}) ) unset({$last['uid']}); ?>";
|
|
||||||
}
|
|
||||||
|
|
||||||
array_pop($context->iterationStack);
|
|
||||||
|
|
||||||
return $output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$context->iterationStack[] = [
|
||||||
|
'or' => false,
|
||||||
|
'uid' => $name,
|
||||||
|
'token' => "end{$token}",
|
||||||
|
];
|
||||||
|
|
||||||
|
return "<?php $token ($arguments): \$__loop_index = $name = ( $name ?? 0 ) + 1; ?>";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function closeLoop(\Picea\Compiler\Context &$context, ?string $arguments, string $token,) : string
|
||||||
|
{
|
||||||
|
$last = end($context->iterationStack);
|
||||||
|
|
||||||
|
if ( $last['or'] === false ) {
|
||||||
|
$output = "<?php $token; ?>";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$output = "<?php endif; if ( isset({$last['uid']}) ) unset({$last['uid']}); ?>";
|
||||||
|
}
|
||||||
|
|
||||||
|
array_pop($context->iterationStack);
|
||||||
|
|
||||||
|
return $output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2,26 +2,35 @@
|
|||||||
|
|
||||||
namespace Picea\ControlStructure;
|
namespace Picea\ControlStructure;
|
||||||
|
|
||||||
|
use http\Exception\InvalidArgumentException;
|
||||||
|
|
||||||
class BlockToken implements ControlStructure {
|
class BlockToken implements ControlStructure {
|
||||||
|
|
||||||
public array $token = [ "arguments", "block", "endblock", "define", "slot", "endslot", "using" ];
|
public array $token = [ "arguments", "block", "endblock", "/block", "define", "slot", "endslot", "/slot", "using", "public", "private", "protected", "set" ];
|
||||||
|
|
||||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
|
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
|
||||||
{
|
{
|
||||||
|
static $depth = 0;
|
||||||
|
static $slotDepth = 0;
|
||||||
static $slotDefinitions = [];
|
static $slotDefinitions = [];
|
||||||
|
static $slotName = [];
|
||||||
|
$class= static::class;
|
||||||
|
|
||||||
|
# dump($slotDepth, $token, $arguments, $slotDefinitions);
|
||||||
|
|
||||||
switch($token) {
|
switch($token) {
|
||||||
case "block":
|
case "block":
|
||||||
$slotDefinitions[] = $this->slotDefinitions();
|
$slotDefinitions[] = $this->slotDefinitions();
|
||||||
|
$depth++;
|
||||||
|
|
||||||
return "<?php \$___block = \Picea\ControlStructure\BlockToken::instanciateBlock($arguments); ?>";
|
return "<?php \$___block = \Picea\ControlStructure\BlockToken::instanciateBlock($arguments); ?>";
|
||||||
|
|
||||||
|
case "/block":
|
||||||
case "endblock":
|
case "endblock":
|
||||||
|
$depth--;
|
||||||
return "<?php echo \$___block->render(\$___class__template); unset(\$___block); ?>";
|
return "<?php echo \$___block->render(\$___class__template); unset(\$___block); ?>";
|
||||||
|
|
||||||
case "arguments":
|
case "arguments":
|
||||||
$class = static::class;
|
|
||||||
|
|
||||||
return <<<PHP
|
return <<<PHP
|
||||||
<?php
|
<?php
|
||||||
try {
|
try {
|
||||||
@ -30,8 +39,10 @@ class BlockToken implements ControlStructure {
|
|||||||
unset(\$inlineVariables);
|
unset(\$inlineVariables);
|
||||||
}
|
}
|
||||||
catch(\TypeError \$ex) {
|
catch(\TypeError \$ex) {
|
||||||
|
\$showArgs = fn(\$e) => (\$type = gettype(\$e)) === 'object' ? \$e::class : \$type;
|
||||||
|
|
||||||
throw new \Exception(
|
throw new \Exception(
|
||||||
sprintf('A block awaiting arguments `%s` instead received `%s` with values `%s`', '$arguments', implode(', ', array_map('gettype', \$inlineVariables ?? [])), json_encode(\$inlineVariables))
|
sprintf('A block awaiting arguments (%s) instead received (%s) with values (%s)', '$arguments', implode(', ', array_map(\$showArgs, \$inlineVariables ?? [])), json_encode(\$inlineVariables))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
/*%EXCEPTION_LINE_BASE%*/?>
|
/*%EXCEPTION_LINE_BASE%*/?>
|
||||||
@ -40,32 +51,33 @@ class BlockToken implements ControlStructure {
|
|||||||
case "define":
|
case "define":
|
||||||
list($name, $definition) = array_pad(explode(',', $arguments, 2), 2, "");
|
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 <<<PHP
|
return <<<PHP
|
||||||
<?php \$this->defineSlot($name, function($definition) {}); ?>
|
<?php \$this->defineSlot($name, function($definition) {}); ?>
|
||||||
PHP;
|
PHP;
|
||||||
|
|
||||||
case "slot":
|
case "slot":
|
||||||
$def = end($slotDefinitions);
|
$def = ( $slotDefinitions[$depth] ?? end($slotDefinitions) );
|
||||||
|
|
||||||
list($name, $definition) = array_pad(explode(',', $arguments, 2), 2, "");
|
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;
|
$loops = count($context->iterationStack ?? []) ? ",". implode(', ', array_filter(array_column($context->iterationStack, 'uid'), fn($e) => strpos($e, '[') === false)) : null;
|
||||||
|
$slotDepth++;
|
||||||
|
|
||||||
if ($def->hasDefinitions() ) {
|
if ($def->hasDefinitions() ) {
|
||||||
$slotName = eval("return $name;");
|
$slotName[] = eval("return $name;");
|
||||||
$def->currentSlot = $slotName;
|
$def->currentSlot = end($slotName);
|
||||||
$def->setDefinitionVars($slotName, $definition);
|
$def->setDefinitionVars(end($slotName), $definition);
|
||||||
|
|
||||||
$definition = $def->printDefinition($slotName);
|
$definition = $def->printDefinition(end($slotName));
|
||||||
|
|
||||||
if ($definition) {
|
if ($definition) {
|
||||||
$definition .= ",";
|
$definition .= ",";
|
||||||
}
|
}
|
||||||
|
|
||||||
return <<<PHP
|
return <<<PHP
|
||||||
<?php \$this->printSlot($name, function($definition array \$___using = []) use (\$picea $loops) { extract(\$___using, \EXTR_SKIP); ?>
|
<?php \$this->printSlot($name, function($definition array \$___using = []) use (\$picea, \$___class__template $loops) { extract(\$___using, \EXTR_SKIP); ?>
|
||||||
PHP;
|
PHP;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -74,14 +86,17 @@ class BlockToken implements ControlStructure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return <<<PHP
|
return <<<PHP
|
||||||
<?php (\$___block ?? \$this)->slotIsSet($name) || \$___block->setSlot($name, function($definition array \$___using = []) use (\$picea $loops) { extract(\$___using, \EXTR_SKIP); ?>
|
<?php (\$___block ?? \$this)->slotIsSet($name) || (\$___block ?? \$this)->setSlot($name, function($definition array \$___using = []) use (\$picea, \$___class__template $loops) { extract(\$___using, \EXTR_SKIP); ?>
|
||||||
PHP;
|
PHP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "/slot":
|
||||||
case "endslot":
|
case "endslot":
|
||||||
$def =end($slotDefinitions);
|
$slotDepth--;
|
||||||
|
$def = ( $slotDefinitions[$depth] ?? end($slotDefinitions) );
|
||||||
|
|
||||||
if ($def->hasDefinitions() ) {
|
if ($def->hasDefinitions() ) {
|
||||||
|
$def->currentSlot = array_pop($slotName);
|
||||||
$definition = $def->getCurrentSlotDefinitionVars();
|
$definition = $def->getCurrentSlotDefinitionVars();
|
||||||
|
|
||||||
if ($definition) {
|
if ($definition) {
|
||||||
@ -89,18 +104,29 @@ class BlockToken implements ControlStructure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return <<<PHP
|
return <<<PHP
|
||||||
<?php })->call(\$this, $definition array_merge(get_defined_vars(), \$this->using)); ?>
|
<?php })->call(\$this, $definition array_merge(get_defined_vars(), \$this->using)); ?>
|
||||||
PHP;
|
PHP;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return "<?php }); ?>";
|
return "<?php }); ?>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "public":
|
||||||
|
case "private":
|
||||||
|
case "protected":
|
||||||
|
$arguments = rtrim($arguments, ';');
|
||||||
|
return "<?php \$this->createProperty(\\$class::parseProperty('$token', fn($arguments) => func_get_arg(0))) ?>";
|
||||||
|
|
||||||
|
case "set":
|
||||||
|
return "<?php \$___block->setPropertyValue({$arguments}); ?>";
|
||||||
|
|
||||||
|
# DEPRECATED ; should be removed, to be superseded by 'set' instead
|
||||||
case "using":
|
case "using":
|
||||||
return "<?php \$___block->setUsing($arguments); ?>";
|
return "<?php \$___block->setUsing($arguments); ?>";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
throw new \LogicException("Unhandled token ? Should never have been here !");
|
||||||
|
}
|
||||||
|
|
||||||
public function inlineHtml(? object $proxy, string $viewPath, ... $variables) {
|
public function inlineHtml(? object $proxy, string $viewPath, ... $variables) {
|
||||||
return $this->renderHtml($viewPath, [ 'inlineVariables' => $variables ], $proxy);
|
return $this->renderHtml($viewPath, [ 'inlineVariables' => $variables ], $proxy);
|
||||||
@ -111,7 +137,6 @@ class BlockToken implements ControlStructure {
|
|||||||
#return
|
#return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static function parseArguments(Callable $method, array $arguments) : array
|
public static function parseArguments(Callable $method, array $arguments) : array
|
||||||
{
|
{
|
||||||
try{
|
try{
|
||||||
@ -124,23 +149,51 @@ class BlockToken implements ControlStructure {
|
|||||||
$parameters = [];
|
$parameters = [];
|
||||||
|
|
||||||
foreach((new \ReflectionFunction($method))->getParameters() as $key => $value) {
|
foreach((new \ReflectionFunction($method))->getParameters() as $key => $value) {
|
||||||
|
$name = $value->getName();
|
||||||
|
|
||||||
|
# Ordered arguments
|
||||||
if ( isset($arguments[$key]) ) {
|
if ( isset($arguments[$key]) ) {
|
||||||
$parameters[ $value->getName() ] = $arguments[$key];
|
$parameters[ $name ] = $arguments[$key];
|
||||||
}
|
}
|
||||||
|
# Named arguments
|
||||||
|
elseif (isset($arguments[$name])) {
|
||||||
|
$parameters[ $name ] = $arguments[$name];
|
||||||
|
}
|
||||||
|
# Using default value
|
||||||
elseif ( $value->isDefaultValueAvailable() ) {
|
elseif ( $value->isDefaultValueAvailable() ) {
|
||||||
$parameters[ $value->getName() ] = $value->getDefaultValue();
|
$parameters[ $name ] = $value->getDefaultValue();
|
||||||
}
|
}
|
||||||
elseif ( $value->isVariadic() ) {
|
elseif ( $value->isVariadic() ) {
|
||||||
$parameters[ $value->getName() ] = [];
|
$parameters[ $name ] = [];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$parameters[ $value->getName() ] = null;
|
$parameters[ $name ] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $parameters;
|
return $parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function parseProperty(string $token, \Closure $method) : BlockToken\Property
|
||||||
|
{
|
||||||
|
foreach((new \ReflectionFunction($method))->getParameters() as $value) {
|
||||||
|
$property = new BlockToken\Property(
|
||||||
|
name: $value->getName(),
|
||||||
|
scope: BlockToken\PropertyScopeEnum::from($token),
|
||||||
|
setter: $method,
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($value->isDefaultValueAvailable()) {
|
||||||
|
$property->value = $value->getDefaultValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
# For now, we only allow one declaration per token, might be revised at another moment...
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $property ?? throw new \LogicException("No parameters found in property declaration.");
|
||||||
|
}
|
||||||
|
|
||||||
public static function slotDefinitions() {
|
public static function slotDefinitions() {
|
||||||
return new class() {
|
return new class() {
|
||||||
|
|
||||||
@ -184,7 +237,7 @@ class BlockToken implements ControlStructure {
|
|||||||
public function printDefinition(string $name) : string
|
public function printDefinition(string $name) : string
|
||||||
{
|
{
|
||||||
if ( ! isset($this->definitions[$name]) ) {
|
if ( ! isset($this->definitions[$name]) ) {
|
||||||
throw new \Exception("Slot definition for `$name` was not found. Have you defined it in your block header ?");
|
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];
|
return $this->definitions[$name];
|
||||||
@ -194,7 +247,6 @@ class BlockToken implements ControlStructure {
|
|||||||
{
|
{
|
||||||
$this->rendering = true;
|
$this->rendering = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,6 +266,10 @@ class BlockToken implements ControlStructure {
|
|||||||
|
|
||||||
public array $definition = [];
|
public array $definition = [];
|
||||||
|
|
||||||
|
protected array $properties = [];
|
||||||
|
|
||||||
|
private array $definedPropertyValues = [];
|
||||||
|
|
||||||
public function __construct(string $viewPath, ...$arguments) {
|
public function __construct(string $viewPath, ...$arguments) {
|
||||||
$this->viewPath = $viewPath;
|
$this->viewPath = $viewPath;
|
||||||
$this->arguments = $arguments;
|
$this->arguments = $arguments;
|
||||||
@ -223,6 +279,10 @@ class BlockToken implements ControlStructure {
|
|||||||
{
|
{
|
||||||
$this->rendering = true;
|
$this->rendering = true;
|
||||||
|
|
||||||
|
if ($this->using['this'] ?? false) {
|
||||||
|
throw new \InvalidArgumentException("Block '{$this->viewPath}' cannot overwrite 'this' variable.");
|
||||||
|
}
|
||||||
|
|
||||||
return $classTemplate->picea->inlineBlock($this, $this->viewPath, ...$this->arguments);
|
return $classTemplate->picea->inlineBlock($this, $this->viewPath, ...$this->arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,14 +301,51 @@ class BlockToken implements ControlStructure {
|
|||||||
return ! empty($this->slots[$name]);
|
return ! empty($this->slots[$name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function printSlot(string $name, Callable $default)
|
public function printSlot(string $name, Callable $default) : mixed
|
||||||
{
|
{
|
||||||
return $this->slotIsSet($name) ? $this->slots[$name] : $default;
|
return $this->slotIsSet($name) ? $this->slots[$name] : $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUsing(array $variables) {
|
public function setUsing(array $variables) : void
|
||||||
|
{
|
||||||
$this->using = $variables;
|
$this->using = $variables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setPropertyValue(array $vars) : void
|
||||||
|
{
|
||||||
|
foreach($vars as $key => $value) {
|
||||||
|
$this->definedPropertyValues[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createProperty(BlockToken\Property $property) : void
|
||||||
|
{
|
||||||
|
if (isset($this->properties[$property->name])) {
|
||||||
|
throw new \InvalidArgumentException("Given property '{$property->name}' is already defined somewhere else in this block.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->properties[$property->name] = $property;
|
||||||
|
|
||||||
|
if (isset($this->definedPropertyValues[$property->name])) {
|
||||||
|
if ($property->scope !== BlockToken\PropertyScopeEnum::Public) {
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
sprintf("Trying to set property %s but it's scope (%s) makes it impossible", $property->name, $property->scope->name)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->__set($property->name, $this->definedPropertyValues[$property->name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __set(string $name, mixed $value) : void
|
||||||
|
{
|
||||||
|
$this->properties[$name]->value = call_user_func($this->properties[$name]->setter, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __get(string $name) : mixed
|
||||||
|
{
|
||||||
|
return $this->properties[$name]->value;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
14
src/ControlStructure/BlockToken/Property.php
Normal file
14
src/ControlStructure/BlockToken/Property.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Picea\ControlStructure\BlockToken;
|
||||||
|
|
||||||
|
class Property
|
||||||
|
{
|
||||||
|
public mixed $value;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public readonly string $name,
|
||||||
|
public readonly PropertyScopeEnum $scope,
|
||||||
|
public readonly \Closure $setter,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
10
src/ControlStructure/BlockToken/PropertyScopeEnum.php
Normal file
10
src/ControlStructure/BlockToken/PropertyScopeEnum.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Picea\ControlStructure\BlockToken;
|
||||||
|
|
||||||
|
enum PropertyScopeEnum: string
|
||||||
|
{
|
||||||
|
case Private = "private";
|
||||||
|
case Protected = "protected";
|
||||||
|
case Public = "public";
|
||||||
|
}
|
||||||
@ -4,7 +4,7 @@ namespace Picea\ControlStructure;
|
|||||||
|
|
||||||
class BreakToken implements ControlStructure {
|
class BreakToken implements ControlStructure {
|
||||||
|
|
||||||
public string $token = "break";
|
public array $token = [ "break", "/case" ];
|
||||||
|
|
||||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
|
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
|
||||||
{
|
{
|
||||||
|
|||||||
@ -4,7 +4,7 @@ namespace Picea\ControlStructure;
|
|||||||
|
|
||||||
class ForToken implements ControlStructure {
|
class ForToken implements ControlStructure {
|
||||||
|
|
||||||
public array $token = [ "for", "endfor" ];
|
public array $token = [ "for", "endfor", "/for" ];
|
||||||
|
|
||||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string {
|
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string {
|
||||||
switch($token) {
|
switch($token) {
|
||||||
@ -19,6 +19,7 @@ class ForToken implements ControlStructure {
|
|||||||
|
|
||||||
return "<?php for ($arguments): {$uid} = 1; ?>";
|
return "<?php for ($arguments): {$uid} = 1; ?>";
|
||||||
|
|
||||||
|
case "/for":
|
||||||
case "endfor":
|
case "endfor":
|
||||||
$last = end($context->iterationStack);
|
$last = end($context->iterationStack);
|
||||||
|
|
||||||
|
|||||||
@ -5,5 +5,17 @@ namespace Picea\ControlStructure;
|
|||||||
use DI\Definition\Source\AnnotationBasedAutowiring;
|
use DI\Definition\Source\AnnotationBasedAutowiring;
|
||||||
|
|
||||||
class ForeachToken extends AbstractLoop {
|
class ForeachToken extends AbstractLoop {
|
||||||
public array $token = [ "foreach", "endforeach" ];
|
public array $token = [ "foreach", "endforeach", "/foreach" ];
|
||||||
|
|
||||||
|
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
|
||||||
|
{
|
||||||
|
switch($token) {
|
||||||
|
case "foreach":
|
||||||
|
return $this->openLoop($context, $arguments, $token);
|
||||||
|
|
||||||
|
case "endforeach":
|
||||||
|
case "/foreach":
|
||||||
|
return $this->closeLoop($context, $arguments, $token);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,7 +33,9 @@ class FunctionToken implements ControlStructure {
|
|||||||
|
|
||||||
protected function printFunction($context, ?string $arguments) : string
|
protected function printFunction($context, ?string $arguments) : string
|
||||||
{
|
{
|
||||||
return "<?php function $arguments { ?>";
|
$name = trim(explode('(', $arguments, 2)[0]);
|
||||||
|
|
||||||
|
return "<?php if (! function_exists(__NAMESPACE__ . '\\$name')) { function $arguments { ?>";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function printReturn($context, ?string $arguments) : string
|
protected function printReturn($context, ?string $arguments) : string
|
||||||
@ -43,6 +45,6 @@ class FunctionToken implements ControlStructure {
|
|||||||
|
|
||||||
protected function printEndFunction($context) : string
|
protected function printEndFunction($context) : string
|
||||||
{
|
{
|
||||||
return "<?php } ?>";
|
return "<?php } } ?>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4,7 +4,7 @@ namespace Picea\ControlStructure;
|
|||||||
|
|
||||||
class IfToken implements ControlStructure {
|
class IfToken implements ControlStructure {
|
||||||
|
|
||||||
public array $token = [ "if", "else", "elseif", "endif" ];
|
public array $token = [ "if", "else", "elseif", "endif", "/if" ];
|
||||||
|
|
||||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string {
|
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string {
|
||||||
switch($token) {
|
switch($token) {
|
||||||
@ -17,6 +17,7 @@ class IfToken implements ControlStructure {
|
|||||||
case "elseif":
|
case "elseif":
|
||||||
return "<?php elseif ($arguments): ?>";
|
return "<?php elseif ($arguments): ?>";
|
||||||
|
|
||||||
|
case "/if":
|
||||||
case "endif":
|
case "endif":
|
||||||
return "<?php endif ?>";
|
return "<?php endif ?>";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ enum PrintActionEnum : string {
|
|||||||
|
|
||||||
class SectionToken implements ControlStructure {
|
class SectionToken implements ControlStructure {
|
||||||
|
|
||||||
public array $token = [ "section", "endsection" ];
|
public array $token = [ "section", "endsection", "/section" ];
|
||||||
|
|
||||||
protected PrintActionEnum $action = PrintActionEnum::default;
|
protected PrintActionEnum $action = PrintActionEnum::default;
|
||||||
|
|
||||||
@ -29,6 +29,7 @@ class SectionToken implements ControlStructure {
|
|||||||
return $this->printSection($context, $arguments);
|
return $this->printSection($context, $arguments);
|
||||||
|
|
||||||
case "endsection":
|
case "endsection":
|
||||||
|
case "/endsection":
|
||||||
if ( empty($context->sections) ) {
|
if ( empty($context->sections) ) {
|
||||||
throw new \RuntimeException("A section closing tag {% endsection %} was found without an opening {% section %} tag");
|
throw new \RuntimeException("A section closing tag {% endsection %} was found without an opening {% section %} tag");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ namespace Picea\ControlStructure;
|
|||||||
|
|
||||||
class SwitchToken implements ControlStructure {
|
class SwitchToken implements ControlStructure {
|
||||||
|
|
||||||
public array $token = [ "switch", "case", "endswitch" ];
|
public array $token = [ "switch", "case", "endcase", "endswitch", "/switch" ];
|
||||||
|
|
||||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string {
|
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string {
|
||||||
switch($token) {
|
switch($token) {
|
||||||
@ -25,9 +25,11 @@ class SwitchToken implements ControlStructure {
|
|||||||
return ( $output ?? "" ) . "case $arguments: ?>";
|
return ( $output ?? "" ) . "case $arguments: ?>";
|
||||||
|
|
||||||
case "endcase":
|
case "endcase":
|
||||||
|
case "/case":
|
||||||
return "<?php break; ?>";
|
return "<?php break; ?>";
|
||||||
|
|
||||||
case "endswitch":
|
case "endswitch":
|
||||||
|
case "/switch":
|
||||||
return "<?php endswitch; ?>";
|
return "<?php endswitch; ?>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
25
src/ControlStructure/TryCatchToken.php
Normal file
25
src/ControlStructure/TryCatchToken.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Picea\ControlStructure;
|
||||||
|
|
||||||
|
class TryCatchToken implements ControlStructure {
|
||||||
|
|
||||||
|
public array $token = [ "try", "catch", "finally", "endtry", "/try" ];
|
||||||
|
|
||||||
|
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string {
|
||||||
|
switch($token) {
|
||||||
|
case "try":
|
||||||
|
return "<?php try { ?>";
|
||||||
|
|
||||||
|
case "catch":
|
||||||
|
return "<?php } catch($arguments) { ?>";
|
||||||
|
|
||||||
|
case "finally":
|
||||||
|
return "<?php } finally { ?>";
|
||||||
|
|
||||||
|
case "endtry":
|
||||||
|
case "/try":
|
||||||
|
return "<?php } ?>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,7 +3,7 @@
|
|||||||
namespace Picea\ControlStructure;
|
namespace Picea\ControlStructure;
|
||||||
|
|
||||||
class WhileToken extends AbstractLoop {
|
class WhileToken extends AbstractLoop {
|
||||||
public array $token = [ "do", "while", "endwhile", ];
|
public array $token = [ "do", "while", "endwhile", "/while" ];
|
||||||
|
|
||||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string {
|
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string {
|
||||||
switch($token) {
|
switch($token) {
|
||||||
@ -23,10 +23,13 @@ class WhileToken extends AbstractLoop {
|
|||||||
return "<?php } while($arguments); ?>";
|
return "<?php } while($arguments); ?>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $this->openLoop($context, $arguments, $token);
|
||||||
|
|
||||||
|
case "endwhile":
|
||||||
|
case "/while":
|
||||||
|
return $this->closeLoop($context, $arguments, $token);
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::parse($context, $arguments, $token);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
39
src/Extension/DiExtension.php
Normal file
39
src/Extension/DiExtension.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Picea\Extension;
|
||||||
|
|
||||||
|
use Picea\Compiler\Context;
|
||||||
|
use Psr\Container\ContainerInterface;
|
||||||
|
|
||||||
|
class DiExtension implements Extension, FunctionExtension {
|
||||||
|
|
||||||
|
public array $token = [ "di:has", "di:get" ];
|
||||||
|
|
||||||
|
public function __construct(public readonly ContainerInterface $container) {}
|
||||||
|
|
||||||
|
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
|
||||||
|
{
|
||||||
|
if ( $token === 'di:get' ) {
|
||||||
|
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->container->get($arguments) ?>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $token === 'di:has' ) {
|
||||||
|
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->container->has($arguments) ?>";
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \InvalidArgumentException("You must use di:get/di:has tokens or di_get()/di_has() methods.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function exportFunctions(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'di_get' => function(string $classname) {
|
||||||
|
return $this->container->get($classname);
|
||||||
|
},
|
||||||
|
|
||||||
|
'di_has' => function(string $classname) {
|
||||||
|
return $this->container->has($classname);
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,5 +3,5 @@
|
|||||||
namespace Picea\Extension;
|
namespace Picea\Extension;
|
||||||
|
|
||||||
interface Extension {
|
interface Extension {
|
||||||
public function parse(\Picea\Compiler\Context &$context, string $sourceCode, string $token, array $options = []) : string;
|
public function parse(\Picea\Compiler\Context &$context, string $arguments, string $token, array $options = []) : string;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,11 +11,9 @@ class LanguageExtension implements Extension, FunctionExtension {
|
|||||||
|
|
||||||
public string $currentLanguage = "";
|
public string $currentLanguage = "";
|
||||||
|
|
||||||
protected LanguageHandlerInterface $languageHandler;
|
public function __construct(
|
||||||
|
protected LanguageHandlerInterface $languageHandler
|
||||||
public function __construct(LanguageHandlerInterface $handler) {
|
) {}
|
||||||
$this->languageHandler = $handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function exportFunctions(): array
|
public function exportFunctions(): array
|
||||||
{
|
{
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class TitleExtension implements Extension, FunctionExtension {
|
|||||||
"} ?>";
|
"} ?>";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleTitle(? string $set = null, ...$arguments) : ? string
|
public function handleTitle(null|\Stringable|string $set = null, ...$arguments) : ? string
|
||||||
{
|
{
|
||||||
if ( $set === null ) {
|
if ( $set === null ) {
|
||||||
return $this->title;
|
return $this->title;
|
||||||
@ -31,6 +31,7 @@ class TitleExtension implements Extension, FunctionExtension {
|
|||||||
else {
|
else {
|
||||||
# Fixed a bug where template inheritance was rewriting title
|
# Fixed a bug where template inheritance was rewriting title
|
||||||
if ( empty($this->title) ) {
|
if ( empty($this->title) ) {
|
||||||
|
$set = (string) $set;
|
||||||
$this->title = $arguments ? sprintf($set, ...$arguments) : $set;
|
$this->title = $arguments ? sprintf($set, ...$arguments) : $set;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,29 +16,23 @@ class UrlExtension implements Extension, FunctionExtension {
|
|||||||
/(?:[a-z0-9!#$%&'*+\\/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+\\/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])/
|
/(?:[a-z0-9!#$%&'*+\\/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+\\/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])/
|
||||||
PATTERN;
|
PATTERN;
|
||||||
|
|
||||||
protected string $urlBase;
|
|
||||||
|
|
||||||
protected array $appUrl;
|
|
||||||
|
|
||||||
protected string $assetToken;
|
|
||||||
|
|
||||||
protected array $routes;
|
protected array $routes;
|
||||||
|
|
||||||
protected array $routesTarget;
|
protected array $routesTarget;
|
||||||
|
|
||||||
protected bool $forceSSL = false;
|
|
||||||
|
|
||||||
public array $tokens = [ "url" , "route", "asset", "slug" ];
|
public array $tokens = [ "url" , "route", "asset", "slug" ];
|
||||||
|
|
||||||
#[\Deprecated]
|
##[\Deprecated]
|
||||||
protected bool $enforceExistingArguments = true;
|
public bool $enforceExistingArguments = true;
|
||||||
|
|
||||||
public function __construct(string $urlBase = "", string $assetToken = "", array $appUrl = [], bool $forceSSL = false) {
|
public function __construct(
|
||||||
|
protected string $urlBase = "",
|
||||||
|
protected string $assetToken = "",
|
||||||
|
protected array $appUrl = [],
|
||||||
|
protected bool $forceSSL = false
|
||||||
|
) {
|
||||||
$this->urlBase = trim($urlBase, "/");
|
$this->urlBase = trim($urlBase, "/");
|
||||||
$this->assetToken = $assetToken;
|
}
|
||||||
$this->appUrl = $appUrl;
|
|
||||||
$this->forceSSL = $forceSSL;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
|
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
|
||||||
{
|
{
|
||||||
@ -120,7 +114,7 @@ PATTERN;
|
|||||||
|
|
||||||
public function buildRouteUrl(string $name, array $parameters = [], bool $appendVersion = false) : string
|
public function buildRouteUrl(string $name, array $parameters = [], bool $appendVersion = false) : string
|
||||||
{
|
{
|
||||||
if ( false !== ( $route = $this->routes[$name] ?? false ) ) {
|
if ( false !== $route = $this->findRoute($name) ) {
|
||||||
return $this->buildUrl($this->prepareRoute($route, $parameters), $parameters, $appendVersion);
|
return $this->buildUrl($this->prepareRoute($route, $parameters), $parameters, $appendVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,9 +132,9 @@ PATTERN;
|
|||||||
}
|
}
|
||||||
|
|
||||||
# src: https://stackoverflow.com/a/14550919
|
# src: https://stackoverflow.com/a/14550919
|
||||||
public static function slug(string $text, string $separator = '-') : string
|
public static function slug(\Stringable|string $text, string $separator = '-') : string
|
||||||
{
|
{
|
||||||
$clean = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $text);
|
$clean = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', (string) $text);
|
||||||
$clean = preg_replace("/[^a-zA-Z0-9\/_| -]/", '', $clean);
|
$clean = preg_replace("/[^a-zA-Z0-9\/_| -]/", '', $clean);
|
||||||
|
|
||||||
return preg_replace("/[\/_| -]+/", $separator, strtolower(trim($clean, '-')));
|
return preg_replace("/[\/_| -]+/", $separator, strtolower(trim($clean, '-')));
|
||||||
@ -149,14 +143,28 @@ PATTERN;
|
|||||||
|
|
||||||
public function registerRoute(string $name, string $route, string $class, string $method, array $routeMethods) : void
|
public function registerRoute(string $name, string $route, string $class, string $method, array $routeMethods) : void
|
||||||
{
|
{
|
||||||
$this->routes[$name] = [
|
$this->routes[] = $array = [
|
||||||
|
'name' => $name,
|
||||||
'route' => $route,
|
'route' => $route,
|
||||||
'routeMethods' => $routeMethods,
|
'routeMethods' => array_map('strtoupper', $routeMethods),
|
||||||
'class' => $class,
|
'class' => $class,
|
||||||
'classMethod' => $method,
|
'classMethod' => $method,
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->eventExecute(UrlRegisterRouteEvent::class, $name, $this->routes[$name]);
|
$this->eventExecute(UrlRegisterRouteEvent::class, $name, $array);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function findRoute(string $name, string $method = "*") : false|array
|
||||||
|
{
|
||||||
|
foreach($this->routes as $route) {
|
||||||
|
if ( $route['name'] === $name ) {
|
||||||
|
if ($method === '*' || in_array(strtoupper($method), $route['routeMethods']) ) {
|
||||||
|
return $route;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -275,7 +283,7 @@ PATTERN;
|
|||||||
if ($default ?? false) {
|
if ($default ?? false) {
|
||||||
$value = $default;
|
$value = $default;
|
||||||
}
|
}
|
||||||
elseif ( strpos($route, "[{$matches[0][0]}]") !== false && $this->enforceExistingArguments) {
|
elseif ( $this->enforceExistingArguments && ! preg_match(sprintf("/\[\/?%s]/i", $item[0]), $route) ) {
|
||||||
throw new \RuntimeException(sprintf("Error while preparing route %s : could not match variable '%s' into given arguments ( %s ) from %s::%s", $route, $variable, json_encode($arguments), $routeParam['class'], $routeParam['classMethod']));
|
throw new \RuntimeException(sprintf("Error while preparing route %s : could not match variable '%s' into given arguments ( %s ) from %s::%s", $route, $variable, json_encode($arguments), $routeParam['class'], $routeParam['classMethod']));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,7 @@ class DefaultRegistrations implements LanguageRegistration
|
|||||||
|
|
||||||
public function registerControlStructure(Compiler $compiler) : void
|
public function registerControlStructure(Compiler $compiler) : void
|
||||||
{
|
{
|
||||||
|
$compiler->registerControlStructure(new \Picea\ControlStructure\TryCatchToken());
|
||||||
$compiler->registerControlStructure(new \Picea\ControlStructure\NamespaceToken());
|
$compiler->registerControlStructure(new \Picea\ControlStructure\NamespaceToken());
|
||||||
$compiler->registerControlStructure(new \Picea\ControlStructure\UseToken());
|
$compiler->registerControlStructure(new \Picea\ControlStructure\UseToken());
|
||||||
$compiler->registerControlStructure(new \Picea\ControlStructure\IfToken());
|
$compiler->registerControlStructure(new \Picea\ControlStructure\IfToken());
|
||||||
|
|||||||
@ -5,24 +5,21 @@ namespace Picea\Method;
|
|||||||
use Picea\Extension\Extension,
|
use Picea\Extension\Extension,
|
||||||
Picea\Extension\ExtensionTrait;
|
Picea\Extension\ExtensionTrait;
|
||||||
|
|
||||||
use Picea\Compiler\Context;
|
|
||||||
|
|
||||||
use Picea\Extension\FunctionExtension;
|
use Picea\Extension\FunctionExtension;
|
||||||
use Psr\Http\Message\RequestInterface;
|
use Psr\Http\Message\RequestInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
class Request implements Extension, FunctionExtension {
|
class
|
||||||
|
Request implements Extension, FunctionExtension {
|
||||||
use ExtensionTrait;
|
use ExtensionTrait;
|
||||||
|
|
||||||
public array $tokens;
|
public array $tokens;
|
||||||
|
|
||||||
public string $token;
|
public string $token;
|
||||||
|
|
||||||
public ServerRequestInterface $request;
|
public function __construct(
|
||||||
|
public ServerRequestInterface $request
|
||||||
public function __construct(ServerRequestInterface $request, Context $context) {
|
) { }
|
||||||
$this->request = $request;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string { }
|
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string { }
|
||||||
|
|
||||||
@ -84,7 +81,7 @@ class Request implements Extension, FunctionExtension {
|
|||||||
$post = $this->request->getParsedBody();
|
$post = $this->request->getParsedBody();
|
||||||
|
|
||||||
if ( ! $post ) {
|
if ( ! $post ) {
|
||||||
$content = utf8_encode((string) $this->request->getBody());
|
$content = mb_convert_encoding((string)$this->request->getBody(), 'UTF-8', 'ISO-8859-1');
|
||||||
|
|
||||||
if ( $content && ( $json = json_decode($content, true) ) ) {
|
if ( $content && ( $json = json_decode($content, true) ) ) {
|
||||||
$post = $json;
|
$post = $json;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user