Skip to content

Commit

Permalink
working on cleaning generator
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorotwell committed Dec 22, 2016
1 parent 0f3e509 commit 39e8c83
Show file tree
Hide file tree
Showing 3 changed files with 428 additions and 345 deletions.
318 changes: 318 additions & 0 deletions src/Illuminate/Routing/RouteUrlGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,318 @@
<?php

namespace Illuminate\Routing;

use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Routing\Exceptions\UrlGenerationException;

class RouteUrlGenerator
{
/**
* The URL generator instance.
*
* @param \Illuminate\Routing\UrlGenerator
*/
protected $url;

/**
* The request instance.
*
* @var \Illuminate\Http\Request
*/
protected $request;

/**
* The named parameter defaults.
*
* @var array
*/
public $defaultParameters = [];

/**
* Characters that should not be URL encoded.
*
* @var array
*/
public $dontEncode = [
'%2F' => '/',
'%40' => '@',
'%3A' => ':',
'%3B' => ';',
'%2C' => ',',
'%3D' => '=',
'%2B' => '+',
'%21' => '!',
'%2A' => '*',
'%7C' => '|',
'%3F' => '?',
'%26' => '&',
'%23' => '#',
'%25' => '%',
];

/**
* Create a new Route URL generator.
*
* @param \Illuminate\Routing\UrlGenerator $url
* @param \Illuminate\Http\Request $request
* @return void
*/
public function __construct($url, $request)
{
$this->url = $url;
$this->request = $request;
}

/**
* Generate a URL for the given route.
*
* @param \Illuminate\Routing\UrlGeneartor $url
* @param \Illuminate\Routing\Route $route
* @param array $parameters
* @param bool $absolute
* @return string
*/
public function to($route, $parameters = [], $absolute = false)
{
$domain = $this->getRouteDomain($route, $parameters);

$uri = $this->addQueryString($this->url->format(
$root = $this->replaceRoot($route, $domain, $parameters),
$this->replaceRouteParameters($route->uri(), $parameters)
), $parameters);

if (preg_match('/\{.*?\}/', $uri)) {
throw UrlGenerationException::forMissingParameters($route);
}

$uri = strtr(rawurlencode($uri), $this->dontEncode);

return $absolute ? $uri : '/'.ltrim(str_replace($root, '', $uri), '/');
}

/**
* Get the formatted domain for a given route.
*
* @param \Illuminate\Routing\Route $route
* @param array $parameters
* @return string
*/
protected function getRouteDomain($route, &$parameters)
{
return $route->domain() ? $this->formatDomain($route, $parameters) : null;
}

/**
* Format the domain and port for the route and request.
*
* @param \Illuminate\Routing\Route $route
* @param array $parameters
* @return string
*/
protected function formatDomain($route, &$parameters)
{
return $this->addPortToDomain($this->getDomainAndScheme($route));
}

/**
* Get the domain and scheme for the route.
*
* @param \Illuminate\Routing\Route $route
* @return string
*/
protected function getDomainAndScheme($route)
{
return $this->getRouteScheme($route).$route->domain();
}

/**
* Get the scheme for the given route.
*
* @param \Illuminate\Routing\Route $route
* @return string
*/
protected function getRouteScheme($route)
{
if ($route->httpOnly()) {
return 'http://';
} elseif ($route->httpsOnly()) {
return 'https://';
}

return $this->url->formatScheme(null);
}

/**
* Add the port to the domain if necessary.
*
* @param string $domain
* @return string
*/
protected function addPortToDomain($domain)
{
$secure = $this->request->isSecure();

$port = (int) $this->request->getPort();

if (($secure && $port === 443) || (! $secure && $port === 80)) {
return $domain;
}

return $domain.':'.$port;
}

/**
* Add a query string to the URI.
*
* @param string $uri
* @param array $parameters
* @return mixed|string
*/
protected function addQueryString($uri, array $parameters)
{
// If the URI has a fragment we will move it to the end of this URI since it will
// need to come after any query string that may be added to the URL else it is
// not going to be available. We will remove it then append it back on here.
if (! is_null($fragment = parse_url($uri, PHP_URL_FRAGMENT))) {
$uri = preg_replace('/#.*/', '', $uri);
}

$uri .= $this->getRouteQueryString($parameters);

return is_null($fragment) ? $uri : $uri."#{$fragment}";
}

/**
* Get the query string for a given route.
*
* @param array $parameters
* @return string
*/
protected function getRouteQueryString(array $parameters)
{
// First we will get all of the string parameters that are remaining after we
// have replaced the route wildcards. We'll then build a query string from
// these string parameters then use it as a starting point for the rest.
if (count($parameters) == 0) {
return '';
}

$query = http_build_query(
$keyed = $this->getStringParameters($parameters)
);

// Lastly, if there are still parameters remaining, we will fetch the numeric
// parameters that are in the array and add them to the query string or we
// will make the initial query string if it wasn't started with strings.
if (count($keyed) < count($parameters)) {
$query .= '&'.implode(
'&', $this->getNumericParameters($parameters)
);
}

return '?'.trim($query, '&');
}

/**
* Get the string parameters from a given list.
*
* @param array $parameters
* @return array
*/
protected function getStringParameters(array $parameters)
{
return array_filter($parameters, 'is_string', ARRAY_FILTER_USE_KEY);
}

/**
* Get the numeric parameters from a given list.
*
* @param array $parameters
* @return array
*/
protected function getNumericParameters(array $parameters)
{
return array_filter($parameters, 'is_numeric', ARRAY_FILTER_USE_KEY);
}

/**
* Replace the parameters on the root path.
*
* @param \Illuminate\Routing\Route $route
* @param string $domain
* @param array $parameters
* @return string
*/
protected function replaceRoot($route, $domain, &$parameters)
{
return $this->replaceRouteParameters(
$this->formatRouteRoot($route, $domain), $parameters
);
}

/**
* Get the root of the route URL.
*
* @param \Illuminate\Routing\Route $route
* @param string $domain
* @return string
*/
protected function formatRouteRoot($route, $domain)
{
return $this->url->formatRoot($this->getRouteScheme($route), $domain);
}

/**
* Replace all of the wildcard parameters for a route path.
*
* @param string $path
* @param array $parameters
* @return string
*/
protected function replaceRouteParameters($path, array &$parameters)
{
$path = $this->replaceNamedParameters($path, $parameters);

$path = preg_replace_callback('/\{.*?\}/', function ($match) use (&$parameters) {
return (empty($parameters) && ! Str::endsWith($match[0], '?}'))
? $match[0]
: array_shift($parameters);
}, $path);

return trim(preg_replace('/\{.*?\?\}/', '', $path), '/');
}

/**
* Replace all of the named parameters in the path.
*
* @param string $path
* @param array $parameters
* @return string
*/
protected function replaceNamedParameters($path, &$parameters)
{
return preg_replace_callback('/\{(.*?)\??\}/', function ($m) use (&$parameters) {
if (isset($parameters[$m[1]])) {
return Arr::pull($parameters, $m[1]);
} elseif (isset($this->defaultParameters[$m[1]])) {
return $this->defaultParameters[$m[1]];
} else {
return $m[0];
}
}, $path);
}

/**
* Set the default named parameters used by the URL generator.
*
* @param array $defaults
* @return void
*/
public function defaults(array $defaults)
{
$this->defaultParameters = array_merge(
$this->defaultParameters, $defaults
);
}
}
Loading

0 comments on commit 39e8c83

Please sign in to comment.