routes = $routes; $this->setRequest($request); } /** * Get the full URL for the current request. * * @return string */ public function full() { return $this->request->fullUrl(); } /** * Get the current URL for the request. * * @return string */ public function current() { return $this->to($this->request->getPathInfo()); } /** * Get the URL for the previous request. * * @param mixed $fallback * @return string */ public function previous($fallback = false) { $referrer = $this->request->headers->get('referer'); $url = $referrer ? $this->to($referrer) : $this->getPreviousUrlFromSession(); if ($url) { return $url; } elseif ($fallback) { return $this->to($fallback); } return $this->to('/'); } /** * Get the previous URL from the session if possible. * * @return string|null */ protected function getPreviousUrlFromSession() { $session = $this->getSession(); return $session ? $session->previousUrl() : null; } /** * Generate an absolute URL to the given path. * * @param string $path * @param mixed $extra * @param bool|null $secure * @return string */ public function to($path, $extra = [], $secure = null) { // First we will check if the URL is already a valid URL. If it is we will not // try to generate a new one but will simply return the URL as is, which is // convenient since developers do not always have to check if it's valid. if ($this->isValidUrl($path)) { return $path; } $tail = implode('/', array_map( 'rawurlencode', (array) $this->formatParameters($extra)) ); // Once we have the scheme we will compile the "tail" by collapsing the values // into a single string delimited by slashes. This just makes it convenient // for passing the array of parameters to this URL as a list of segments. $root = $this->formatRoot($this->formatScheme($secure)); list($path, $query) = $this->extractQueryString($path); return $this->format( $root, '/'.trim($path.'/'.$tail, '/') ).$query; } /** * Generate a secure, absolute URL to the given path. * * @param string $path * @param array $parameters * @return string */ public function secure($path, $parameters = []) { return $this->to($path, $parameters, true); } /** * Generate the URL to an application asset. * * @param string $path * @param bool|null $secure * @return string */ public function asset($path, $secure = null) { if ($this->isValidUrl($path)) { return $path; } // Once we get the root URL, we will check to see if it contains an index.php // file in the paths. If it does, we will remove it since it is not needed // for asset paths, but only for routes to endpoints in the application. $root = $this->formatRoot($this->formatScheme($secure)); return $this->removeIndex($root).'/'.trim($path, '/'); } /** * Generate the URL to a secure asset. * * @param string $path * @return string */ public function secureAsset($path) { return $this->asset($path, true); } /** * Generate the URL to an asset from a custom root domain such as CDN, etc. * * @param string $root * @param string $path * @param bool|null $secure * @return string */ public function assetFrom($root, $path, $secure = null) { // Once we get the root URL, we will check to see if it contains an index.php // file in the paths. If it does, we will remove it since it is not needed // for asset paths, but only for routes to endpoints in the application. $root = $this->formatRoot($this->formatScheme($secure), $root); return $this->removeIndex($root).'/'.trim($path, '/'); } /** * Remove the index.php file from a path. * * @param string $root * @return string */ protected function removeIndex($root) { $i = 'index.php'; return Str::contains($root, $i) ? str_replace('/'.$i, '', $root) : $root; } /** * Get the default scheme for a raw URL. * * @param bool|null $secure * @return string */ public function formatScheme($secure) { if (! is_null($secure)) { return $secure ? 'https://' : 'http://'; } if (is_null($this->cachedSchema)) { $this->cachedSchema = $this->forceScheme ?: $this->request->getScheme().'://'; } return $this->cachedSchema; } /** * Get the URL to a named route. * * @param string $name * @param mixed $parameters * @param bool $absolute * @return string * * @throws \InvalidArgumentException */ public function route($name, $parameters = [], $absolute = true) { if (! is_null($route = $this->routes->getByName($name))) { return $this->toRoute($route, $parameters, $absolute); } throw new InvalidArgumentException("Route [{$name}] not defined."); } /** * Get the URL for a given route instance. * * @param \Illuminate\Routing\Route $route * @param mixed $parameters * @param bool $absolute * @return string * * @throws \Illuminate\Routing\Exceptions\UrlGenerationException */ protected function toRoute($route, $parameters, $absolute) { return $this->routeUrl()->to( $route, $this->formatParameters($parameters), $absolute ); } /** * Get the URL to a controller action. * * @param string $action * @param mixed $parameters * @param bool $absolute * @return string * * @throws \InvalidArgumentException */ public function action($action, $parameters = [], $absolute = true) { if (is_null($route = $this->routes->getByAction($action = $this->formatAction($action)))) { throw new InvalidArgumentException("Action {$action} not defined."); } return $this->toRoute($route, $parameters, $absolute); } /** * Format the given controller action. * * @param string $action * @return string */ protected function formatAction($action) { if ($this->rootNamespace && ! (strpos($action, '\\') === 0)) { return $this->rootNamespace.'\\'.$action; } else { return trim($action, '\\'); } } /** * Format the array of URL parameters. * * @param mixed|array $parameters * @return array */ public function formatParameters($parameters) { $parameters = Arr::wrap($parameters); foreach ($parameters as $key => $parameter) { if ($parameter instanceof UrlRoutable) { $parameters[$key] = $parameter->getRouteKey(); } } return $parameters; } /** * Extract the query string from the given path. * * @param string $path * @return array */ protected function extractQueryString($path) { if (($queryPosition = strpos($path, '?')) !== false) { return [ substr($path, 0, $queryPosition), substr($path, $queryPosition), ]; } return [$path, '']; } /** * Get the base URL for the request. * * @param string $scheme * @param string $root * @return string */ public function formatRoot($scheme, $root = null) { if (is_null($root)) { if (is_null($this->cachedRoot)) { $this->cachedRoot = $this->forcedRoot ?: $this->request->root(); } $root = $this->cachedRoot; } $start = Str::startsWith($root, 'http://') ? 'http://' : 'https://'; return preg_replace('~'.$start.'~', $scheme, $root, 1); } /** * Format the given URL segments into a single URL. * * @param string $root * @param string $path * @return string */ public function format($root, $path) { $path = '/'.trim($path, '/'); if ($this->formatHostUsing) { $root = call_user_func($this->formatHostUsing, $root); } if ($this->formatPathUsing) { $path = call_user_func($this->formatPathUsing, $path); } return trim($root.$path, '/'); } /** * Determine if the given path is a valid URL. * * @param string $path * @return bool */ public function isValidUrl($path) { if (! preg_match('~^(#|//|https?://|mailto:|tel:)~', $path)) { return filter_var($path, FILTER_VALIDATE_URL) !== false; } return true; } /** * Get the Route URL generator instance. * * @return \Illuminate\Routing\RouteUrlGenerator */ protected function routeUrl() { if (! $this->routeGenerator) { $this->routeGenerator = new RouteUrlGenerator($this, $this->request); } return $this->routeGenerator; } /** * Set the default named parameters used by the URL generator. * * @param array $defaults * @return void */ public function defaults(array $defaults) { $this->routeUrl()->defaults($defaults); } /** * Get the default named parameters used by the URL generator. * * @return array */ public function getDefaultParameters() { return $this->routeUrl()->defaultParameters; } /** * Force the scheme for URLs. * * @param string $schema * @return void */ public function forceScheme($schema) { $this->cachedSchema = null; $this->forceScheme = $schema.'://'; } /** * Set the forced root URL. * * @param string $root * @return void */ public function forceRootUrl($root) { $this->forcedRoot = rtrim($root, '/'); $this->cachedRoot = null; } /** * Set a callback to be used to format the host of generated URLs. * * @param \Closure $callback * @return $this */ public function formatHostUsing(Closure $callback) { $this->formatHostUsing = $callback; return $this; } /** * Set a callback to be used to format the path of generated URLs. * * @param \Closure $callback * @return $this */ public function formatPathUsing(Closure $callback) { $this->formatPathUsing = $callback; return $this; } /** * Get the path formatter being used by the URL generator. * * @return \Closure */ public function pathFormatter() { return $this->formatPathUsing ?: function ($path) { return $path; }; } /** * Get the request instance. * * @return \Illuminate\Http\Request */ public function getRequest() { return $this->request; } /** * Set the current request instance. * * @param \Illuminate\Http\Request $request * @return void */ public function setRequest(Request $request) { $this->request = $request; $this->cachedRoot = null; $this->cachedSchema = null; $this->routeGenerator = null; } /** * Set the route collection. * * @param \Illuminate\Routing\RouteCollection $routes * @return $this */ public function setRoutes(RouteCollection $routes) { $this->routes = $routes; return $this; } /** * Get the session implementation from the resolver. * * @return \Illuminate\Session\Store|null */ protected function getSession() { if ($this->sessionResolver) { return call_user_func($this->sessionResolver); } } /** * Set the session resolver for the generator. * * @param callable $sessionResolver * @return $this */ public function setSessionResolver(callable $sessionResolver) { $this->sessionResolver = $sessionResolver; return $this; } /** * Set the root controller namespace. * * @param string $rootNamespace * @return $this */ public function setRootControllerNamespace($rootNamespace) { $this->rootNamespace = $rootNamespace; return $this; } }