- Fixed UrlExtension to reflect on notes-routes changes - Added some methods to FileFetcher
206 lines
6.1 KiB
PHP
206 lines
6.1 KiB
PHP
<?php
|
|
|
|
namespace Picea\Extension;
|
|
|
|
use Picea\Compiler\Context;
|
|
|
|
class UrlExtension implements Extension {
|
|
|
|
protected string $urlBase;
|
|
|
|
protected string $assetToken;
|
|
|
|
protected array $routes;
|
|
|
|
protected array $routesTarget;
|
|
|
|
public array $tokens = [ "url" , "route", "asset", "url.parameters" ];
|
|
|
|
public function __construct(Context $context, string $urlBase = "", string $assetToken = "") {
|
|
$this->urlBase = trim($urlBase, "/");
|
|
$this->assetToken = $assetToken;
|
|
$this->register($context);
|
|
}
|
|
|
|
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) : ?string
|
|
{
|
|
switch($token) {
|
|
case "asset":
|
|
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->buildAssetUrl($arguments) ?>";
|
|
|
|
case "route":
|
|
return "<?php echo \$picea->compiler->getExtensionFromToken('$token')->buildRouteUrl($arguments) ?>";
|
|
|
|
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;
|
|
}
|
|
|
|
public function register(Context $context) : void
|
|
{
|
|
$context->pushFunction("url", [ $this, 'buildUrl' ]);
|
|
$context->pushFunction("asset", [ $this, 'buildAssetUrl' ]);
|
|
$context->pushFunction("route", [ $this, 'buildRouteUrl' ]);
|
|
}
|
|
|
|
public function getRouteList(bool $full = false) : array
|
|
{
|
|
return $this->routes;
|
|
}
|
|
|
|
public function setUrlParameters(string $url = "", array $parameters = []) : string
|
|
{
|
|
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));
|
|
}
|
|
|
|
public function buildRouteUrl(string $name, array $parameters = []) : string
|
|
{
|
|
if ( false !== ( $route = $this->routes[$name] ?? false ) ) {
|
|
return $this->buildUrl($this->prepareRoute($route['route'], $parameters), $parameters);
|
|
}
|
|
|
|
$routeList = json_encode($this->routes, \JSON_PRETTY_PRINT);
|
|
|
|
throw new \RuntimeException("
|
|
Given route `$name` could not be found within current route list:
|
|
$routeList
|
|
");
|
|
}
|
|
|
|
public function url() : string
|
|
{
|
|
return $this->scheme() . $this->domain() . $this->base();
|
|
}
|
|
|
|
public function registerRoute(string $name, string $route, string $class, string $method, array $routeMethods) : void
|
|
{
|
|
$this->routes[$name] = [
|
|
'route' => $route,
|
|
'routeMethods' => $routeMethods,
|
|
'class' => $class,
|
|
'classMethod' => $method,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Return URI formatted
|
|
*/
|
|
protected function uri(bool $queryString = false) : string
|
|
{
|
|
$uri = ( $_SERVER['REQUEST_URI'] ?? $_SERVER['PHP_SELF'] ?? "" ) . ( $queryString ? $this->queryString() : "" );
|
|
|
|
if ( ! $queryString ) {
|
|
$uri = explode('?', $uri, 2)[0];
|
|
}
|
|
|
|
if ( ($base = $this->config['base'] ?? false) && ( stripos($uri, $base) === 0 ) ) {
|
|
$uri = substr($uri, strlen($base));
|
|
}
|
|
|
|
return '/' . ltrim($uri, '/');
|
|
}
|
|
|
|
/**
|
|
* Return query string
|
|
*/
|
|
protected function queryString() : string
|
|
{
|
|
return isset($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : "";
|
|
}
|
|
|
|
protected function scheme() : string
|
|
{
|
|
return ( $this->isHttps() ? "https" : "http" ) . "://";
|
|
}
|
|
|
|
protected function base() : string
|
|
{
|
|
return $this->urlBase ? "/" . $this->urlBase : "";
|
|
}
|
|
|
|
/**
|
|
* Check if Uri's segments are valid
|
|
* @param array $segments The uri's segments
|
|
*/
|
|
protected function secure($segments = []) : array
|
|
{
|
|
return array_diff($segments, [ '..', '://' ]);
|
|
}
|
|
|
|
protected function domain() : string
|
|
{
|
|
return strtolower($_SERVER['HTTP_HOST']);
|
|
}
|
|
|
|
protected function isDefaultPort() : bool
|
|
{
|
|
return in_array($_SERVER['SERVER_PORT'], [ 80, 443 ]);
|
|
}
|
|
|
|
protected function isHttps() : bool
|
|
{
|
|
$header = in_array('https', array_map("strtolower", [
|
|
$_SERVER['X-Url-Scheme'] ?? "",
|
|
$_SERVER['Front-End-Https'] ?? "",
|
|
$_SERVER['X-Forwarded-Ssl'] ?? "",
|
|
$_SERVER['X-Forwarded-Proto'] ?? "",
|
|
$_SERVER['X-Forwarded-Protocol'] ?? "",
|
|
]));
|
|
|
|
return $header
|
|
|| ( "443" === ( $_SERVER['SERVER_PORT'] ?? "" ) )
|
|
|| ( "https" === ( $_SERVER['REQUEST_SCHEME'] ?? "http") )
|
|
|| ( "off" !== ( strtolower($_SERVER['HTTPS'] ?? "off")) );
|
|
}
|
|
|
|
protected function prepareRoute(string $route, array &$arguments)
|
|
{
|
|
if ( preg_match_all('~{(.*?)}~si', $route, $matches, PREG_SET_ORDER) ) {
|
|
$search = [];
|
|
|
|
foreach($matches as $item) {
|
|
if (strpos($item[1], "=") !== false) {
|
|
list($variable, $default) = explode('=', $item[1]);
|
|
}
|
|
else {
|
|
$variable = $item[1];
|
|
}
|
|
|
|
if ( array_key_exists($variable, $arguments) ) {
|
|
$value = $arguments[ $item[1] ];
|
|
}
|
|
else if ( isset($default) ) {
|
|
$value = ""; # $default;
|
|
}
|
|
else {
|
|
$variable = $item[1];
|
|
}
|
|
|
|
$search[ $item[0] ] = $value;
|
|
|
|
unset($arguments[ $item[1] ]);
|
|
}
|
|
|
|
$route = str_replace(array_keys($search), array_values($search), $route);
|
|
}
|
|
|
|
return $route;
|
|
|
|
}
|
|
}
|