1<?php defined('SYSPATH') OR die('No direct access allowed.');
2/**
3 * URL helper class.
4 *
5 * $Id: url.php 4029 2009-03-03 12:39:32Z Shadowhand $
6 *
7 * @package    Core
8 * @author     Kohana Team
9 * @copyright  (c) 2007-2008 Kohana Team
10 * @license    http://kohanaphp.com/license.html
11 */
12class url_Core {
13
14	/**
15	 * Fetches the current URI.
16	 *
17	 * @param   boolean  include the query string
18	 * @return  string
19	 */
20	public static function current($qs = FALSE)
21	{
22		return ($qs === TRUE) ? Router::$complete_uri : Router::$current_uri;
23	}
24
25	/**
26	 * Base URL, with or without the index page.
27	 *
28	 * If protocol (and core.site_protocol) and core.site_domain are both empty,
29	 * then
30	 *
31	 * @param   boolean  include the index page
32	 * @param   boolean  non-default protocol
33	 * @return  string
34	 */
35	public static function base($index = FALSE, $protocol = FALSE)
36	{
37		if ($protocol == FALSE)
38		{
39			// Use the default configured protocol
40			$protocol = Kohana::config('core.site_protocol');
41		}
42
43		// Load the site domain
44		$site_domain = (string) Kohana::config('core.site_domain', TRUE);
45
46		if ($protocol == FALSE)
47		{
48			if ($site_domain === '' OR $site_domain[0] === '/')
49			{
50				// Use the configured site domain
51				$base_url = $site_domain;
52			}
53			else
54			{
55				// Guess the protocol to provide full http://domain/path URL
56				$base_url = ((empty($_SERVER['HTTPS']) OR $_SERVER['HTTPS'] === 'off') ? 'http' : 'https').'://'.$site_domain;
57			}
58		}
59		else
60		{
61			if ($site_domain === '' OR $site_domain[0] === '/')
62			{
63				// Guess the server name if the domain starts with slash
64				$base_url = $protocol.'://'.$_SERVER['HTTP_HOST'].$site_domain;
65			}
66			else
67			{
68				// Use the configured site domain
69				$base_url = $protocol.'://'.$site_domain;
70			}
71		}
72
73		if ($index === TRUE AND $index = Kohana::config('core.index_page'))
74		{
75			// Append the index page
76			$base_url = $base_url.$index;
77		}
78
79		// Force a slash on the end of the URL
80		return rtrim($base_url, '/').'/';
81	}
82
83	/**
84	 * Fetches an absolute site URL based on a URI segment.
85	 *
86	 * @param   string  site URI to convert
87	 * @param   string  non-default protocol
88	 * @return  string
89	 */
90	public static function site($uri = '', $protocol = FALSE)
91	{
92		if ($path = trim(parse_url($uri, PHP_URL_PATH), '/'))
93		{
94			// Add path suffix
95			$path .= Kohana::config('core.url_suffix');
96		}
97
98		if ($query = parse_url($uri, PHP_URL_QUERY))
99		{
100			// ?query=string
101			$query = '?'.$query;
102		}
103
104		if ($fragment = parse_url($uri, PHP_URL_FRAGMENT))
105		{
106			// #fragment
107			$fragment =  '#'.$fragment;
108		}
109
110		// Concat the URL
111		return url::base(TRUE, $protocol).$path.$query.$fragment;
112	}
113
114	/**
115	 * Return the URL to a file. Absolute filenames and relative filenames
116	 * are allowed.
117	 *
118	 * @param   string   filename
119	 * @param   boolean  include the index page
120	 * @return  string
121	 */
122	public static function file($file, $index = FALSE)
123	{
124		if (strpos($file, '://') === FALSE)
125		{
126			// Add the base URL to the filename
127			$file = url::base($index).$file;
128		}
129
130		return $file;
131	}
132
133	/**
134	 * Merges an array of arguments with the current URI and query string to
135	 * overload, instead of replace, the current query string.
136	 *
137	 * @param   array   associative array of arguments
138	 * @return  string
139	 */
140	public static function merge(array $arguments)
141	{
142		if ($_GET === $arguments)
143		{
144			$query = Router::$query_string;
145		}
146		elseif ($query = http_build_query(array_merge($_GET, $arguments)))
147		{
148			$query = '?'.$query;
149		}
150
151		// Return the current URI with the arguments merged into the query string
152		return Router::$current_uri.$query;
153	}
154
155	/**
156	 * Convert a phrase to a URL-safe title.
157	 *
158	 * @param   string  phrase to convert
159	 * @param   string  word separator (- or _)
160	 * @return  string
161	 */
162	public static function title($title, $separator = '-')
163	{
164		$separator = ($separator === '-') ? '-' : '_';
165
166		// Replace accented characters by their unaccented equivalents
167		$title = utf8::transliterate_to_ascii($title);
168
169		// Remove all characters that are not the separator, a-z, 0-9, or whitespace
170		$title = preg_replace('/[^'.$separator.'a-z0-9\s]+/', '', strtolower($title));
171
172		// Replace all separator characters and whitespace by a single separator
173		$title = preg_replace('/['.$separator.'\s]+/', $separator, $title);
174
175		// Trim separators from the beginning and end
176		return trim($title, $separator);
177	}
178
179	/**
180	 * Sends a page redirect header and runs the system.redirect Event.
181	 *
182	 * @param  mixed   string site URI or URL to redirect to, or array of strings if method is 300
183	 * @param  string  HTTP method of redirect
184	 * @return void
185	 */
186	public static function redirect($uri = '', $method = '302')
187	{
188		if (Event::has_run('system.send_headers'))
189		{
190			return FALSE;
191		}
192
193		$codes = array
194		(
195			'refresh' => 'Refresh',
196			'300' => 'Multiple Choices',
197			'301' => 'Moved Permanently',
198			'302' => 'Found',
199			'303' => 'See Other',
200			'304' => 'Not Modified',
201			'305' => 'Use Proxy',
202			'307' => 'Temporary Redirect'
203		);
204
205		// Validate the method and default to 302
206		$method = isset($codes[$method]) ? (string) $method : '302';
207
208		if ($method === '300')
209		{
210			$uri = (array) $uri;
211
212			$output = '<ul>';
213			foreach ($uri as $link)
214			{
215				$output .= '<li>'.html::anchor($link).'</li>';
216			}
217			$output .= '</ul>';
218
219			// The first URI will be used for the Location header
220			$uri = $uri[0];
221		}
222		else
223		{
224			$output = '<p>'.html::anchor($uri).'</p>';
225		}
226
227		// Run the redirect event
228		Event::run('system.redirect', $uri);
229
230		if (strpos($uri, '://') === FALSE)
231		{
232			// HTTP headers expect absolute URLs
233			$uri = url::site($uri, request::protocol());
234		}
235
236		if ($method === 'refresh')
237		{
238			header('Refresh: 0; url='.$uri);
239		}
240		else
241		{
242			header('HTTP/1.1 '.$method.' '.$codes[$method]);
243			header('Location: '.$uri);
244		}
245
246		// We are about to exit, so run the send_headers event
247		Event::run('system.send_headers');
248
249		exit('<h1>'.$method.' - '.$codes[$method].'</h1>'.$output);
250	}
251
252} // End url