PageRenderTime 61ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/application/third_party/HMVC/Router.php

https://gitlab.com/digitalpoetry/catt-old
PHP | 293 lines | 208 code | 29 blank | 56 comment | 11 complexity | 45fbe41befb6af3f1b1db7e5d5def98a MD5 | raw file
  1. <?php
  2. /**
  3. * Code All The Things!
  4. *
  5. * A project kickstarter based on the Sprint & CodeIgnitor frameworks.
  6. *
  7. * @package DigitalPoetry\CATT\ThirdParty
  8. * @author Jesse LaReaux <jlareaux@gmail.com>
  9. * @copyright Copyright (c) 2016, DigitalPoetry (http://digitalpoetry.studio/).
  10. * @license http://opensource.org/licenses/MIT MIT License
  11. * @link http://codeallthethings.xyz
  12. * @version 0.1.0 Shiny Things
  13. * @filesource
  14. */
  15. defined('BASEPATH') OR exit('No direct script access allowed');
  16. /**
  17. * @inheritdoc
  18. */
  19. class HMVC_Router extends CI_Router {
  20. /**
  21. * Current module name
  22. *
  23. * @var string
  24. * @access public
  25. */
  26. var $module = '';
  27. /**
  28. * Constructor
  29. *
  30. * Runs the route mapping function.
  31. */
  32. function __construct() {
  33. $this->config =& load_class('Config', 'core');
  34. // Process 'modules_locations' from config
  35. $locations = $this->config->item('modules_locations');
  36. if (!$locations) {
  37. $locations = array(APPPATH . 'modules/');
  38. } else if (!is_array($locations)) {
  39. $locations = array($locations);
  40. }
  41. // Make sure all paths are the same format
  42. foreach ($locations as &$location) {
  43. $location = realpath($location);
  44. $location = str_replace('\\', '/', $location);
  45. $location = rtrim($location, '/') . '/';
  46. }
  47. $this->config->set_item('modules_locations', $locations);
  48. parent::__construct();
  49. }
  50. /**
  51. * Validates the supplied segments. Attempts to determine the path to
  52. * the controller.
  53. *
  54. * @access private
  55. * @param array
  56. * @return array
  57. */
  58. function _validate_request($segments) {
  59. if (count($segments) == 0) {
  60. return $segments;
  61. }
  62. // Locate the controller with modules support
  63. if ($located = $this->locate($segments)) {
  64. return $located;
  65. }
  66. // Is there a 404 override?
  67. if (!empty($this->routes['404_override'])) {
  68. $segments = explode('/', $this->routes['404_override']);
  69. if ($located = $this->locate($segments)) {
  70. return $located;
  71. }
  72. }
  73. // Nothing else to do at this point but show a 404
  74. show_404($segments[0]);
  75. }
  76. /**
  77. * Parse Routes
  78. *
  79. * This function matches any routes that may exist in
  80. * the config/routes.php file against the URI to
  81. * determine if the class/method need to be remapped.
  82. *
  83. * NOTE: The first segment must stay the name of the
  84. * module, otherwise it is impossible to detect
  85. * the current module in this method.
  86. *
  87. * @access private
  88. * @return void
  89. */
  90. function _parse_routes() {
  91. // Apply the current module's routing config
  92. // CI v3.x has URI starting at segment 1
  93. $segstart = (intval(substr(CI_VERSION,0,1)) > 2) ? 1 : 0;
  94. if ($module = $this->uri->segment($segstart)) {
  95. foreach ($this->config->item('modules_locations') as $location) {
  96. if (is_file($file = $location . $module . '/config/routes.php')) {
  97. include ($file);
  98. $route = (!isset($route) or !is_array($route)) ? array() : $route;
  99. $this->routes = array_merge($this->routes, $route);
  100. unset($route);
  101. }
  102. }
  103. }
  104. // Let parent do the heavy routing
  105. return parent::_parse_routes();
  106. }
  107. /**
  108. * The logic of locating a controller is grouped in this function
  109. *
  110. * @param array
  111. * @return array
  112. */
  113. function locate($segments) {
  114. // anon function to ucfirst a string if CI ver > 2 (for backwards compatibility)
  115. $_ucfirst = function($cn) {return (intval(substr(CI_VERSION,0,1)) > 2) ? ucfirst($cn) : $cn;};
  116. list($module, $directory, $controller) = array_pad($segments, 3, NULL);
  117. // Look for it in the standar APPPATH/controllers first so that it can override modules.
  118. $c = count($segments);
  119. $s = $segments;
  120. // Loop through our segments and return as soon as a controller
  121. // is found or when such a directory doesn't exist
  122. while ($c-- > 0)
  123. {
  124. $test = $this->directory
  125. .ucfirst($this->translate_uri_dashes === TRUE ? str_replace('-', '_', $s[0]) : $s[0]);
  126. if ( ! file_exists(APPPATH.'controllers/'.$test.'.php') && is_dir(APPPATH.'controllers/'.$this->directory.$s[0]))
  127. {
  128. $this->set_directory(array_shift($s), TRUE);
  129. continue;
  130. }
  131. elseif (file_exists(APPPATH .'controllers/'. $test .'.php'))
  132. {
  133. return $s;
  134. }
  135. }
  136. unset($s);
  137. // Now look for it in all of our modules.
  138. foreach ($this->config->item('modules_locations') as $location) {
  139. $relative = $location;
  140. // Make path relative to controllers directory
  141. $start = rtrim(realpath(APPPATH), '/');
  142. $parts = explode('/', str_replace('\\', '/', $start));
  143. // Iterate all parts and replace absolute part with relative part
  144. for ($i = 1; $i <= count($parts); $i++) {
  145. $relative = str_replace(implode('/', $parts) . '/', str_repeat('../', $i), $relative, $count);
  146. array_pop($parts);
  147. // Stop iteration if found
  148. if ($count)
  149. break;
  150. }
  151. // Does a module exist? (/modules/xyz/controllers/)
  152. if (is_dir($source = $location . $module . '/controllers/')) {
  153. $this->module = $module;
  154. $this->directory = $relative . $module . '/controllers/';
  155. // Module root controller?
  156. if ($directory && is_file($source . $_ucfirst($directory) . '.php')) {
  157. $this->class = $directory;
  158. return array_slice($segments, 1);
  159. }
  160. // Module sub-directory?
  161. if ($directory && is_dir($source . $directory . '/')) {
  162. $source = $source . $directory . '/';
  163. $this->directory .= $directory . '/';
  164. // Module sub-directory controller?
  165. if (is_file($source . $_ucfirst($directory) . '.php')) {
  166. return array_slice($segments, 1);
  167. }
  168. // Module sub-directory default controller?
  169. if (is_file($source . $_ucfirst($this->default_controller) . '.php')) {
  170. $segments[1] = $this->default_controller;
  171. return array_slice($segments, 1);
  172. }
  173. // Module sub-directory sub-controller?
  174. if ($controller && is_file($source . $_ucfirst($controller) . '.php')) {
  175. return array_slice($segments, 2);
  176. }
  177. }
  178. // Module controller?
  179. if (is_file($source . $_ucfirst($module) . '.php')) {
  180. return $segments;
  181. }
  182. // Module default controller?
  183. if (is_file($source . $_ucfirst($this->default_controller) . '.php')) {
  184. $segments[0] = $this->default_controller;
  185. return $segments;
  186. }
  187. }
  188. }
  189. // Default controller?
  190. if (is_file(APPPATH . 'controllers/' . $module . '/' . $_ucfirst($this->default_controller) . '.php')) {
  191. $segments[0] = $this->default_controller;
  192. return $segments;
  193. }
  194. }
  195. /**
  196. * Set the module name
  197. *
  198. * @param string
  199. * @return void
  200. */
  201. function set_module($module) {
  202. $this->module = $module;
  203. }
  204. /**
  205. * Set default controller
  206. *
  207. * First we check in normal APPPATH/controller's location,
  208. * then in Modules named after the default_controller
  209. * @author hArpanet - based on system/core/Router.php
  210. *
  211. * @return void
  212. */
  213. protected function _set_default_controller()
  214. {
  215. // controller in APPPATH/controllers takes priority over module with same name
  216. parent::_set_default_controller();
  217. // see if parent found a controller
  218. $class = $this->fetch_class();
  219. if (empty($class)) {
  220. // no 'normal' controller found,
  221. // get the class/method from the default_controller route
  222. if (sscanf($this->default_controller, '%[^/]/%s', $class, $method) !== 2)
  223. {
  224. $method = 'index';
  225. }
  226. // try to locate default controller in modules
  227. if ($located = $this->locate(array($class, $class, $method))) {
  228. log_message('debug', 'No URI present. Default module controller set.');
  229. }
  230. }
  231. // Nothing found - this will trigger 404 later
  232. }
  233. // --------------------------------------------------------------------
  234. /**
  235. * Fetch the module
  236. *
  237. * @access public
  238. * @return string
  239. */
  240. function fetch_module() {
  241. return $this->module;
  242. }
  243. }