url.php 9.35 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
	 * Get the full URL for the current request.
	 *
	 * @return string
	 */
	public static function current()
	{
29
		return static::to(URI::current(), null, false, false);
Taylor Otwell committed
30 31 32
	}

	/**
Taylor Otwell committed
33 34 35 36 37
	 * Get the URL for the application root.
	 *
	 * @param  bool    $https
	 * @return string
	 */
38
	public static function home($https = null)
Taylor Otwell committed
39 40 41 42
	{
		$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';

Taylor Otwell committed
64
		// If the application's URL configuration is set, we will just use that
65
		// instead of trying to guess the URL from the $_SERVER array's host
Taylor Otwell committed
66
		// and script variables as this is a more reliable method.
Taylor Otwell committed
67 68 69 70
		if (($url = Config::get('application.url')) !== '')
		{
			$base = $url;
		}
71
		else
72
		{
73
			$base = Request::foundation()->getRootUrl();
Taylor Otwell committed
74 75 76 77 78 79
		}

		return static::$base = $base;
	}

	/**
80 81
	 * Generate an application URL.
	 *
82 83 84
	 * <code>
	 *		// Create a URL to a location within the application
	 *		$url = URL::to('user/profile');
Taylor Otwell committed
85 86 87
	 *
	 *		// Create a HTTPS URL to a location within the application
	 *		$url = URL::to('user/profile', true);
88 89
	 * </code>
	 *
90
	 * @param  string  $url
91
	 * @param  bool    $https
92 93
	 * @param  bool    $asset
	 * @param  bool    $locale
94 95
	 * @return string
	 */
96
	public static function to($url = '', $https = null, $asset = false, $locale = true)
97
	{
98 99 100 101 102 103 104
		// If the given URL is already valid or begins with a hash, we'll just return
		// the URL unchanged since it is already well formed. Otherwise we will add
		// the base URL of the application and return the full URL.
		if (static::valid($url) or starts_with($url, '#'))
		{
			return $url;
		}
105

Chris Berthe committed
106
		// Unless $https is specified (true or false), we maintain the current request
107 108 109
		// security for any new links generated.  So https for all secure links.
		if (is_null($https)) $https = Request::secure();

110 111 112 113 114 115 116
		$root = static::base();

		if ( ! $asset)
		{
			$root .= '/'.Config::get('application.index');
		}

117 118 119
		$languages = Config::get('application.languages');

		if ( ! $asset and $locale and count($languages) > 0)
120
		{
121 122 123 124
			if (in_array($default = Config::get('application.language'), $languages))
			{
				$root = rtrim($root, '/').'/'.$default;
			}
125
		}
126

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

Taylor Otwell committed
139
		return rtrim($root, '/').'/'.ltrim($url, '/');
140 141 142 143 144 145 146 147
	}

	/**
	 * Generate an application URL with HTTPS.
	 *
	 * @param  string  $url
	 * @return string
	 */
148
	public static function to_secure($url = '')
149
	{
150
		return static::to($url, true);
151 152 153
	}

	/**
154 155 156 157 158 159 160 161 162 163 164 165 166 167
	 * 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
	 */
168
	public static function to_action($action, $parameters = array())
169
	{
170 171
		// This allows us to use true reverse routing to controllers, since
		// URIs may be setup to handle the action that do not follow the
172 173
		// typical Laravel controller URI conventions.
		$route = Router::uses($action);
174

175 176
		if ( ! is_null($route))
		{
177
			return static::explicit($route, $action, $parameters);
178 179 180
		}
		// If no route was found that handled the given action, we'll just
		// generate the URL using the typical controller routing setup
Taylor Otwell committed
181
		// for URIs and turn SSL to false by default.
182 183
		else
		{
184
			return static::convention($action, $parameters);
185 186 187 188
		}
	}

	/**
Chris Berthe committed
189
	 * Generate an action URL from a route definition
190 191 192 193 194 195 196 197
	 *
	 * @param  array   $route
	 * @param  string  $action
	 * @param  array   $parameters
	 * @return string
	 */
	protected static function explicit($route, $action, $parameters)
	{
198
		$https = array_get(current($route), 'https', null);
199

200
		return static::to(static::transpose(key($route), $parameters), $https);
201 202 203 204 205 206 207 208 209 210
	}

	/**
	 * Generate an action URI by convention.
	 *
	 * @param  string  $action
	 * @param  array   $parameters
	 * @return string
	 */
	protected static function convention($action, $parameters)
211
	{
212 213 214 215
		list($bundle, $action) = Bundle::parse($action);

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

Chris Berthe committed
216
		// If a bundle exists for the action, we will attempt to use its "handles"
217
		// clause as the root of the generated URL, as the bundle can only handle
Taylor Otwell committed
218
		// URIs that begin with that string and no others.
219 220
		$root = $bundle['handles'] ?: '';

221 222
		$parameters = implode('/', $parameters);

223 224
		// 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
225
		// translated into URI slashes for the URL.
226
		$uri = $root.'/'.str_replace(array('.', '@'), '/', $action);
227

228 229 230
		$uri = static::to(str_finish($uri, '/').$parameters);

		return trim($uri, '/');
231 232 233
	}

	/**
234
	 * Generate an application URL to an asset.
235
	 *
236 237
	 * @param  string  $url
	 * @param  bool    $https
238 239
	 * @return string
	 */
240
	public static function to_asset($url, $https = null)
241
	{
Colin Viebrock committed
242 243
		if (static::valid($url)) return $url;

244 245 246 247 248
		// If a base asset URL is defined in the configuration, use that and don't
		// try and change the HTTP protocol. This allows the delivery of assets
		// through a different server or third-party content delivery network.
		if ($root = Config::get('application.asset_url', false))
		{
Colin Viebrock committed
249 250 251
			return rtrim($root, '/').'/'.ltrim($url, '/');
		}

252
		$url = static::to($url, $https, true);
253

254 255
		// 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
256
		// in the application config from the generated URL.
257 258 259 260
		if (($index = Config::get('application.index')) !== '')
		{
			$url = str_replace($index.'/', '', $url);
		}
261

262
		return $url;
263 264 265
	}

	/**
266
	 * Generate a URL from a route name.
267 268 269
	 *
	 * <code>
	 *		// Create a URL to the "profile" named route
270
	 *		$url = URL::to_route('profile');
271
	 *
272 273
	 *		// Create a URL to the "profile" named route with wildcard parameters
	 *		$url = URL::to_route('profile', array($username));
274
	 * </code>
275 276 277 278
	 *
	 * @param  string  $name
	 * @param  array   $parameters
	 * @return string
279
	 */
280
	public static function to_route($name, $parameters = array())
281
	{
282
		if (is_null($route = Routing\Router::find($name)))
283
		{
284
			throw new \Exception("Error creating URL for undefined route [$name].");
285 286
		}

287
		// To determine whether the URL should be HTTPS or not, we look for the "https"
288 289
		// 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.
290
		$https = array_get(current($route), 'https', null);
291

Taylor Otwell committed
292 293 294
		$uri = trim(static::transpose(key($route), $parameters), '/');

		return static::to($uri, $https);
295 296 297
	}

	/**
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
	 * Get the URL to switch language, keeping the current page or not
	 *
	 * @param  string  $language  The new language
	 * @param  boolean $reset     Whether navigation should be reset
	 * @return string             An URL
	 */
	public static function to_language($language, $reset = false)
	{
		// Get the url to use as base
		$url = $reset ? URL::home() : URL::to(URI::current());

		// Validate the language
		if (!in_array($language, Config::get('application.languages')))
		{
			return $url;
		}

		// Get the language we're switching from and the one we're going to
		$from = '/'.Config::get('application.language').'/';
		$to   = '/'.$language.'/';

		return str_replace($from, $to, $url);
	}

	/**
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
	 * 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
344 345
		// in the array of parameters that were passed to us.
		$uri = preg_replace('/\(.+?\)/', '', $uri);
346 347

		return trim($uri, '/');
348 349
	}

350 351 352 353 354 355 356 357 358 359 360
	/**
	 * Determine if the given URL is valid.
	 *
	 * @param  string  $url
	 * @return bool
	 */
	public static function valid($url)
	{
		return filter_var($url, FILTER_VALIDATE_URL) !== false;
	}

Dayle Rees committed
361
}