- Added a new {% block ... %} token

- Added a new {% php ... %} token
- Fixed a bug with an OR if foreach is empty
This commit is contained in:
Dave Mc Nicoll 2020-03-30 12:13:02 -04:00
parent 0e201b77f2
commit 404d1f4359
9 changed files with 143 additions and 22 deletions

View File

@ -0,0 +1,50 @@
<?php
namespace Picea\ControlStructure;
class BlockToken implements ControlStructure {
public array $token = [ "block", "arguments" ];
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) {
switch($token) {
case "block":
return "<?php echo \$___class__template->picea->inlineHtml(\$this, $arguments); ?>";
case "arguments":
$class = static::class;
return <<<PHP
<?php
try {
extract( \\$class::parseArguments(function($arguments) {}, \$inlineVariables), \EXTR_OVERWRITE);
unset(\$inlineVariables);
}
catch(\TypeError \$ex) {
throw new \Exception('A block awaiting arguments `$arguments` instead received `' . implode(', ', array_map('gettype', \$inlineVariables)) . '`');
}
?>
PHP;
}
}
public static function parseArguments(Callable $method, array $arguments) : array
{
try{
call_user_func_array($method, $arguments);
}
catch(\TypeError $ex) {
throw $ex;
}
$parameters = [];
foreach((new \ReflectionFunction($method))->getParameters() as $key => $value) {
$parameters[ $value->getName() ] = $arguments[$key] ?? $value->getDefaultValue();
}
return $parameters;
}
}

View File

@ -7,14 +7,20 @@ class ForeachToken implements ControlStructure {
public string $token = "foreach";
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) {
$uid = "$".uniqid("foreach_");
$name = "$".uniqid("foreach_");
$count = count($context->iterationStack ?? []);
if ( $count > 0 ) {
$name .= "[" . $context->iterationStack[$count - 1]['uid'] . "]";
}
$context->iterationStack[] = [
'or' => false,
'uid' => $uid,
'uid' => $name,
'token' => 'endforeach',
];
return "<?php foreach ($arguments): {$uid} = 1; ?>";
return "<?php foreach ($arguments): $name = ( $name ?? 0 ) + 1; ; ?>";
}
}

View File

@ -13,7 +13,13 @@ class OrToken implements ControlStructure {
$key = count( $context->iterationStack ) - 1;
$context->iterationStack[$key]['or'] = true;
return "<?php {$context->iterationStack[$key]['token']}; if( false === ({$context->iterationStack[$key]['uid']} ?? false) ): ?>";
$name = $context->iterationStack[$key]['uid'];
#if ($key !== 0) {
#}
return "<?php {$context->iterationStack[$key]['token']}; if( false === ($name ?? false) ): ?>";
}
}

View File

@ -2,13 +2,35 @@
namespace Picea\Extension;
use Picea\Compiler\Context;
class JsonExtension implements Extension {
public string $token = "json";
public array $token = [ "json", "json.pretty" ];
public int $flags = JSON_HEX_TAG | \JSON_HEX_APOS | \JSON_HEX_QUOT | \JSON_THROW_ON_ERROR;
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) {
return "<?php echo json_encode($arguments, {$this->flags}) ?>";
public function __construct(? Context $context = null) {
if ($context) {
$this->register($context);
}
}
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) {
$flag = $this->flags;
if ( $token === "json.pretty" ) {
$flag = \JSON_PRETTY_PRINT;
}
return "<?php echo json_encode($arguments, $flag) ?>";
}
public function register(Context $context) : void
{
$context->pushFunction("json", function($arguments, ? int $flags = null) {
return json_encode($arguments, \JSON_FORCE_OBJECT);
});
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace Picea\Extension;
class PhpExtension implements Extension {
public array $token = [ "php" ];
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) {
return "<?php $arguments ?>";
}
}

View File

@ -12,7 +12,7 @@ class UrlExtension implements Extension {
protected array $routes;
public array $tokens = [ "url" , "route", "asset" ];
public array $tokens = [ "url" , "route", "asset", "url.parameters" ];
public function __construct(Context $context, string $urlBase = "", string $assetToken = "") {
$this->urlBase = trim($urlBase, "/");
@ -31,6 +31,9 @@ class UrlExtension implements Extension {
case "url":
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->buildUrl($arguments) ?>";
case "url.parameters":
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->setUrlParameters($arguments) ?>";
}
return null;
@ -43,11 +46,16 @@ class UrlExtension implements Extension {
$context->pushFunction("route", [ $this, 'buildRouteUrl' ]);
}
public function buildUrl(string $uri = "", array $parameters = []) : string
public function setUrlParameters(string $url = "", array $parameters = []) : string
{
return $this->url() . "/" . ltrim($uri, "/") . ( $parameters ? "?" . http_build_query($parameters) : "" );
return $url . ( $parameters ? "?" . http_build_query($parameters) : "" );
}
public function buildUrl(string $uri = "", array $parameters = []) : string
{
return $this->setUrlParameters($this->url() . "/" . ltrim($uri, "/"), $parameters);
}
public function buildAssetUrl(string $uri, array $parameters = []) : string
{
return $this->buildUrl($uri, array_replace([ 'v' => $this->assetToken ], $parameters));

View File

@ -4,6 +4,8 @@ namespace Picea\Language;
use Picea\Compiler;
use Picea\Compiler\Context;
class DefaultRegistrations implements LanguageRegistration
{
protected array $extensions;
@ -12,8 +14,11 @@ class DefaultRegistrations implements LanguageRegistration
protected array $controlStructures;
public function __construct(array $extensions = [], array $syntaxes = [], array $controlStructure = [])
protected ? Context $context;
public function __construct(? Context $context = null, array $extensions = [], array $syntaxes = [], array $controlStructure = [])
{
$this->context = $context;
$this->extensions = $extensions;
$this->syntaxes = $syntaxes;
$this->controlStructures = $controlStructure;
@ -63,6 +68,7 @@ class DefaultRegistrations implements LanguageRegistration
$compiler->registerControlStructure(new \Picea\ControlStructure\ExtendsToken());
$compiler->registerControlStructure(new \Picea\ControlStructure\SectionToken());
$compiler->registerControlStructure(new \Picea\ControlStructure\EndSectionToken());
$compiler->registerControlStructure(new \Picea\ControlStructure\BlockToken());
$compiler->registerControlStructure(new \Picea\ControlStructure\ViewToken());
foreach($this->controlStructures ?? [] as $controlStructure) {
@ -72,7 +78,7 @@ class DefaultRegistrations implements LanguageRegistration
public function registerExtension(Compiler $compiler) : void
{
$compiler->registerExtension(new \Picea\Extension\JsonExtension());
$compiler->registerExtension(new \Picea\Extension\JsonExtension($this->context));
$compiler->registerExtension(new \Picea\Extension\AssetExtension());
foreach($this->extensions ?? [] as $extension) {

View File

@ -33,24 +33,24 @@ class Request implements Extension {
$context->pushFunction("post", [ $this, 'post' ]);
}
public function cookie(? string $variableName = null)
public function cookie(? string $variableName = null, $default = null)
{
return $variableName === null ? $this->request->getCookieParams() : static::arrayGet($this->request->getCookieParams(), $variableName);
return $variableName === null ? $this->request->getCookieParams() : static::arrayGet($this->request->getCookieParams(), $variableName) ?? $default;
}
public function get(? string $variableName = null)
public function get(? string $variableName = null, $default = null)
{
return $variableName === null ? $this->request->getQueryParams() : static::arrayGet($this->request->getQueryParams(), $variableName);
return $variableName === null ? $this->request->getQueryParams() : static::arrayGet($this->request->getQueryParams(), $variableName) ?? $default;
}
public function post(? string $variableName = null)
public function post(? string $variableName = null, $default = null)
{
return $variableName === null ? $this->request->getParsedBody() : static::arrayGet($this->request->getParsedBody(), $variableName);
return $variableName === null ? $this->request->getParsedBody() : static::arrayGet($this->request->getParsedBody(), $variableName) ?? $default;
}
public function server(? string $variableName = null)
public function server(? string $variableName = null, $default = null)
{
return $variableName === null ? $this->request->getServerParams() : static::arrayGet($this->request->getServerParams(), $variableName);
return $variableName === null ? $this->request->getServerParams() : static::arrayGet($this->request->getServerParams(), $variableName) ?? $default;
}
public static function arrayGet(array $array, string $path, string $delimiter = '.')

View File

@ -57,7 +57,18 @@ class Picea implements LanguageRegistration
return $object();
}
/**
* Method used by Block and View tokens
* @param object $proxy
* @param string $viewPath
* @param array $variables
* @return type
*/
public function inlineHtml(? object $proxy, string $viewPath, ... $variables) {
return $this->renderHtml($viewPath, [ 'inlineVariables' => $variables ], $proxy);
}
public function renderContext(Compiler\Context $context) : object
{
if ( null === $object = $this->contextFromCache($context) ) {