PageRenderTime 27ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/library/core/class.router.php

https://github.com/Emaratilicious/Garden
PHP | 208 lines | 149 code | 43 blank | 16 comment | 33 complexity | 5934653f230c2c14c4887c55dd89b283 MD5 | raw file
  1. <?php
  2. class Gdn_Router extends Gdn_Pluggable {
  3. public $Routes;
  4. public $ReservedRoutes;
  5. public $RouteTypes;
  6. public function __construct() {
  7. parent::__construct();
  8. $this->RouteTypes = array(
  9. 'Internal' => 'Internal',
  10. 'Temporary' => 'Temporary (302)',
  11. 'Permanent' => 'Permanent (301)',
  12. 'NotAuthorized' => 'Not Authorized (401)',
  13. 'NotFound' => 'Not Found (404)'
  14. );
  15. $this->ReservedRoutes = array('DefaultController', 'DefaultForumRoot', 'Default404', 'DefaultPermission', 'UpdateMode');
  16. $this->_LoadRoutes();
  17. }
  18. public function GetRoute($Route) {
  19. if (is_numeric($Route) && $Route !== FALSE) {
  20. $Keys = array_keys($this->Routes);
  21. $Route = ArrayValue($Route, $Keys);
  22. }
  23. $Decoded = $this->_DecodeRouteKey($Route);
  24. if ($Decoded !== FALSE && array_key_exists($Decoded, $this->Routes))
  25. $Route = $Decoded;
  26. if ($Route === FALSE || !array_key_exists($Route, $this->Routes))
  27. return FALSE;
  28. //return $this->Routes[$Route];
  29. return array_merge($this->Routes[$Route],array(
  30. 'TypeLocale' => T($this->RouteTypes[$this->Routes[$Route]['Type']]),
  31. 'FinalDestination' => $this->Routes[$Route]['Destination']
  32. ));
  33. }
  34. public function GetDestination($Request) {
  35. $Route = $this->MatchRoute($Request);
  36. if ($Route !== FALSE)
  37. return isset($Route['FinalDestination']) ? $Route['FinalDestination'] : $Route['Destination'];
  38. return FALSE;
  39. }
  40. /**
  41. * Update or add a route to the config table
  42. *
  43. * @return void
  44. */
  45. public function SetRoute($Route, $Destination, $Type) {
  46. $Key = $this->_EncodeRouteKey($Route);
  47. SaveToConfig('Routes.'.$Key, array($Destination, $Type));
  48. $this->_LoadRoutes();
  49. }
  50. public function DeleteRoute($Route) {
  51. $Route = $this->GetRoute($Route);
  52. // Is a valid route?
  53. if ($Route !== FALSE) {
  54. if (!in_array($Route['Route'],$this->ReservedRoutes))
  55. {
  56. RemoveFromConfig('Routes.'.$Route['Key']);
  57. $this->_LoadRoutes();
  58. }
  59. }
  60. }
  61. public function MatchRoute($Request) {
  62. // Check for a literal match
  63. if ($this->GetRoute($Request))
  64. return $this->GetRoute($Request);
  65. foreach ($this->Routes as $Route => $RouteData)
  66. {
  67. // Check for wild-cards
  68. $Route = str_replace(
  69. array(':alphanum', ':num'),
  70. array('([0-9a-zA-Z-_]+)', '([0-9]+)'),
  71. $Route
  72. );
  73. // Check for a match
  74. if (preg_match('#^'.$Route.'#', $Request)) {
  75. // Route matched!
  76. $Final = $this->GetRoute($Route);
  77. $Final['FinalDestination'] = $Final['Destination'];
  78. // Do we have a back-reference?
  79. if (strpos($Final['Destination'], '$') !== FALSE && strpos($Final['Route'], '(') !== FALSE) {
  80. $Final['FinalDestination'] = preg_replace('#^'.$Final['Route'].'#', $Final['Destination'], $Request);
  81. }
  82. return $Final;
  83. }
  84. }
  85. return FALSE; // No route matched
  86. }
  87. public function ReverseRoute($Url) {
  88. $Root = rtrim(Gdn::Request()->Domain().'/'.Gdn::Request()->WebRoot(), '/');
  89. if (StringBeginsWith($Url, $Root)) {
  90. $Url = StringBeginsWith($Url, $Root, TRUE, TRUE);
  91. $WithDomain = TRUE;
  92. } else {
  93. $WithDomain = FALSE;
  94. }
  95. $Url = '/'.ltrim($Url, '/');
  96. foreach ($this->Routes as $Route => $RouteData) {
  97. if ($RouteData['Type'] != 'Internal' || ($RouteData['Reserved'] && $RouteData['Route'] != 'DefaultController'))
  98. continue;
  99. $Destination = '/'.ltrim($RouteData['Destination'], '/');
  100. if ($Destination == $Url) {
  101. $Route = '/'.ltrim($RouteData['Route'], '/');
  102. if ($Route == '/DefaultController')
  103. $Route = '/';
  104. if ($WithDomain)
  105. return $Root.$Route;
  106. else
  107. return $Route;
  108. }
  109. }
  110. if ($WithDomain)
  111. return $Root.$Url;
  112. else
  113. return $Url;
  114. }
  115. public function GetRouteTypes() {
  116. $RT = array();
  117. foreach ($this->RouteTypes as $RouteType => $RouteTypeText) {
  118. $RT[$RouteType] = T($RouteTypeText);
  119. }
  120. return $RT;
  121. }
  122. private function _LoadRoutes() {
  123. $Routes = Gdn::Config('Routes', array());
  124. $this->EventArguments['Routes'] = &$Routes;
  125. $this->FireEvent("BeforeLoadRoutes");
  126. foreach ($Routes as $Key => $Destination) {
  127. $Route = $this->_DecodeRouteKey($Key);
  128. $RouteData = $this->_ParseRoute($Destination);
  129. $this->Routes[$Route] = array_merge(array(
  130. 'Route' => $Route,
  131. 'Key' => $Key,
  132. 'Reserved' => in_array($Route,$this->ReservedRoutes)
  133. ), $RouteData);
  134. }
  135. $this->FireEvent("AfterLoadRoutes");
  136. }
  137. private function _ParseRoute($Destination) {
  138. // If Destination is a serialized array
  139. if (is_string($Destination) && ($Decoded = @unserialize($Destination)) !== FALSE)
  140. $Destination = $Decoded;
  141. // If Destination is a short array
  142. if (is_array($Destination) && sizeof($Destination) == 1)
  143. $Destination = $Destination[0];
  144. // If Destination is a simple string...
  145. if (!is_array($Destination))
  146. $Destination = $this->_FormatRoute($Destination, 'Internal');
  147. // If Destination is an array with no named keys...
  148. if (!array_key_exists('Destination', $Destination))
  149. $Destination = $this->_FormatRoute($Destination[0], $Destination[1]);
  150. return $Destination;
  151. }
  152. private function _FormatRoute($Destination, $RouteType) {
  153. return array(
  154. 'Destination' => $Destination,
  155. 'Type' => $RouteType
  156. );
  157. }
  158. protected function _EncodeRouteKey($Key) {
  159. return str_replace('/','_',in_array($Key,$this->ReservedRoutes) ? $Key : base64_encode($Key));
  160. }
  161. protected function _DecodeRouteKey($Key) {
  162. return in_array($Key,$this->ReservedRoutes) ? $Key : base64_decode(str_replace('_','/',$Key));
  163. }
  164. }
  165. ?>