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 "compiler->getExtensionFromToken('$token')->buildAssetUrl($arguments) ?>"; case "route": return "compiler->getExtensionFromToken('$token')->buildRouteUrl($arguments) ?>"; case "url": return "compiler->getExtensionFromToken('$token')->buildUrl($arguments) ?>"; case "url.parameters": return "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; } }