url.php 8.05 KB
Newer Older
1
<?php namespace Laravel; use Laravel\Routing\Router, Laravel\Routing\Route;
2 3 4 5

class URL {

	/**
Taylor Otwell committed
6 7 8 9 10 11 12
	 * The cached base URL.
	 *
	 * @var string
	 */
	public static $base;

	/**
13 14 15 16 17 18 19 20 21 22
	 * Get the full URI including the query string.
	 *
	 * @return string
	 */
	public static function full()
	{
		return static::to(URI::full());
	}

	/**
Taylor Otwell committed
23 24 25 26 27 28 29 30 31 32
	 * Get the full URL for the current request.
	 *
	 * @return string
	 */
	public static function current()
	{
		return static::to(URI::current());
	}

	/**
Taylor Otwell committed
33 34 35 36 37 38 39 40 41 42
	 * Get the URL for the application root.
	 *
	 * @param  bool    $https
	 * @return string
	 */
	public static function home($https = false)
	{
		$route = Router::find('home');

		// If a route named "home" exists, we'll route to that instead of using
Pavel committed
43
		// the single slash root URI. This allows the HTTPS attribute to be
Taylor Otwell committed
44 45 46 47 48 49 50 51 52 53
		// respected instead of being hard-coded in the redirect.
		if ( ! is_null($route))
		{
			return static::to_route('home');
		}

		return static::to('/', $https);
	}

	/**
54 55 56 57 58 59
	 * Get the base URL of the application.
	 *
	 * @return string
	 */
	public static function base()
	{
Taylor Otwell committed
60 61 62 63
		if (isset(static::$base)) return static::$base;

		$base = 'http://localhost';

64 65 66
		// If the application URL configuration is set, we will just use that
		// instead of trying to guess the URL from the $_SERVER array's host
		// and script variables as this is more reliable.
Taylor Otwell committed
67 68 69 70
		if (($url = Config::get('application.url')) !== '')
		{
			$base = $url;
		}
Taylor Otwell committed
71
		elseif (isset($_SERVER['HTTP_HOST']))
72
		{
Taylor Otwell committed
73 74 75 76 77 78 79 80 81 82 83 84 85 86
			$base = static::guess();
		}

		return static::$base = $base;
	}

	/**
	 * Guess the application URL based on the $_SERVER variables.
	 *
	 * @return string
	 */
	protected static function guess()
	{
		$protocol = (Request::secure()) ? 'https://' : 'http://';
87

Taylor Otwell committed
88 89 90 91
		// Basically, by removing the basename, we are removing everything after
		// the and including the front controller from the URI. Leaving us with
		// the installation path for the application.
		$script = $_SERVER['SCRIPT_NAME'];
92

Taylor Otwell committed
93
		$path = str_replace(basename($script), '', $script);
94

Taylor Otwell committed
95 96 97 98
		// Now that we have the URL, all we need to do is attach the protocol
		// protocol and HTTP_HOST to build the URL for the application, and
		// we also trim off trailing slashes for cleanliness.
		$uri = $protocol.$_SERVER['HTTP_HOST'].$path;
99

Taylor Otwell committed
100
		return rtrim($uri, '/');
101 102 103
	}

	/**
104 105
	 * Generate an application URL.
	 *
106 107 108
	 * <code>
	 *		// Create a URL to a location within the application
	 *		$url = URL::to('user/profile');
Taylor Otwell committed
109 110 111
	 *
	 *		// Create a HTTPS URL to a location within the application
	 *		$url = URL::to('user/profile', true);
112 113
	 * </code>
	 *
114
	 * @param  string  $url
115
	 * @param  bool    $https
116 117
	 * @return string
	 */
118
	public static function to($url = '', $https = false)
119
	{
Taylor Otwell committed
120
		if (filter_var($url, FILTER_VALIDATE_URL) !== false) return $url;
121

122
		$root = static::base().'/'.Config::get('application.index');
123

124
		// Since SSL is not often used while developing the application, we allow the
125
		// developer to disable SSL on all framework generated links to make it more
126 127
		// convenient to work with the site while developing locally.
		if ($https and Config::get('application.ssl'))
128
		{
Taylor Otwell committed
129
			$root = preg_replace('~http://~', 'https://', $root, 1);
130
		}
131

Taylor Otwell committed
132
		return rtrim($root, '/').'/'.ltrim($url, '/');
133 134 135 136 137 138 139 140
	}

	/**
	 * Generate an application URL with HTTPS.
	 *
	 * @param  string  $url
	 * @return string
	 */
141
	public static function to_secure($url = '')
142
	{
143
		return static::to($url, true);
144 145 146
	}

	/**
147 148 149 150 151 152 153 154 155 156 157 158 159 160
	 * Generate a URL to a controller action.
	 *
	 * <code>
	 *		// Generate a URL to the "index" method of the "user" controller
	 *		$url = URL::to_action('user@index');
	 *
	 *		// Generate a URL to http://example.com/user/profile/taylor
	 *		$url = URL::to_action('user@profile', array('taylor'));
	 * </code>
	 *
	 * @param  string  $action
	 * @param  array   $parameters
	 * @return string
	 */
161
	public static function to_action($action, $parameters = array())
162
	{
163 164
		// This allows us to use true reverse routing to controllers, since
		// URIs may be setup to handle the action that do not follow the
165 166
		// typical Laravel controller URI conventions.
		$route = Router::uses($action);
167

168 169
		if ( ! is_null($route))
		{
170
			return static::explicit($route, $action, $parameters);
171 172 173 174 175 176
		}
		// If no route was found that handled the given action, we'll just
		// generate the URL using the typical controller routing setup
		// for URIs and turn SSL to false.
		else
		{
177
			return static::convention($action, $parameters);
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
		}
	}

	/**
	 * Generate a action URL from a route definition
	 *
	 * @param  array   $route
	 * @param  string  $action
	 * @param  array   $parameters
	 * @return string
	 */
	protected static function explicit($route, $action, $parameters)
	{
		$https = array_get(current($route), 'https', false);

193
		return static::to(static::transpose(key($route), $parameters), $https);
194 195 196 197 198 199 200 201 202 203
	}

	/**
	 * Generate an action URI by convention.
	 *
	 * @param  string  $action
	 * @param  array   $parameters
	 * @return string
	 */
	protected static function convention($action, $parameters)
204
	{
205 206 207 208 209 210
		list($bundle, $action) = Bundle::parse($action);

		$bundle = Bundle::get($bundle);

		// If a bundle exists for the action, we will attempt to use it's "handles"
		// clause as the root of the generated URL, as the bundle can only handle
Taylor Otwell committed
211
		// URIs that begin with that string and no others.
212 213 214 215
		$root = $bundle['handles'] ?: '';

		$https = false;

216 217
		$parameters = implode('/', $parameters);

218 219
		// We'll replace both dots and @ signs in the URI since both are used
		// to specify the controller and action, and by convention should be
Taylor Otwell committed
220
		// translated into URI slashes for the URL.
221
		$uri = $root.'/'.str_replace(array('.', '@'), '/', $action);
222

223 224 225
		$uri = static::to(str_finish($uri, '/').$parameters);

		return trim($uri, '/');
226 227 228
	}

	/**
229
	 * Generate an application URL to an asset.
230
	 *
231 232
	 * @param  string  $url
	 * @param  bool    $https
233 234
	 * @return string
	 */
235
	public static function to_asset($url, $https = null)
236
	{
237
		if (is_null($https)) $https = Request::secure();
238

239
		$url = static::to($url, $https);
240

241 242
		// Since assets are not served by Laravel, we do not need to come through
		// the front controller. So, we'll remove the application index specified
243
		// in the application config from the generated URL.
244 245 246 247
		if (($index = Config::get('application.index')) !== '')
		{
			$url = str_replace($index.'/', '', $url);
		}
248

249
		return $url;
250 251 252
	}

	/**
253
	 * Generate a URL from a route name.
254 255 256
	 *
	 * <code>
	 *		// Create a URL to the "profile" named route
257
	 *		$url = URL::to_route('profile');
258
	 *
259 260
	 *		// Create a URL to the "profile" named route with wildcard parameters
	 *		$url = URL::to_route('profile', array($username));
261
	 * </code>
262 263 264 265 266
	 *
	 * @param  string  $name
	 * @param  array   $parameters
	 * @param  bool    $https
	 * @return string
267
	 */
268
	public static function to_route($name, $parameters = array())
269
	{
270
		if (is_null($route = Routing\Router::find($name)))
271
		{
272
			throw new \Exception("Error creating URL for undefined route [$name].");
273 274
		}

275
		// To determine whether the URL should be HTTPS or not, we look for the "https"
276 277
		// value on the route action array. The route has control over whether the URL
		// should be generated with an HTTPS protocol string or just HTTP.
278
		$https = array_get(current($route), 'https', false);
279

Taylor Otwell committed
280 281 282
		$uri = trim(static::transpose(key($route), $parameters), '/');

		return static::to($uri, $https);
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
	}

	/**
	 * Substitute the parameters in a given URI.
	 *
	 * @param  string  $uri
	 * @param  array   $parameters
	 * @return string
	 */
	public static function transpose($uri, $parameters)
	{
		// Spin through each route parameter and replace the route wildcard segment
		// with the corresponding parameter passed to the method. Afterwards, we'll
		// replace all of the remaining optional URI segments.
		foreach ((array) $parameters as $parameter)
		{
			if ( ! is_null($parameter))
			{
				$uri = preg_replace('/\(.+?\)/', $parameter, $uri, 1);
			}
		}

		// If there are any remaining optional place-holders, we'll just replace
		// them with empty strings since not every optional parameter has to be
		// in the array of parameters that were passed.
		$uri = str_replace(array_keys(Router::$optional), '', $uri);

		return trim($uri, '/');
311 312
	}

313
}