Compare commits
No commits in common. "master" and "picea-asset" have entirely different histories.
master
...
picea-asse
@ -16,14 +16,5 @@
|
|||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"psr/http-message": "^1.0"
|
"psr/http-message": "^1.0"
|
||||||
},
|
|
||||||
"extra": {
|
|
||||||
"lean": {
|
|
||||||
"autoload": {
|
|
||||||
"definitions": [
|
|
||||||
"meta/definitions.php"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 "attributes" %}
|
{% define slot %}
|
||||||
|
|
||||||
<a {% slot "attributes" %}{% endslot %} href="{{ $anchor }}" tabindex="{{ $index }}"{% endslot %}>{{ $name }}"</a>
|
<a {% slot "attributes" %}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 :
|
||||||
|
|||||||
@ -1,65 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use function DI\autowire, DI\create, DI\get;
|
|
||||||
|
|
||||||
use Picea\{
|
|
||||||
Caching\Cache,
|
|
||||||
Caching\Opcache,
|
|
||||||
Compiler,
|
|
||||||
Compiler\Context,
|
|
||||||
Compiler\BaseContext,
|
|
||||||
FileFetcher,
|
|
||||||
Method\Request
|
|
||||||
};
|
|
||||||
|
|
||||||
use Picea\Extension\{ LanguageHandlerInterface, LanguageExtension, TitleExtension, NumberExtension, UrlExtension, DiExtension };
|
|
||||||
|
|
||||||
return [
|
|
||||||
Picea\Picea::class => function($c) {
|
|
||||||
return new Picea\Picea($c->get(Context::class), $c->get(Cache::class), $c->get(Compiler::class), null, $c->get(FileFetcher::class), null, getenv("DEBUG"));
|
|
||||||
},
|
|
||||||
|
|
||||||
Context::class => function($c) {
|
|
||||||
return new BaseContext(
|
|
||||||
defaultNamespace: $c->get(Lean\Lean::class)->getPiceaContext(),
|
|
||||||
declare: getenv('PICEA_DECLARE') ?? 'declare(strict_types=1)'
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
Compiler::class => autowire(Compiler::class),
|
|
||||||
|
|
||||||
Request::class => autowire(Request::class),
|
|
||||||
|
|
||||||
LanguageExtension::class => create(LanguageExtension::class)->constructor(get(LanguageHandlerInterface::class)),
|
|
||||||
|
|
||||||
# LanguageHandlerInterface::class => autowire(\Lean\LanguageHandler::class),
|
|
||||||
|
|
||||||
# LanguageRegistration::class => create(\Lean\PiceaDefaultRegistration::class)->constructor(get('picea.extensions'), [], [], get(Ui::class), null),
|
|
||||||
|
|
||||||
'picea.extensions' => function(\Psr\Container\ContainerInterface $c) {
|
|
||||||
return array_merge([
|
|
||||||
$c->get(LanguageExtension::class),
|
|
||||||
$c->get(TitleExtension::class),
|
|
||||||
$c->get(NumberExtension::class),
|
|
||||||
$c->get(DiExtension::class),
|
|
||||||
$c->get(UrlExtension::class),
|
|
||||||
$c->get(Request::class),
|
|
||||||
], class_exists(\Taxus\Picea\Extension::class) ? [ $c->get(\Taxus\Picea\Extension::class) ] : [],
|
|
||||||
array_map(fn($class) => $c->get($class), $c->get(Lean\Lean::class)->getPiceaExtensions())
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
TitleExtension::class => autowire(TitleExtension::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')),
|
|
||||||
|
|
||||||
Cache::class => create(Opcache::class)->constructor(getenv("CACHE_PATH"), get(Context::class)),
|
|
||||||
|
|
||||||
FileFetcher::class => function($c) {
|
|
||||||
return new FileFetcher($c->get(Lean\Lean::class)->getViewPaths());
|
|
||||||
},
|
|
||||||
];
|
|
||||||
@ -21,8 +21,7 @@ class Builder
|
|||||||
|
|
||||||
$replace = [
|
$replace = [
|
||||||
'%NAMESPACE%' => $context->namespace,
|
'%NAMESPACE%' => $context->namespace,
|
||||||
'%USE%' => ( $uses = $context->renderUses() ) ? $uses : false,
|
'%USE%' => ( $uses = $context->renderUses() ) ? "use $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 %DECLARE%
|
<?php
|
||||||
|
|
||||||
namespace %NAMESPACE%;
|
namespace %NAMESPACE%;
|
||||||
|
|
||||||
|
|||||||
@ -4,25 +4,7 @@ namespace Picea\Compiler;
|
|||||||
|
|
||||||
class BaseContext extends Context {
|
class BaseContext extends Context {
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(?string $defaultNamespace = null) {
|
||||||
?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,6 +6,36 @@ 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
|
||||||
@ -27,7 +57,7 @@ abstract class Context {
|
|||||||
|
|
||||||
public function renderUses() : string
|
public function renderUses() : string
|
||||||
{
|
{
|
||||||
return implode(PHP_EOL, array_map(fn($use) => "use $use;", $this->useStack ?? []));
|
return implode(",", $this->useStack ?? []);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renderFunctions() : string
|
public function renderFunctions() : string
|
||||||
|
|||||||
@ -4,43 +4,45 @@ namespace Picea\ControlStructure;
|
|||||||
|
|
||||||
abstract class AbstractLoop implements ControlStructure {
|
abstract class AbstractLoop implements ControlStructure {
|
||||||
|
|
||||||
protected function openLoop(\Picea\Compiler\Context &$context, ?string $arguments, string $token,) : string
|
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token, array $options = []) : string
|
||||||
{
|
{
|
||||||
$name = "$".uniqid("{$token}_");
|
switch($token) {
|
||||||
|
case "while":
|
||||||
|
case "foreach":
|
||||||
|
$name = "$".uniqid("{$token}_");
|
||||||
|
|
||||||
|
$stack = array_filter($context->iterationStack ?? [], function($item) {
|
||||||
|
return ! $item['or'];
|
||||||
|
});
|
||||||
|
|
||||||
|
$count = count($stack);
|
||||||
|
|
||||||
$stack = array_filter($context->iterationStack ?? [], function($item) {
|
if ( $count > 0 ) {
|
||||||
return ! $item['or'];
|
$name .= "[" . end($stack)['uid'] . "]";
|
||||||
});
|
}
|
||||||
|
|
||||||
$count = count($stack);
|
$context->iterationStack[] = [
|
||||||
|
'or' => false,
|
||||||
|
'uid' => $name,
|
||||||
|
'token' => "end{$token}",
|
||||||
|
];
|
||||||
|
|
||||||
if ( $count > 0 ) {
|
return "<?php $token ($arguments): $name = ( $name ?? 0 ) + 1; ?>";
|
||||||
$name .= "[" . end($stack)['uid'] . "]";
|
|
||||||
|
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,35 +2,26 @@
|
|||||||
|
|
||||||
namespace Picea\ControlStructure;
|
namespace Picea\ControlStructure;
|
||||||
|
|
||||||
use http\Exception\InvalidArgumentException;
|
|
||||||
|
|
||||||
class BlockToken implements ControlStructure {
|
class BlockToken implements ControlStructure {
|
||||||
|
|
||||||
public array $token = [ "arguments", "block", "endblock", "/block", "define", "slot", "endslot", "/slot", "using", "public", "private", "protected", "set" ];
|
public array $token = [ "arguments", "block", "endblock", "define", "slot", "endslot", "using" ];
|
||||||
|
|
||||||
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 {
|
||||||
@ -39,104 +30,88 @@ 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(\$showArgs, \$inlineVariables ?? [])), json_encode(\$inlineVariables))
|
sprintf('A block awaiting arguments `%s` instead received `%s` with values `%s`', '$arguments', implode(', ', array_map('gettype', \$inlineVariables ?? [])), json_encode(\$inlineVariables))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
/*%EXCEPTION_LINE_BASE%*/?>
|
/*%EXCEPTION_LINE_BASE%*/?>
|
||||||
PHP;
|
PHP;
|
||||||
|
|
||||||
case "define":
|
case "define":
|
||||||
list($name, $definition) = array_pad(explode(',', $arguments, 2), 2, "");
|
list($name, $definition) = array_pad(explode(',', $arguments, 2), 2, "");
|
||||||
|
|
||||||
( $slotDefinitions[$depth] ?? end($slotDefinitions) )->setDefinition(eval("return $name;"), $definition);
|
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 = ( $slotDefinitions[$depth] ?? end($slotDefinitions) );
|
$def = 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 = end($slotName);
|
$def->currentSlot = $slotName;
|
||||||
$def->setDefinitionVars(end($slotName), $definition);
|
$def->setDefinitionVars($slotName, $definition);
|
||||||
|
|
||||||
$definition = $def->printDefinition(end($slotName));
|
$definition = $def->printDefinition($slotName);
|
||||||
|
|
||||||
if ($definition) {
|
if ($definition) {
|
||||||
$definition .= ",";
|
$definition .= ",";
|
||||||
}
|
}
|
||||||
|
|
||||||
return <<<PHP
|
return <<<PHP
|
||||||
<?php \$this->printSlot($name, function($definition array \$___using = []) use (\$picea, \$___class__template $loops) { extract(\$___using, \EXTR_SKIP); ?>
|
<?php \$this->printSlot($name, function($definition array \$___using = []) use (\$picea $loops) { extract(\$___using, \EXTR_SKIP); ?>
|
||||||
PHP;
|
PHP;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ($definition) {
|
if ($definition) {
|
||||||
$definition .= ",";
|
$definition .= ",";
|
||||||
}
|
}
|
||||||
|
|
||||||
return <<<PHP
|
return <<<PHP
|
||||||
<?php (\$___block ?? \$this)->slotIsSet($name) || (\$___block ?? \$this)->setSlot($name, function($definition array \$___using = []) use (\$picea, \$___class__template $loops) { extract(\$___using, \EXTR_SKIP); ?>
|
<?php (\$___block ?? \$this)->slotIsSet($name) || \$___block->setSlot($name, function($definition array \$___using = []) use (\$picea $loops) { extract(\$___using, \EXTR_SKIP); ?>
|
||||||
PHP;
|
PHP;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "/slot":
|
|
||||||
case "endslot":
|
case "endslot":
|
||||||
$slotDepth--;
|
$def =end($slotDefinitions);
|
||||||
$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) {
|
||||||
$definition .= ",";
|
$definition .= ",";
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function parseSlotArguments(Callable $method) : array
|
public static function parseSlotArguments(Callable $method) : array
|
||||||
{
|
{
|
||||||
#return
|
#return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static function parseArguments(Callable $method, array $arguments) : array
|
public static function parseArguments(Callable $method, array $arguments) : array
|
||||||
{
|
{
|
||||||
try{
|
try{
|
||||||
@ -144,208 +119,136 @@ class BlockToken implements ControlStructure {
|
|||||||
}
|
}
|
||||||
catch(\TypeError $ex) {
|
catch(\TypeError $ex) {
|
||||||
throw $ex;
|
throw $ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
$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[ $name ] = $arguments[$key];
|
$parameters[ $value->getName() ] = $arguments[$key];
|
||||||
}
|
}
|
||||||
# Named arguments
|
|
||||||
elseif (isset($arguments[$name])) {
|
|
||||||
$parameters[ $name ] = $arguments[$name];
|
|
||||||
}
|
|
||||||
# Using default value
|
|
||||||
elseif ( $value->isDefaultValueAvailable() ) {
|
elseif ( $value->isDefaultValueAvailable() ) {
|
||||||
$parameters[ $name ] = $value->getDefaultValue();
|
$parameters[ $value->getName() ] = $value->getDefaultValue();
|
||||||
}
|
}
|
||||||
elseif ( $value->isVariadic() ) {
|
elseif ( $value->isVariadic() ) {
|
||||||
$parameters[ $name ] = [];
|
$parameters[ $value->getName() ] = [];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$parameters[ $name ] = null;
|
$parameters[ $value->getName() ] = 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() {
|
||||||
|
|
||||||
public array $definitions = [];
|
public array $definitions = [];
|
||||||
|
|
||||||
public array $variables = [];
|
public array $variables = [];
|
||||||
|
|
||||||
public bool $rendering = false;
|
public bool $rendering = false;
|
||||||
|
|
||||||
public string $currentSlot;
|
public string $currentSlot;
|
||||||
|
|
||||||
public function setDefinition(string $name, string $definition) : self
|
public function setDefinition(string $name, string $definition) : self
|
||||||
{
|
{
|
||||||
$this->definitions[$name] = $definition;
|
$this->definitions[$name] = $definition;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setDefinitionVars(string $name, string $variables) : self
|
public function setDefinitionVars(string $name, string $variables) : self
|
||||||
{
|
{
|
||||||
$this->variables[$name] = $variables;
|
$this->variables[$name] = $variables;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDefinitionVars(string $name) : string
|
public function getDefinitionVars(string $name) : string
|
||||||
{
|
{
|
||||||
return $this->variables[$name] ?? "";
|
return $this->variables[$name] ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCurrentSlotDefinitionVars() : string
|
public function getCurrentSlotDefinitionVars() : string
|
||||||
{
|
{
|
||||||
return $this->getDefinitionVars($this->currentSlot);
|
return $this->getDefinitionVars($this->currentSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasDefinitions() : bool
|
public function hasDefinitions() : bool
|
||||||
{
|
{
|
||||||
return count($this->definitions) > 0;
|
return count($this->definitions) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 using something like '{% define \"$name\", ...\$arguments %}' ?");
|
throw new \Exception("Slot definition for `$name` was not found. Have you defined it in your block header ?");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->definitions[$name];
|
return $this->definitions[$name];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render() : void
|
public function render() : void
|
||||||
{
|
{
|
||||||
$this->rendering = true;
|
$this->rendering = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function instanciateBlock(string $viewPath, ... $arguments)
|
public static function instanciateBlock(string $viewPath, ... $arguments)
|
||||||
{
|
{
|
||||||
return new class($viewPath, ...$arguments) {
|
return new class($viewPath, ...$arguments) {
|
||||||
|
|
||||||
public bool $rendering = false;
|
public bool $rendering = false;
|
||||||
|
|
||||||
public string $viewPath;
|
public string $viewPath;
|
||||||
|
|
||||||
public array $using = [];
|
public array $using = [];
|
||||||
|
|
||||||
public array $arguments = [];
|
public array $arguments = [];
|
||||||
|
|
||||||
public array $slots = [];
|
public array $slots = [];
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render(object $classTemplate) : string
|
public function render(object $classTemplate) : string
|
||||||
{
|
{
|
||||||
$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);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setSlot(string $name, Callable $method) : void
|
public function setSlot(string $name, Callable $method) : void
|
||||||
{
|
{
|
||||||
$this->slots[$name] = $method;
|
$this->slots[$name] = $method;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function defineSlot(string $name, Callable $method) : void
|
public function defineSlot(string $name, Callable $method) : void
|
||||||
{
|
{
|
||||||
$this->definition[$name] = $method;
|
$this->definition[$name] = $method;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function slotIsSet(string $name) : bool
|
public function slotIsSet(string $name) : bool
|
||||||
{
|
{
|
||||||
return ! empty($this->slots[$name]);
|
return ! empty($this->slots[$name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function printSlot(string $name, Callable $default) : mixed
|
public function printSlot(string $name, Callable $default)
|
||||||
{
|
{
|
||||||
return $this->slotIsSet($name) ? $this->slots[$name] : $default;
|
return $this->slotIsSet($name) ? $this->slots[$name] : $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUsing(array $variables) : void
|
public function setUsing(array $variables) {
|
||||||
{
|
|
||||||
$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;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,14 +0,0 @@
|
|||||||
<?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,
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
<?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 array $token = [ "break", "/case" ];
|
public string $token = "break";
|
||||||
|
|
||||||
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", "/for" ];
|
public array $token = [ "for", "endfor" ];
|
||||||
|
|
||||||
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) {
|
||||||
@ -18,8 +18,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,17 +5,5 @@ 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", "/foreach" ];
|
public array $token = [ "foreach", "endforeach" ];
|
||||||
|
|
||||||
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,9 +33,7 @@ class FunctionToken implements ControlStructure {
|
|||||||
|
|
||||||
protected function printFunction($context, ?string $arguments) : string
|
protected function printFunction($context, ?string $arguments) : string
|
||||||
{
|
{
|
||||||
$name = trim(explode('(', $arguments, 2)[0]);
|
return "<?php function $arguments { ?>";
|
||||||
|
|
||||||
return "<?php if (! function_exists(__NAMESPACE__ . '\\$name')) { function $arguments { ?>";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function printReturn($context, ?string $arguments) : string
|
protected function printReturn($context, ?string $arguments) : string
|
||||||
@ -45,6 +43,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", "/if" ];
|
public array $token = [ "if", "else", "elseif", "endif" ];
|
||||||
|
|
||||||
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) {
|
||||||
@ -16,8 +16,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", "/section" ];
|
public array $token = [ "section", "endsection" ];
|
||||||
|
|
||||||
protected PrintActionEnum $action = PrintActionEnum::default;
|
protected PrintActionEnum $action = PrintActionEnum::default;
|
||||||
|
|
||||||
@ -29,13 +29,10 @@ 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->action = PrintActionEnum::default;
|
|
||||||
|
|
||||||
return $this->printEndSection($context);
|
return $this->printEndSection($context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ namespace Picea\ControlStructure;
|
|||||||
|
|
||||||
class SwitchToken implements ControlStructure {
|
class SwitchToken implements ControlStructure {
|
||||||
|
|
||||||
public array $token = [ "switch", "case", "endcase", "endswitch", "/switch" ];
|
public array $token = [ "switch", "case", "endswitch" ];
|
||||||
|
|
||||||
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,13 +23,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; ?>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,25 +0,0 @@
|
|||||||
<?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", "/while" ];
|
public array $token = [ "do", "while", "endwhile", ];
|
||||||
|
|
||||||
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,13 +23,10 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Picea\Event\Extension;
|
|
||||||
|
|
||||||
interface BuildAssetUrl
|
|
||||||
{
|
|
||||||
public function execute(string $uri, array $parameters = [], bool $appendVersion = true) : mixed;
|
|
||||||
}
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
<?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:has' ) {
|
|
||||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->container->has($arguments) ?>";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $token === 'di:get' ) {
|
|
||||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->container->get($arguments) ?>";
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new \InvalidArgumentException("You must use has() or get() method.");
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -11,9 +11,11 @@ class LanguageExtension implements Extension, FunctionExtension {
|
|||||||
|
|
||||||
public string $currentLanguage = "";
|
public string $currentLanguage = "";
|
||||||
|
|
||||||
public function __construct(
|
protected LanguageHandlerInterface $languageHandler;
|
||||||
protected LanguageHandlerInterface $languageHandler
|
|
||||||
) {}
|
public function __construct(LanguageHandlerInterface $handler) {
|
||||||
|
$this->languageHandler = $handler;
|
||||||
|
}
|
||||||
|
|
||||||
public function exportFunctions(): array
|
public function exportFunctions(): array
|
||||||
{
|
{
|
||||||
|
|||||||
@ -15,7 +15,6 @@ class NumberExtension implements Extension, FunctionExtension {
|
|||||||
public string $title = "",
|
public string $title = "",
|
||||||
) {
|
) {
|
||||||
$this->locale = explode('.', \Locale::getDefault())[0];
|
$this->locale = explode('.', \Locale::getDefault())[0];
|
||||||
$this->formatter = new \NumberFormatter($this->locale, \NumberFormatter::CURRENCY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportFunctions(): array
|
public function exportFunctions(): array
|
||||||
@ -56,6 +55,8 @@ class NumberExtension implements Extension, FunctionExtension {
|
|||||||
|
|
||||||
public function money(float $money, ? string $currency = null) /* : string|false */
|
public function money(float $money, ? string $currency = null) /* : string|false */
|
||||||
{
|
{
|
||||||
|
$this->formatter ??= new \NumberFormatter($this->locale, \NumberFormatter::CURRENCY);
|
||||||
|
|
||||||
$this->formatter->setTextAttribute(\NumberFormatter::CURRENCY_CODE, 'CAD');
|
$this->formatter->setTextAttribute(\NumberFormatter::CURRENCY_CODE, 'CAD');
|
||||||
|
|
||||||
$this->formatter->setPattern( str_replace('¤#','¤ #', $this->formatter->getPattern() ) );
|
$this->formatter->setPattern( str_replace('¤#','¤ #', $this->formatter->getPattern() ) );
|
||||||
|
|||||||
@ -8,7 +8,7 @@ class PrintExtension implements Extension {
|
|||||||
|
|
||||||
public array $token = [ "echo", "print", "printf", "no_html" ];
|
public array $token = [ "echo", "print", "printf", "no_html" ];
|
||||||
|
|
||||||
public int $flag = \ENT_QUOTES | \ENT_DISALLOWED | \ENT_SUBSTITUTE;
|
public int $flag = \ENT_QUOTES;
|
||||||
|
|
||||||
public string $encoding;
|
public string $encoding;
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class TitleExtension implements Extension, FunctionExtension {
|
|||||||
"} ?>";
|
"} ?>";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleTitle(null|\Stringable|string $set = null, ...$arguments) : ? string
|
public function handleTitle(? string $set = null, ...$arguments) : ? string
|
||||||
{
|
{
|
||||||
if ( $set === null ) {
|
if ( $set === null ) {
|
||||||
return $this->title;
|
return $this->title;
|
||||||
@ -31,7 +31,6 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,10 +2,15 @@
|
|||||||
|
|
||||||
namespace Picea\Extension;
|
namespace Picea\Extension;
|
||||||
|
|
||||||
|
use Notes\Route\Attribute\Object\Route;
|
||||||
use Picea\EventTrait;
|
use Picea\EventTrait;
|
||||||
|
use Picea\Compiler\Context;
|
||||||
|
|
||||||
use Picea\Event\Extension\{ UrlBuildAssetEvent, UrlBuildUrlEvent, UrlBuildRouteEvent, UrlRegisterRouteEvent };
|
use Picea\Event\Extension\{ UrlBuildAssetEvent, UrlBuildUrlEvent, UrlBuildRouteEvent, UrlRegisterRouteEvent };
|
||||||
|
|
||||||
class UrlExtension implements Extension, FunctionExtension {
|
class UrlExtension implements Extension, FunctionExtension {
|
||||||
|
use \Picea\EventTrait;
|
||||||
|
|
||||||
use EventTrait;
|
use EventTrait;
|
||||||
|
|
||||||
public const URLIZE_PATTERN_URL = <<<PATTERN
|
public const URLIZE_PATTERN_URL = <<<PATTERN
|
||||||
@ -16,23 +21,29 @@ 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]
|
||||||
public bool $enforceExistingArguments = true;
|
protected bool $enforceExistingArguments = true;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(string $urlBase = "", string $assetToken = "", array $appUrl = [], bool $forceSSL = false) {
|
||||||
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
|
||||||
{
|
{
|
||||||
@ -57,7 +68,7 @@ PATTERN;
|
|||||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->slug($arguments) ?>";
|
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->slug($arguments) ?>";
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \Exception("Unknown token given $token in UrlExtension.");
|
throw new \ParseExtensionException("Unknown token given $token in UrlExtension.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportFunctions(): array
|
public function exportFunctions(): array
|
||||||
@ -114,7 +125,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->findRoute($name) ) {
|
if ( false !== ( $route = $this->routes[$name] ?? false ) ) {
|
||||||
return $this->buildUrl($this->prepareRoute($route, $parameters), $parameters, $appendVersion);
|
return $this->buildUrl($this->prepareRoute($route, $parameters), $parameters, $appendVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,9 +143,9 @@ PATTERN;
|
|||||||
}
|
}
|
||||||
|
|
||||||
# src: https://stackoverflow.com/a/14550919
|
# src: https://stackoverflow.com/a/14550919
|
||||||
public static function slug(\Stringable|string $text, string $separator = '-') : string
|
public static function slug(string $text, string $separator = '-') : string
|
||||||
{
|
{
|
||||||
$clean = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', (string) $text);
|
$clean = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $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, '-')));
|
||||||
@ -143,28 +154,14 @@ 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[] = $array = [
|
$this->routes[$name] = [
|
||||||
'name' => $name,
|
|
||||||
'route' => $route,
|
'route' => $route,
|
||||||
'routeMethods' => array_map('strtoupper', $routeMethods),
|
'routeMethods' => $routeMethods,
|
||||||
'class' => $class,
|
'class' => $class,
|
||||||
'classMethod' => $method,
|
'classMethod' => $method,
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->eventExecute(UrlRegisterRouteEvent::class, $name, $array);
|
$this->eventExecute(UrlRegisterRouteEvent::class, $name, $this->routes[$name]);
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -283,7 +280,7 @@ PATTERN;
|
|||||||
if ($default ?? false) {
|
if ($default ?? false) {
|
||||||
$value = $default;
|
$value = $default;
|
||||||
}
|
}
|
||||||
elseif ( $this->enforceExistingArguments && ! preg_match(sprintf("/\[\/?%s]/i", $item[0]), $route) ) {
|
elseif ( strpos($route, "[{$matches[0][0]}]") !== false && $this->enforceExistingArguments) {
|
||||||
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,7 +32,6 @@ 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,6 +5,8 @@ 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;
|
||||||
@ -15,10 +17,12 @@ class Request implements Extension, FunctionExtension {
|
|||||||
public array $tokens;
|
public array $tokens;
|
||||||
|
|
||||||
public string $token;
|
public string $token;
|
||||||
|
|
||||||
|
public ServerRequestInterface $request;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(ServerRequestInterface $request, Context $context) {
|
||||||
public ServerRequestInterface $request
|
$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 { }
|
||||||
|
|
||||||
|
|||||||
@ -180,7 +180,6 @@ class Picea implements LanguageRegistration
|
|||||||
{
|
{
|
||||||
if ( $this->debug || ! $this->cache->compiled( $context->cacheFilename() ) ) {
|
if ( $this->debug || ! $this->cache->compiled( $context->cacheFilename() ) ) {
|
||||||
$context = $this->compileContext($context);
|
$context = $this->compileContext($context);
|
||||||
|
|
||||||
$this->cache->save($context);
|
$this->cache->save($context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user