Merge branch 'master' of https://git.mcnd.ca/mcndave/picea
This commit is contained in:
commit
14cfb46c98
|
@ -113,9 +113,7 @@ class Compiler
|
|||
foreach($this->extensionList as $ext) {
|
||||
if ($ext instanceof FunctionExtension) {
|
||||
foreach ($ext->exportFunctions() as $name => $value) {
|
||||
if ( is_string($value) ) {
|
||||
$callable = fn(...$args) => call_user_func_array([ $ext, $value ], $args);
|
||||
}
|
||||
$callable = is_string($value) ? fn(...$args) => call_user_func_array([ $ext, $value ], $args) : null;
|
||||
|
||||
$context->pushFunction(is_numeric($name) ? $value : $name, $callable ?? $value);
|
||||
}
|
||||
|
|
|
@ -24,14 +24,13 @@ class BlockToken implements ControlStructure {
|
|||
return <<<PHP
|
||||
<?php
|
||||
try {
|
||||
extract( \$this->using ?? [], \EXTR_OVERWRITE);
|
||||
extract( \\$class::parseArguments(function($arguments) {}, \$inlineVariables), \EXTR_OVERWRITE);
|
||||
|
||||
unset(\$inlineVariables);
|
||||
}
|
||||
catch(\TypeError \$ex) {
|
||||
|
||||
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('gettype', \$inlineVariables ?? [])), json_encode(\$inlineVariables))
|
||||
);
|
||||
}
|
||||
?>
|
||||
|
@ -72,7 +71,7 @@ class BlockToken implements ControlStructure {
|
|||
}
|
||||
|
||||
return <<<PHP
|
||||
<?php \$___block->slotIsSet($name) || \$___block->setSlot($name, function($definition array \$___using = []) use (\$picea) { extract(\$___using, \EXTR_SKIP); ?>
|
||||
<?php (\$___block ?? \$this)->slotIsSet($name) || \$___block->setSlot($name, function($definition array \$___using = []) use (\$picea) { extract(\$___using, \EXTR_SKIP); ?>
|
||||
PHP;
|
||||
}
|
||||
|
||||
|
@ -131,6 +130,9 @@ class BlockToken implements ControlStructure {
|
|||
elseif ( $value->isVariadic() ) {
|
||||
$parameters[ $value->getName() ] = [];
|
||||
}
|
||||
else {
|
||||
$parameters[ $value->getName() ] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return $parameters;
|
||||
|
@ -217,7 +219,7 @@ class BlockToken implements ControlStructure {
|
|||
public function render(object $classTemplate) : string
|
||||
{
|
||||
$this->rendering = true;
|
||||
|
||||
|
||||
return $classTemplate->picea->inlineBlock($this, $this->viewPath, ...$this->arguments);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class FunctionToken implements ControlStructure {
|
||||
|
||||
public array $token = [ "function", "endfunction", "return" ];
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) {
|
||||
switch($token) {
|
||||
case "function":
|
||||
return $this->printFunction($context, $arguments);
|
||||
|
||||
case "return":
|
||||
if ( empty($context->functions) ) {
|
||||
throw new \RuntimeException("A function return tag {% return %} was found without an opening {% function ... %} tag");
|
||||
}
|
||||
|
||||
return $this->printReturn($context, $arguments);
|
||||
|
||||
case "endfunction":
|
||||
if ( empty($context->functions) ) {
|
||||
throw new \RuntimeException("A function closing tag {% endfunction %} was found without an opening {% function ... %} tag");
|
||||
}
|
||||
|
||||
$context->functions--;
|
||||
|
||||
return $this->printEndFunction($context);
|
||||
}
|
||||
}
|
||||
|
||||
protected function printFunction($context, ?string $arguments) : string
|
||||
{
|
||||
$context->functions++;
|
||||
return "<?php function $arguments { ?>";
|
||||
}
|
||||
|
||||
protected function printReturn($context, ?string $arguments) : string
|
||||
{
|
||||
return "<?php return $arguments; ?>";
|
||||
}
|
||||
|
||||
protected function printEndFunction($context) : string
|
||||
{
|
||||
return "<?php } ?>";
|
||||
}
|
||||
}
|
|
@ -53,7 +53,7 @@ class SectionToken implements ControlStructure {
|
|||
protected function printEndSection($context) : string
|
||||
{
|
||||
$section = array_pop($context->sections);
|
||||
$build = $context->extendFrom ? "\$___class__template->sectionStack && \$___class__template->renderSection({$section['name']});" : "\$___class__template->renderSection({$section['name']});";
|
||||
$build = $context->extendFrom ? "!empty(\$___class__template->sectionStack) && \$___class__template->renderSection({$section['name']});" : "\$___class__template->renderSection({$section['name']});";
|
||||
return "<?php array_pop(\$___class__template->sectionStack); }]; $build?>";
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ use Picea\Compiler\Context;
|
|||
|
||||
class JsonExtension implements Extension, FunctionExtension {
|
||||
|
||||
public array $token = [ "json", "json.pretty" ];
|
||||
public array $token = [ "json", "json.pretty", "json.html" ];
|
||||
|
||||
public int $flags = JSON_HEX_TAG | \JSON_HEX_QUOT | \JSON_THROW_ON_ERROR | \JSON_UNESCAPED_UNICODE;
|
||||
|
||||
|
@ -23,16 +23,32 @@ class JsonExtension implements Extension, FunctionExtension {
|
|||
return "<?php echo htmlentities(json_encode($arguments, {$this->flags}), ENT_QUOTES, 'UTF-8') ?>";
|
||||
}
|
||||
|
||||
return "<?php echo json_encode($arguments, $flag) ?>";
|
||||
$cls = static::class;
|
||||
|
||||
return "<?php echo json_encode(\\$cls::utf8($arguments), $flag) ?>";
|
||||
}
|
||||
|
||||
public function exportFunctions(): array
|
||||
{
|
||||
return [
|
||||
'json' => function($arguments, ? int $flags = null) {
|
||||
return json_encode($arguments, \JSON_FORCE_OBJECT);
|
||||
return json_encode($arguments, \JSON_FORCE_OBJECT);
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
public static function utf8($src) {
|
||||
|
||||
if (is_array($src)) {
|
||||
foreach ($src as $key => $value) {
|
||||
$src[$key] = static::utf8($value);
|
||||
}
|
||||
}
|
||||
elseif (is_string($src)) {
|
||||
return mb_convert_encoding($src, "UTF-8", "UTF-8");
|
||||
}
|
||||
|
||||
return $src;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use Picea\Compiler\Context;
|
|||
|
||||
class LanguageExtension implements Extension, FunctionExtension {
|
||||
|
||||
public array $tokens = [ "lang", "_", "language.set" ];
|
||||
public array $tokens = [ "lang", "lang.raw", "_", "_.raw", "language.set" ];
|
||||
|
||||
public string $currentLanguage = "";
|
||||
|
||||
|
@ -31,9 +31,15 @@ class LanguageExtension implements Extension, FunctionExtension {
|
|||
return "<?php \$picea->compiler->getExtensionFromToken('$token')->currentLanguage = $arguments; ?>";
|
||||
|
||||
case "lang":
|
||||
return "<?php echo htmlspecialchars(\$picea->compiler->getExtensionFromToken('$token')->absoluteLang($arguments), \ENT_QUOTES, ini_get('default_charset'), true) ?>";
|
||||
|
||||
case "lang.raw":
|
||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->absoluteLang($arguments) ?>";
|
||||
|
||||
case "_":
|
||||
return "<?php echo htmlspecialchars(\$picea->compiler->getExtensionFromToken('$token')->relativeLang($arguments), \ENT_QUOTES, ini_get('default_charset'), true) ?>";
|
||||
|
||||
case "_.raw":
|
||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->relativeLang($arguments) ?>";
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\Extension;
|
||||
|
||||
use Picea\Compiler\Context;
|
||||
|
||||
class MoneyExtension implements Extension {
|
||||
|
||||
public string $token = "money";
|
||||
|
||||
public string $title = "";
|
||||
|
||||
public string $locale;
|
||||
|
||||
public \NumberFormatter $formatter;
|
||||
|
||||
public function __construct(Context $context) {
|
||||
$this->register($context);
|
||||
$this->locale = explode('.', \Locale::getDefault())[0];
|
||||
$this->formatter = new \NumberFormatter($this->locale, \NumberFormatter::CURRENCY);
|
||||
}
|
||||
|
||||
public function register(Context $context) : void
|
||||
{
|
||||
$context->pushFunction("money", [ $this, 'money' ]);
|
||||
}
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) {
|
||||
return "<?php echo money($arguments) ?>";
|
||||
}
|
||||
|
||||
public function money(float $money, ? string $currency = null) /* : string|false */
|
||||
{
|
||||
$this->formatter->setTextAttribute(\NumberFormatter::CURRENCY_CODE, 'CAD');
|
||||
|
||||
$this->formatter->setPattern( str_replace('¤#','¤ #', $this->formatter->getPattern() ) );
|
||||
|
||||
return $this->formatter->formatCurrency($money, $currency ?? $this->formatter->getTextAttribute(\NumberFormatter::CURRENCY_CODE));
|
||||
}
|
||||
|
||||
}
|
|
@ -14,8 +14,8 @@ class UrlExtension implements Extension {
|
|||
|
||||
protected array $routesTarget;
|
||||
|
||||
public array $tokens = [ "url" , "route", "route.cacheless", "asset", "url.current", "url.parameters" ];
|
||||
|
||||
public array $tokens = [ "url" , "route", "route.cacheless", "asset", "url.current", "url.parameters", "slug" ];
|
||||
|
||||
public function __construct(Context $context, string $urlBase = "", string $assetToken = "") {
|
||||
$this->urlBase = trim($urlBase, "/");
|
||||
$this->assetToken = $assetToken;
|
||||
|
@ -39,6 +39,9 @@ class UrlExtension implements Extension {
|
|||
|
||||
case "url.parameters":
|
||||
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->setUrlParameters($arguments) ?>";
|
||||
|
||||
case "slug":
|
||||
return \Transliterator::createFromRules(':: Any-Latin;:: NFD;:: [:Nonspacing Mark:] Remove;:: NFC;:: [:Punctuation:] Remove;:: Lower();[:Separator:] > \'-\'')->transliterate( $arguments );
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -50,6 +53,7 @@ class UrlExtension implements Extension {
|
|||
$context->pushFunction("current_url", [ $this, 'currentUrl' ]);
|
||||
$context->pushFunction("asset", [ $this, 'buildAssetUrl' ]);
|
||||
$context->pushFunction("route", [ $this, 'buildRouteUrl' ]);
|
||||
$context->pushFunction("slug", [ $this, 'slug' ]);
|
||||
}
|
||||
|
||||
public function getRouteList(bool $full = false) : array
|
||||
|
@ -96,6 +100,11 @@ class UrlExtension implements Extension {
|
|||
return $this->scheme() . $this->domain() . $this->base();
|
||||
}
|
||||
|
||||
public static function slug(string $text, string $separator = '-') : string
|
||||
{
|
||||
return str_replace('-', $separator, \Transliterator::createFromRules(':: Any-Latin;:: NFD;:: [:Nonspacing Mark:] Remove;:: NFC;:: [:Punctuation:] Remove;:: Lower();[:Separator:] > \'-\'')->transliterate(str_replace('-', ' ', $text)));
|
||||
}
|
||||
|
||||
public function registerRoute(string $name, string $route, string $class, string $method, array $routeMethods) : void
|
||||
{
|
||||
$this->routes[$name] = [
|
||||
|
@ -159,18 +168,19 @@ class UrlExtension implements Extension {
|
|||
|
||||
protected function isHttps() : bool
|
||||
{
|
||||
$header = in_array('https', array_map("strtolower", [
|
||||
$https = in_array('https', array_map("strtolower", [
|
||||
$_SERVER['REQUEST_SCHEME'] ?? "",
|
||||
$_SERVER['X-Url-Scheme'] ?? "",
|
||||
$_SERVER['Front-End-Https'] ?? "",
|
||||
$_SERVER['X-Forwarded-Ssl'] ?? "",
|
||||
$_SERVER['X-Forwarded-Proto'] ?? "",
|
||||
$_SERVER['X-Forwarded-Protocol'] ?? "",
|
||||
]));
|
||||
$_SERVER['HTTP_X_FORWARDED_PROTO'] ?? "",
|
||||
$_SERVER['HTTP_X_FORWARDED_PROTOCOL'] ?? "",
|
||||
])) || isset($_SERVER['HTTP_X_ARR_SSL']);
|
||||
|
||||
return $header
|
||||
return $https
|
||||
|| ( "443" === ( $_SERVER['SERVER_PORT'] ?? "" ) )
|
||||
|| ( "https" === ( $_SERVER['REQUEST_SCHEME'] ?? "http") )
|
||||
|| ( "off" !== ( strtolower($_SERVER['HTTPS'] ?? "off")) );
|
||||
|| ( "off" !== ( strtolower($_SERVER['HTTPS'] ?? $_SERVER['HTTP_X_FORWARDED_SSL'] ?? $_SERVER['X-Forwarded-Ssl'] ?? "off")) );
|
||||
}
|
||||
|
||||
protected function prepareRoute(string $route, array &$arguments)
|
||||
|
@ -205,6 +215,5 @@ class UrlExtension implements Extension {
|
|||
}
|
||||
|
||||
return $route;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ class DefaultRegistrations implements LanguageRegistration
|
|||
$compiler->registerControlStructure(new \Picea\ControlStructure\BreakToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\ExtendsToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\SectionToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\FunctionToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\BlockToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\IncludeToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\ViewToken());
|
||||
|
|
|
@ -7,6 +7,7 @@ use Picea\Extension\Extension,
|
|||
|
||||
use Picea\Compiler\Context;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class Request implements Extension {
|
||||
|
@ -46,7 +47,7 @@ class Request implements Extension {
|
|||
|
||||
public function post(? string $variableName = null, $default = null)
|
||||
{
|
||||
return $variableName === null ? $this->request->getParsedBody() : static::arrayGet($this->request->getParsedBody(), $variableName) ?? $default;
|
||||
return $variableName === null ? $this->_post() : static::arrayGet($this->_post(), $variableName) ?? $default;
|
||||
}
|
||||
|
||||
public function request(? string $variableName = null, $default = null)
|
||||
|
@ -75,4 +76,19 @@ class Request implements Extension {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected function _post() : array
|
||||
{
|
||||
$post = $this->request->getParsedBody();
|
||||
|
||||
if ( ! $post ) {
|
||||
$content = utf8_encode((string) $this->request->getBody());
|
||||
|
||||
if ( $content && ( $json = json_decode($content, true) ) ) {
|
||||
$post = $json;
|
||||
}
|
||||
}
|
||||
|
||||
return $post ?: [];
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue