PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/default_www/frontend/core/engine/url.php

https://github.com/bet0x/forkcms
PHP | 472 lines | 189 code | 91 blank | 192 comment | 41 complexity | f4b2e965043b828c61b3955166dc2101 MD5 | raw file
  1. <?php
  2. /**
  3. * This class will handle the incomming URL.
  4. *
  5. * @package frontend
  6. * @subpackage core
  7. *
  8. * @author Tijs Verkoyen <tijs@netlash.com>
  9. * @author Davy Hellemans <davy@netlash.com>
  10. * @author Dieter Vanden Eynde <dieter@netlash.com>
  11. * @since 2.0
  12. */
  13. class FrontendURL
  14. {
  15. /**
  16. * The pages
  17. *
  18. * @var array
  19. */
  20. private $pages = array();
  21. /**
  22. * The parameters
  23. *
  24. * @var array
  25. */
  26. private $parameters = array();
  27. /**
  28. * The host, will be used for cookies
  29. *
  30. * @var string
  31. */
  32. private $host;
  33. /**
  34. * The querystring
  35. *
  36. * @var string
  37. */
  38. private $queryString;
  39. /**
  40. * Default constructor
  41. *
  42. * @return void
  43. */
  44. public function __construct()
  45. {
  46. // add ourself to the reference so other classes can retrieve us
  47. Spoon::set('url', $this);
  48. // if there is a trailing slash we permanent redirect to the page without slash
  49. if(mb_strlen($_SERVER['REQUEST_URI']) != 1 && mb_substr($_SERVER['REQUEST_URI'], -1) == '/') SpoonHTTP::redirect(mb_substr($_SERVER['REQUEST_URI'], 0, -1), 301);
  50. // set query-string for later use
  51. $this->setQueryString($_SERVER['REQUEST_URI']);
  52. // set host for later use
  53. $this->setHost($_SERVER['HTTP_HOST']);
  54. // process URL
  55. $this->processQueryString();
  56. // set constant
  57. define('SELF', SITE_URL . '/' . $this->queryString);
  58. }
  59. /**
  60. * Get the domain
  61. *
  62. * @return string The current domain (without www.)
  63. */
  64. public function getDomain()
  65. {
  66. // get host
  67. $host = $this->getHost();
  68. // replace
  69. return str_replace('www.', '', $host);
  70. }
  71. /**
  72. * Get the host
  73. *
  74. * @return string
  75. */
  76. public function getHost()
  77. {
  78. return $this->host;
  79. }
  80. /**
  81. * Get a page specified by the given index
  82. *
  83. * @return mixed
  84. * @param int $index The index (0-based).
  85. */
  86. public function getPage($index)
  87. {
  88. // redefine
  89. $index = (int) $index;
  90. // does the index exists
  91. if(isset($this->pages[$index])) return $this->pages[$index];
  92. // fallback
  93. return null;
  94. }
  95. /**
  96. * Return all the pages
  97. *
  98. * @return array
  99. */
  100. public function getPages()
  101. {
  102. return $this->pages;
  103. }
  104. /**
  105. * Get a parameter specified by the given index
  106. * The function will return null if the key is not available
  107. * By default we will cast the return value into a string, if you want something else specify it by passing the wanted type.
  108. *
  109. * @return mixed
  110. * @param mixed $index The index of the parameter.
  111. * @param string[optional] $type The return type, possible values are: bool, boolean, int, integer, float, double, string, array.
  112. * @param mixed[optional] $defaultValue The value that should be returned if the key is not available.
  113. */
  114. public function getParameter($index, $type = 'string', $defaultValue = null)
  115. {
  116. // does the index exists and isn't this parameter empty
  117. if(isset($this->parameters[$index]) && $this->parameters[$index] != '')
  118. {
  119. // parameter exists
  120. if(isset($this->parameters[$index])) return SpoonFilter::getValue($this->parameters[$index], null, null, $type);
  121. }
  122. // fallback
  123. return $defaultValue;
  124. }
  125. /**
  126. * Return all the parameters
  127. *
  128. * @return array
  129. * @param bool[optional] $includeGET Should the GET-parameters be included?
  130. */
  131. public function getParameters($includeGET = true)
  132. {
  133. return ($includeGET) ? $this->parameters : array_diff($this->parameters, $_GET);
  134. }
  135. /**
  136. * Get the querystring
  137. *
  138. * @return string
  139. */
  140. public function getQueryString()
  141. {
  142. return $this->queryString;
  143. }
  144. /**
  145. * Process the querystring
  146. *
  147. * @return void
  148. */
  149. private function processQueryString()
  150. {
  151. // store the querystring local, so we don't alter it.
  152. $queryString = $this->getQueryString();
  153. // fix GET-parameters
  154. $getChunks = explode('?', $queryString);
  155. // are there GET-parameters
  156. if(isset($getChunks[1]))
  157. {
  158. // get key-value pairs
  159. $get = explode('&', $getChunks[1]);
  160. // remove from querystring
  161. $queryString = str_replace('?' . $getChunks[1], '', $this->getQueryString());
  162. // loop pairs
  163. foreach($get as $getItem)
  164. {
  165. // get key and value
  166. $getChunks = explode('=', $getItem, 2);
  167. // key available?
  168. if(isset($getChunks[0]))
  169. {
  170. // reset in $_GET
  171. $_GET[$getChunks[0]] = (isset($getChunks[1])) ? (string) $getChunks[1] : '';
  172. // add into parameters
  173. if(isset($getChunks[1])) $this->parameters[(string) $getChunks[0]] = (string) $getChunks[1];
  174. }
  175. }
  176. }
  177. // split into chunks
  178. $chunks = (array) explode('/', $queryString);
  179. // single language
  180. if(!SITE_MULTILANGUAGE)
  181. {
  182. // set language id
  183. $language = FrontendModel::getModuleSetting('core', 'default_language', SITE_DEFAULT_LANGUAGE);
  184. }
  185. // multiple languages
  186. else
  187. {
  188. // default value
  189. $mustRedirect = false;
  190. // get possible languages
  191. $possibleLanguages = (array) FrontendLanguage::getActiveLanguages();
  192. $redirectLanguages = (array) FrontendLanguage::getRedirectLanguages();
  193. // the language is present in the URL
  194. if(isset($chunks[0]) && in_array($chunks[0], $possibleLanguages))
  195. {
  196. // define language
  197. $language = (string) $chunks[0];
  198. // try to set a cookie with the language
  199. try
  200. {
  201. // set cookie
  202. SpoonCookie::set('frontend_language', $language, (7 * 24 * 60 * 60), '/', '.' . $this->getDomain());
  203. }
  204. // fetch failed cookie
  205. catch(SpoonCookieException $e)
  206. {
  207. // settings cookies isn't allowed, because this isn't a real problem we ignore the exception
  208. }
  209. // set sessions
  210. SpoonSession::set('frontend_language', $language);
  211. // remove the language part
  212. array_shift($chunks);
  213. }
  214. // language set in the cookie
  215. elseif(SpoonCookie::exists('frontend_language') && in_array(SpoonCookie::get('frontend_language'), $redirectLanguages))
  216. {
  217. // set languageId
  218. $language = (string) SpoonCookie::get('frontend_language');
  219. // redirect is needed
  220. $mustRedirect = true;
  221. }
  222. // default browser language
  223. else
  224. {
  225. // set languageId & abbreviation
  226. $language = FrontendLanguage::getBrowserLanguage();
  227. // try to set a cookie with the language
  228. try
  229. {
  230. // set cookie
  231. SpoonCookie::set('frontend_language', $language, (7 * 24 * 60 * 60), '/', '.' . $this->getDomain());
  232. }
  233. // fetch failed cookie
  234. catch(SpoonCookieException $e)
  235. {
  236. // settings cookies isn't allowed, because this isn't a real problem we ignore the exception
  237. }
  238. // redirect is needed
  239. $mustRedirect = true;
  240. }
  241. // redirect is required
  242. if($mustRedirect)
  243. {
  244. // build URL
  245. $URL = rtrim('/' . $language . '/' . $this->getQueryString(), '/');
  246. // set header & redirect
  247. SpoonHTTP::redirect($URL, 301);
  248. }
  249. }
  250. // define the language
  251. define('FRONTEND_LANGUAGE', $language);
  252. // sets the localefile
  253. FrontendLanguage::setLocale($language);
  254. // list of pageIds & their full URL
  255. $keys = FrontendNavigation::getKeys();
  256. // full URL
  257. $URL = implode('/', $chunks);
  258. $startURL = $URL;
  259. // loop until we find the URL in the list of pages
  260. while(!in_array($URL, $keys))
  261. {
  262. // remove the last chunk
  263. array_pop($chunks);
  264. // redefine the URL
  265. $URL = implode('/', $chunks);
  266. }
  267. // remove language from querystring
  268. if(SITE_MULTILANGUAGE) $queryString = trim(substr($queryString, strlen($language)), '/');
  269. // if it's the homepage AND parameters were given (not allowed!)
  270. if($URL == '' && $queryString != '')
  271. {
  272. // get 404 URL
  273. $URL = FrontendNavigation::getURL(404);
  274. // remove language
  275. if(SITE_MULTILANGUAGE) $URL = str_replace('/' . $language, '', $URL);
  276. }
  277. // set pages
  278. $URL = trim($URL, '/');
  279. // currently not in the homepage
  280. if($URL != '')
  281. {
  282. // explode in pages
  283. $pages = explode('/', $URL);
  284. // reset pages
  285. $this->setPages($pages);
  286. // reset parameters
  287. $this->setParameters(array());
  288. }
  289. // set parameters
  290. $parameters = trim(substr($startURL, strlen($URL)), '/');
  291. // has at least one parameter
  292. if($parameters != '')
  293. {
  294. // parameters will be separated by /
  295. $parameters = explode('/', $parameters);
  296. // set parameters
  297. $this->setParameters($parameters);
  298. }
  299. // pageId, parentId & depth
  300. $pageId = FrontendNavigation::getPageId(implode('/', $this->getPages()));
  301. $pageInfo = FrontendNavigation::getPageInfo($pageId);
  302. // invalid page, or parameters but no extra
  303. if($pageInfo === false || (!empty($parameters) && !$pageInfo['has_extra']))
  304. {
  305. // get 404 URL
  306. $URL = FrontendNavigation::getURL(404);
  307. // remove language
  308. if(SITE_MULTILANGUAGE) $URL = trim(str_replace('/' . $language, '', $URL), '/');
  309. // currently not in the homepage
  310. if($URL != '')
  311. {
  312. // explode in pages
  313. $pages = explode('/', $URL);
  314. // reset pages
  315. $this->setPages($pages);
  316. // reset parameters
  317. $this->setParameters(array());
  318. }
  319. }
  320. // is this an internal redirect?
  321. if(isset($pageInfo['redirect_page_id']) && $pageInfo['redirect_page_id'] != '')
  322. {
  323. // get url for item
  324. $newPageURL = FrontendNavigation::getURL((int) $pageInfo['redirect_page_id']);
  325. $errorURL = FrontendNavigation::getURL(404);
  326. // not an error?
  327. if($newPageURL != $errorURL)
  328. {
  329. // redirect
  330. SpoonHTTP::redirect($newPageURL, $pageInfo['redirect_code']);
  331. }
  332. }
  333. // is this an external redirect?
  334. if(isset($pageInfo['redirect_url']) && $pageInfo['redirect_url'] != '')
  335. {
  336. // redirect
  337. SpoonHTTP::redirect($pageInfo['redirect_url'], $pageInfo['redirect_code']);
  338. }
  339. }
  340. /**
  341. * Set the host
  342. *
  343. * @return void
  344. * @param string $host The value of the host.
  345. */
  346. private function setHost($host)
  347. {
  348. $this->host = (string) $host;
  349. }
  350. /**
  351. * Set the pages
  352. *
  353. * @return void
  354. * @param array[optional] $pages An array of all the pages to set.
  355. */
  356. private function setPages(array $pages = array())
  357. {
  358. $this->pages = $pages;
  359. }
  360. /**
  361. * Set the parameters
  362. *
  363. * @return void
  364. * @param array[optional] $parameters An array of all the parameters to set.
  365. */
  366. private function setParameters(array $parameters = array())
  367. {
  368. foreach($parameters as $key => $value) $this->parameters[$key] = $value;
  369. }
  370. /**
  371. * Set the querystring
  372. *
  373. * @return void
  374. * @param string $queryString The full querystring.
  375. */
  376. private function setQueryString($queryString)
  377. {
  378. $this->queryString = trim((string) $queryString, '/');
  379. }
  380. }
  381. ?>