PageRenderTime 382ms CodeModel.GetById 151ms app.highlight 66ms RepoModel.GetById 85ms app.codeStats 0ms

/halogy/libraries/Router.php

https://bitbucket.org/haloweb/halogy-1.0/
PHP | 389 lines | 177 code | 57 blank | 155 comment | 26 complexity | 589c2c1cc5b606106f699ffd09c6e279 MD5 | raw file
  1<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2/**
  3 * CodeIgniter
  4 *
  5 * An open source application development framework for PHP 4.3.2 or newer
  6 *
  7 * @package		CodeIgniter
  8 * @author		ExpressionEngine Dev Team
  9 * @copyright	Copyright (c) 2008 - 2009, EllisLab, Inc.
 10 * @license		http://codeigniter.com/user_guide/license.html
 11 * @link		http://codeigniter.com
 12 * @since		Version 1.0
 13 * @filesource
 14 */
 15
 16// ------------------------------------------------------------------------
 17
 18/**
 19 * Router Class
 20 *
 21 * Parses URIs and determines routing
 22 *
 23 * @package		CodeIgniter
 24 * @subpackage	Libraries
 25 * @author		ExpressionEngine Dev Team
 26 * @category	Libraries
 27 * @link		http://codeigniter.com/user_guide/general/routing.html
 28 */
 29class CI_Router {
 30
 31	var $config;	
 32	var $routes 		= array();
 33	var $error_routes	= array();
 34	var $class			= '';
 35	var $method			= 'index';
 36	var $directory		= '';
 37	var $uri_protocol 	= 'auto';
 38	var $default_controller;
 39	var $scaffolding_request = FALSE; // Must be set to FALSE
 40	
 41	/**
 42	 * Constructor
 43	 *
 44	 * Runs the route mapping function.
 45	 */
 46	function CI_Router()
 47	{
 48		$this->config =& load_class('Config');
 49		$this->uri =& load_class('URI');
 50		$this->_set_routing();
 51		log_message('debug', "Router Class Initialized");
 52	}
 53	
 54	// --------------------------------------------------------------------
 55	
 56	/**
 57	 * Set the route mapping
 58	 *
 59	 * This function determines what should be served based on the URI request,
 60	 * as well as any "routes" that have been set in the routing config file.
 61	 *
 62	 * @access	private
 63	 * @return	void
 64	 */
 65	function _set_routing()
 66	{
 67		// Are query strings enabled in the config file?
 68		// If so, we're done since segment based URIs are not used with query strings.
 69		if ($this->config->item('enable_query_strings') === TRUE AND isset($_GET[$this->config->item('controller_trigger')]))
 70		{
 71			$this->set_class(trim($this->uri->_filter_uri($_GET[$this->config->item('controller_trigger')])));
 72
 73			if (isset($_GET[$this->config->item('function_trigger')]))
 74			{
 75				$this->set_method(trim($this->uri->_filter_uri($_GET[$this->config->item('function_trigger')])));
 76			}
 77			
 78			return;
 79		}
 80		
 81		// Load the routes.php file.
 82		@include(APPPATH.'config/routes'.EXT);
 83		$this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route;
 84		unset($route);
 85
 86		// Set the default controller so we can display it in the event
 87		// the URI doesn't correlated to a valid controller.
 88		$this->default_controller = ( ! isset($this->routes['default_controller']) OR $this->routes['default_controller'] == '') ? FALSE : strtolower($this->routes['default_controller']);	
 89		
 90		// Fetch the complete URI string
 91		$this->uri->_fetch_uri_string();
 92	
 93		// Is there a URI string? If not, the default controller specified in the "routes" file will be shown.
 94		if ($this->uri->uri_string == '')
 95		{
 96			if ($this->default_controller === FALSE)
 97			{
 98				show_error("Unable to determine what should be displayed. A default route has not been specified in the routing file.");
 99			}
100			
101			if (strpos($this->default_controller, '/') !== FALSE)
102			{
103				$x = explode('/', $this->default_controller);
104
105				$this->set_class(end($x));
106				$this->set_method('index');
107				$this->_set_request($x);
108			}
109			else
110			{
111				$this->set_class($this->default_controller);
112				$this->set_method('index');
113				$this->_set_request(array($this->default_controller, 'index'));
114			}
115
116			// re-index the routed segments array so it starts with 1 rather than 0
117			$this->uri->_reindex_segments();
118			
119			log_message('debug', "No URI present. Default controller set.");
120			return;
121		}
122		unset($this->routes['default_controller']);
123		
124		// Do we need to remove the URL suffix?
125		$this->uri->_remove_url_suffix();
126		
127		// Compile the segments into an array
128		$this->uri->_explode_segments();
129		
130		// Parse any custom routing that may exist
131		$this->_parse_routes();		
132		
133		// Re-index the segment array so that it starts with 1 rather than 0
134		$this->uri->_reindex_segments();
135	}
136	
137	// --------------------------------------------------------------------
138	
139	/**
140	 * Set the Route
141	 *
142	 * This function takes an array of URI segments as
143	 * input, and sets the current class/method
144	 *
145	 * @access	private
146	 * @param	array
147	 * @param	bool
148	 * @return	void
149	 */
150	function _set_request($segments = array())
151	{
152		$segments = $this->_validate_request($segments);
153		
154		if (count($segments) == 0)
155		{
156			return;
157		}
158						
159		$this->set_class($segments[0]);
160		
161		if (isset($segments[1]))
162		{
163			// A scaffolding request. No funny business with the URL
164			if ($this->routes['scaffolding_trigger'] == $segments[1] AND $segments[1] != '_ci_scaffolding')
165			{
166				$this->scaffolding_request = TRUE;
167				unset($this->routes['scaffolding_trigger']);
168			}
169			else
170			{
171				// A standard method request
172				$this->set_method($segments[1]);
173			}
174		}
175		else
176		{
177			// This lets the "routed" segment array identify that the default
178			// index method is being used.
179			$segments[1] = 'index';
180		}
181		
182		// Update our "routed" segment array to contain the segments.
183		// Note: If there is no custom routing, this array will be
184		// identical to $this->uri->segments
185		$this->uri->rsegments = $segments;
186	}
187	
188	// --------------------------------------------------------------------
189	
190	/**
191	 * Validates the supplied segments.  Attempts to determine the path to
192	 * the controller.
193	 *
194	 * @access	private
195	 * @param	array
196	 * @return	array
197	 */	
198	function _validate_request($segments)
199	{
200		// Does the requested controller exist in the root folder?
201		if (file_exists(APPPATH.'controllers/'.$segments[0].EXT))
202		{
203			return $segments;
204		}
205
206		// Is the controller in a sub-folder?
207		if (is_dir(APPPATH.'controllers/'.$segments[0]))
208		{		
209			// Set the directory and remove it from the segment array
210			$this->set_directory($segments[0]);
211			$segments = array_slice($segments, 1);
212			
213			if (count($segments) > 0)
214			{
215				// Does the requested controller exist in the sub-folder?
216				if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].EXT))
217				{
218					show_404($this->fetch_directory().$segments[0]);
219				}
220			}
221			else
222			{
223				$this->set_class($this->default_controller);
224				$this->set_method('index');
225			
226				// Does the default controller exist in the sub-folder?
227				if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.EXT))
228				{
229					$this->directory = '';
230					return array();
231				}
232			
233			}
234
235			return $segments;
236		}
237
238		// Can't find the requested controller...
239		show_404($segments[0]);
240	}
241
242	// --------------------------------------------------------------------
243
244	/**
245	 *  Parse Routes
246	 *
247	 * This function matches any routes that may exist in
248	 * the config/routes.php file against the URI to
249	 * determine if the class/method need to be remapped.
250	 *
251	 * @access	private
252	 * @return	void
253	 */
254	function _parse_routes()
255	{
256		// Do we even have any custom routing to deal with?
257		// There is a default scaffolding trigger, so we'll look just for 1
258		if (count($this->routes) == 1)
259		{
260			$this->_set_request($this->uri->segments);
261			return;
262		}
263
264		// Turn the segment array into a URI string
265		$uri = implode('/', $this->uri->segments);
266
267		// Is there a literal match?  If so we're done
268		if (isset($this->routes[$uri]))
269		{
270			$this->_set_request(explode('/', $this->routes[$uri]));		
271			return;
272		}
273				
274		// Loop through the route array looking for wild-cards
275		foreach ($this->routes as $key => $val)
276		{						
277			// Convert wild-cards to RegEx
278			$key = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $key));
279			
280			// Does the RegEx match?
281			if (preg_match('#^'.$key.'$#', $uri))
282			{			
283				// Do we have a back-reference?
284				if (strpos($val, '$') !== FALSE AND strpos($key, '(') !== FALSE)
285				{
286					$val = preg_replace('#^'.$key.'$#', $val, $uri);
287				}
288			
289				$this->_set_request(explode('/', $val));		
290				return;
291			}
292		}
293
294		// If we got this far it means we didn't encounter a
295		// matching route so we'll set the site default route
296		$this->_set_request($this->uri->segments);
297	}
298
299	// --------------------------------------------------------------------
300	
301	/**
302	 * Set the class name
303	 *
304	 * @access	public
305	 * @param	string
306	 * @return	void
307	 */	
308	function set_class($class)
309	{
310		$this->class = $class;
311	}
312	
313	// --------------------------------------------------------------------
314	
315	/**
316	 * Fetch the current class
317	 *
318	 * @access	public
319	 * @return	string
320	 */	
321	function fetch_class()
322	{
323		return $this->class;
324	}
325	
326	// --------------------------------------------------------------------
327	
328	/**
329	 *  Set the method name
330	 *
331	 * @access	public
332	 * @param	string
333	 * @return	void
334	 */	
335	function set_method($method)
336	{
337		$this->method = $method;
338	}
339
340	// --------------------------------------------------------------------
341	
342	/**
343	 *  Fetch the current method
344	 *
345	 * @access	public
346	 * @return	string
347	 */	
348	function fetch_method()
349	{
350		if ($this->method == $this->fetch_class())
351		{
352			return 'index';
353		}
354
355		return $this->method;
356	}
357
358	// --------------------------------------------------------------------
359	
360	/**
361	 *  Set the directory name
362	 *
363	 * @access	public
364	 * @param	string
365	 * @return	void
366	 */	
367	function set_directory($dir)
368	{
369		$this->directory = $dir.'/';
370	}
371
372	// --------------------------------------------------------------------
373	
374	/**
375	 *  Fetch the sub-directory (if any) that contains the requested controller class
376	 *
377	 * @access	public
378	 * @return	string
379	 */	
380	function fetch_directory()
381	{
382		return $this->directory;
383	}
384
385}
386// END Router Class
387
388/* End of file Router.php */
389/* Location: ./system/libraries/Router.php */