url.php 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. <?php namespace Laravel; use Laravel\Routing\Router, Laravel\Routing\Route;
  2. class URL {
  3. /**
  4. * The cached base URL.
  5. *
  6. * @var string
  7. */
  8. public static $base;
  9. /**
  10. * Get the full URI including the query string.
  11. *
  12. * @return string
  13. */
  14. public static function full()
  15. {
  16. return static::to(URI::full());
  17. }
  18. /**
  19. * Get the full URL for the current request.
  20. *
  21. * @return string
  22. */
  23. public static function current()
  24. {
  25. return static::to(URI::current(), null, false, false);
  26. }
  27. /**
  28. * Get the URL for the application root.
  29. *
  30. * @param bool $https
  31. * @return string
  32. */
  33. public static function home($https = null)
  34. {
  35. $route = Router::find('home');
  36. // If a route named "home" exists, we'll route to that instead of using
  37. // the single slash root URI. This allows the HTTPS attribute to be
  38. // respected instead of being hard-coded in the redirect.
  39. if ( ! is_null($route))
  40. {
  41. return static::to_route('home');
  42. }
  43. return static::to('/', $https);
  44. }
  45. /**
  46. * Get the base URL of the application.
  47. *
  48. * @return string
  49. */
  50. public static function base()
  51. {
  52. if (isset(static::$base)) return static::$base;
  53. $base = 'http://localhost';
  54. // If the application's URL configuration is set, we will just use that
  55. // instead of trying to guess the URL from the $_SERVER array's host
  56. // and script variables as this is a more reliable method.
  57. if (($url = Config::get('application.url')) !== '')
  58. {
  59. $base = $url;
  60. }
  61. else
  62. {
  63. $base = Request::foundation()->getRootUrl();
  64. }
  65. return static::$base = $base;
  66. }
  67. /**
  68. * Generate an application URL.
  69. *
  70. * <code>
  71. * // Create a URL to a location within the application
  72. * $url = URL::to('user/profile');
  73. *
  74. * // Create a HTTPS URL to a location within the application
  75. * $url = URL::to('user/profile', true);
  76. * </code>
  77. *
  78. * @param string $url
  79. * @param bool $https
  80. * @param bool $asset
  81. * @param bool $locale
  82. * @return string
  83. */
  84. public static function to($url = '', $https = null, $asset = false, $locale = true)
  85. {
  86. // If the given URL is already valid or begins with a hash, we'll just return
  87. // the URL unchanged since it is already well formed. Otherwise we will add
  88. // the base URL of the application and return the full URL.
  89. if (static::valid($url) or starts_with($url, '#'))
  90. {
  91. return $url;
  92. }
  93. // Unless $https is specified (true or false), we maintain the current request
  94. // security for any new links generated. So https for all secure links.
  95. if (is_null($https)) $https = Request::secure();
  96. $root = static::base();
  97. if ( ! $asset)
  98. {
  99. $root .= '/'.Config::get('application.index');
  100. }
  101. $languages = Config::get('application.languages');
  102. if ( ! $asset and $locale and count($languages) > 0)
  103. {
  104. if (in_array($default = Config::get('application.language'), $languages))
  105. {
  106. $root = rtrim($root, '/').'/'.$default;
  107. }
  108. }
  109. // Since SSL is not often used while developing the application, we allow the
  110. // developer to disable SSL on all framework generated links to make it more
  111. // convenient to work with the site while developing locally.
  112. if ($https and Config::get('application.ssl'))
  113. {
  114. $root = preg_replace('~http://~', 'https://', $root, 1);
  115. }
  116. else
  117. {
  118. $root = preg_replace('~https://~', 'http://', $root, 1);
  119. }
  120. return rtrim($root, '/').'/'.ltrim($url, '/');
  121. }
  122. /**
  123. * Generate an application URL with HTTPS.
  124. *
  125. * @param string $url
  126. * @return string
  127. */
  128. public static function to_secure($url = '')
  129. {
  130. return static::to($url, true);
  131. }
  132. /**
  133. * Generate a URL to a controller action.
  134. *
  135. * <code>
  136. * // Generate a URL to the "index" method of the "user" controller
  137. * $url = URL::to_action('user@index');
  138. *
  139. * // Generate a URL to http://example.com/user/profile/taylor
  140. * $url = URL::to_action('user@profile', array('taylor'));
  141. * </code>
  142. *
  143. * @param string $action
  144. * @param array $parameters
  145. * @return string
  146. */
  147. public static function to_action($action, $parameters = array())
  148. {
  149. // This allows us to use true reverse routing to controllers, since
  150. // URIs may be setup to handle the action that do not follow the
  151. // typical Laravel controller URI conventions.
  152. $route = Router::uses($action);
  153. if ( ! is_null($route))
  154. {
  155. return static::explicit($route, $action, $parameters);
  156. }
  157. // If no route was found that handled the given action, we'll just
  158. // generate the URL using the typical controller routing setup
  159. // for URIs and turn SSL to false by default.
  160. else
  161. {
  162. return static::convention($action, $parameters);
  163. }
  164. }
  165. /**
  166. * Generate an action URL from a route definition
  167. *
  168. * @param array $route
  169. * @param string $action
  170. * @param array $parameters
  171. * @return string
  172. */
  173. protected static function explicit($route, $action, $parameters)
  174. {
  175. $https = array_get(current($route), 'https', null);
  176. return static::to(static::transpose(key($route), $parameters), $https);
  177. }
  178. /**
  179. * Generate an action URI by convention.
  180. *
  181. * @param string $action
  182. * @param array $parameters
  183. * @return string
  184. */
  185. protected static function convention($action, $parameters)
  186. {
  187. list($bundle, $action) = Bundle::parse($action);
  188. $bundle = Bundle::get($bundle);
  189. // If a bundle exists for the action, we will attempt to use its "handles"
  190. // clause as the root of the generated URL, as the bundle can only handle
  191. // URIs that begin with that string and no others.
  192. $root = $bundle['handles'] ?: '';
  193. $parameters = implode('/', $parameters);
  194. // We'll replace both dots and @ signs in the URI since both are used
  195. // to specify the controller and action, and by convention should be
  196. // translated into URI slashes for the URL.
  197. $uri = $root.'/'.str_replace(array('.', '@'), '/', $action);
  198. $uri = static::to(str_finish($uri, '/').$parameters);
  199. return trim($uri, '/');
  200. }
  201. /**
  202. * Generate an application URL to an asset.
  203. *
  204. * @param string $url
  205. * @param bool $https
  206. * @return string
  207. */
  208. public static function to_asset($url, $https = null)
  209. {
  210. if (static::valid($url) or static::valid('http:'.$url)) return $url;
  211. // If a base asset URL is defined in the configuration, use that and don't
  212. // try and change the HTTP protocol. This allows the delivery of assets
  213. // through a different server or third-party content delivery network.
  214. if ($root = Config::get('application.asset_url', false))
  215. {
  216. return rtrim($root, '/').'/'.ltrim($url, '/');
  217. }
  218. $url = static::to($url, $https, true);
  219. // Since assets are not served by Laravel, we do not need to come through
  220. // the front controller. So, we'll remove the application index specified
  221. // in the application config from the generated URL.
  222. if (($index = Config::get('application.index')) !== '')
  223. {
  224. $url = str_replace($index.'/', '', $url);
  225. }
  226. return $url;
  227. }
  228. /**
  229. * Generate a URL from a route name.
  230. *
  231. * <code>
  232. * // Create a URL to the "profile" named route
  233. * $url = URL::to_route('profile');
  234. *
  235. * // Create a URL to the "profile" named route with wildcard parameters
  236. * $url = URL::to_route('profile', array($username));
  237. * </code>
  238. *
  239. * @param string $name
  240. * @param array $parameters
  241. * @return string
  242. */
  243. public static function to_route($name, $parameters = array())
  244. {
  245. if (is_null($route = Routing\Router::find($name)))
  246. {
  247. throw new \Exception("Error creating URL for undefined route [$name].");
  248. }
  249. // To determine whether the URL should be HTTPS or not, we look for the "https"
  250. // value on the route action array. The route has control over whether the URL
  251. // should be generated with an HTTPS protocol string or just HTTP.
  252. $https = array_get(current($route), 'https', null);
  253. $uri = trim(static::transpose(key($route), $parameters), '/');
  254. return static::to($uri, $https);
  255. }
  256. /**
  257. * Get the URL to switch language, keeping the current page or not
  258. *
  259. * @param string $language The new language
  260. * @param boolean $reset Whether navigation should be reset
  261. * @return string An URL
  262. */
  263. public static function to_language($language, $reset = false)
  264. {
  265. // Get the url to use as base
  266. $url = $reset ? URL::home() : URL::to(URI::current());
  267. // Validate the language
  268. if (!in_array($language, Config::get('application.languages')))
  269. {
  270. return $url;
  271. }
  272. // Get the language we're switching from and the one we're going to
  273. $from = '/'.Config::get('application.language').'/';
  274. $to = '/'.$language.'/';
  275. return str_replace($from, $to, $url);
  276. }
  277. /**
  278. * Substitute the parameters in a given URI.
  279. *
  280. * @param string $uri
  281. * @param array $parameters
  282. * @return string
  283. */
  284. public static function transpose($uri, $parameters)
  285. {
  286. // Spin through each route parameter and replace the route wildcard segment
  287. // with the corresponding parameter passed to the method. Afterwards, we'll
  288. // replace all of the remaining optional URI segments.
  289. foreach ((array) $parameters as $parameter)
  290. {
  291. if ( ! is_null($parameter))
  292. {
  293. $uri = preg_replace('/\(.+?\)/', $parameter, $uri, 1);
  294. }
  295. }
  296. // If there are any remaining optional place-holders, we'll just replace
  297. // them with empty strings since not every optional parameter has to be
  298. // in the array of parameters that were passed to us.
  299. $uri = preg_replace('/\(.+?\)/', '', $uri);
  300. return trim($uri, '/');
  301. }
  302. /**
  303. * Determine if the given URL is valid.
  304. *
  305. * @param string $url
  306. * @return bool
  307. */
  308. public static function valid($url)
  309. {
  310. return filter_var($url, FILTER_VALIDATE_URL) !== false;
  311. }
  312. }