PageRenderTime 62ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 1ms

/classes/fURL.php

https://bitbucket.org/wbond/flourish/
PHP | 286 lines | 123 code | 40 blank | 123 comment | 30 complexity | 673eabf8689bad5a12f7916a399e11e9 MD5 | raw file
  1. <?php
  2. /**
  3. * Provides functionality to retrieve and manipulate URL information
  4. *
  5. * This class uses `$_SERVER['REQUEST_URI']` for all operations, meaning that
  6. * the original URL entered by the user will be used, or that any rewrites
  7. * will **not** be reflected by this class.
  8. *
  9. * @copyright Copyright (c) 2007-2011 Will Bond
  10. * @author Will Bond [wb] <will@flourishlib.com>
  11. * @license http://flourishlib.com/license
  12. *
  13. * @package Flourish
  14. * @link http://flourishlib.com/fURL
  15. *
  16. * @version 1.0.0b10
  17. * @changes 1.0.0b10 Fixed some method signatures [wb, 2011-08-24]
  18. * @changes 1.0.0b9 Fixed ::redirect() to handle no parameters properly [wb, 2011-06-13]
  19. * @changes 1.0.0b8 Added the `$delimiter` parameter to ::makeFriendly() [wb, 2011-06-03]
  20. * @changes 1.0.0b7 Fixed ::redirect() to be able to handle unqualified and relative paths [wb, 2011-03-02]
  21. * @changes 1.0.0b6 Added the `$max_length` parameter to ::makeFriendly() [wb, 2010-09-19]
  22. * @changes 1.0.0b5 Updated ::redirect() to not require a URL, using the current URL as the default [wb, 2009-07-29]
  23. * @changes 1.0.0b4 ::getDomain() now includes the port number if non-standard [wb, 2009-05-02]
  24. * @changes 1.0.0b3 ::makeFriendly() now changes _-_ to - and multiple _ to a single _ [wb, 2009-03-24]
  25. * @changes 1.0.0b2 Fixed ::makeFriendly() so that _ doesn't appear at the beginning of URLs [wb, 2009-03-22]
  26. * @changes 1.0.0b The initial implementation [wb, 2007-06-14]
  27. */
  28. class fURL
  29. {
  30. // The following constants allow for nice looking callbacks to static methods
  31. const get = 'fURL::get';
  32. const getDomain = 'fURL::getDomain';
  33. const getQueryString = 'fURL::getQueryString';
  34. const getWithQueryString = 'fURL::getWithQueryString';
  35. const makeFriendly = 'fURL::makeFriendly';
  36. const redirect = 'fURL::redirect';
  37. const removeFromQueryString = 'fURL::removeFromQueryString';
  38. const replaceInQueryString = 'fURL::replaceInQueryString';
  39. /**
  40. * Returns the requested URL, does no include the domain name or query string
  41. *
  42. * This will return the original URL requested by the user - ignores all
  43. * rewrites.
  44. *
  45. * @return string The requested URL without the query string
  46. */
  47. static public function get()
  48. {
  49. return preg_replace('#\?.*$#D', '', $_SERVER['REQUEST_URI']);
  50. }
  51. /**
  52. * Returns the current domain name, with protcol prefix. Port will be included if not 80 for HTTP or 443 for HTTPS.
  53. *
  54. * @return string The current domain name, prefixed by `http://` or `https://`
  55. */
  56. static public function getDomain()
  57. {
  58. $port = (isset($_SERVER['SERVER_PORT'])) ? $_SERVER['SERVER_PORT'] : NULL;
  59. if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
  60. return 'https://' . $_SERVER['SERVER_NAME'] . ($port && $port != 443 ? ':' . $port : '');
  61. } else {
  62. return 'http://' . $_SERVER['SERVER_NAME'] . ($port && $port != 80 ? ':' . $port : '');
  63. }
  64. }
  65. /**
  66. * Returns the current query string, does not include parameters added by rewrites
  67. *
  68. * @return string The query string
  69. */
  70. static public function getQueryString()
  71. {
  72. return preg_replace('#^[^?]*\??#', '', $_SERVER['REQUEST_URI']);
  73. }
  74. /**
  75. * Returns the current URL including query string, but without domain name - does not include query string parameters from rewrites
  76. *
  77. * @return string The URL with query string
  78. */
  79. static public function getWithQueryString()
  80. {
  81. return $_SERVER['REQUEST_URI'];
  82. }
  83. /**
  84. * Changes a string into a URL-friendly string
  85. *
  86. * @param string $string The string to convert
  87. * @param integer $max_length The maximum length of the friendly URL
  88. * @param string $delimiter The delimiter to use between words, defaults to `_`
  89. * @param string |$string
  90. * @param string |$delimiter
  91. * @return string The URL-friendly version of the string
  92. */
  93. static public function makeFriendly($string, $max_length=NULL, $delimiter=NULL)
  94. {
  95. // This allows omitting the max length, but including a delimiter
  96. if ($max_length && !is_numeric($max_length)) {
  97. $delimiter = $max_length;
  98. $max_length = NULL;
  99. }
  100. $string = fHTML::decode(fUTF8::ascii($string));
  101. $string = strtolower(trim($string));
  102. $string = str_replace("'", '', $string);
  103. if (!strlen($delimiter)) {
  104. $delimiter = '_';
  105. }
  106. $delimiter_replacement = strtr($delimiter, array('\\' => '\\\\', '$' => '\\$'));
  107. $delimiter_regex = preg_quote($delimiter, '#');
  108. $string = preg_replace('#[^a-z0-9\-_]+#', $delimiter_replacement, $string);
  109. $string = preg_replace('#' . $delimiter_regex . '{2,}#', $delimiter_replacement, $string);
  110. $string = preg_replace('#_-_#', '-', $string);
  111. $string = preg_replace('#(^' . $delimiter_regex . '+|' . $delimiter_regex . '+$)#D', '', $string);
  112. $length = strlen($string);
  113. if ($max_length && $length > $max_length) {
  114. $last_pos = strrpos($string, $delimiter, ($length - $max_length - 1) * -1);
  115. if ($last_pos < ceil($max_length / 2)) {
  116. $last_pos = $max_length;
  117. }
  118. $string = substr($string, 0, $last_pos);
  119. }
  120. return $string;
  121. }
  122. /**
  123. * Redirects to the URL specified, without requiring a full-qualified URL
  124. *
  125. * - If the URL starts with `/`, it is treated as an absolute path on the current site
  126. * - If the URL starts with `http://` or `https://`, it is treated as a fully-qualified URL
  127. * - If the URL starts with anything else, including a `?`, it is appended to the current URL
  128. * - If the URL is ommitted, it is treated as the current URL
  129. *
  130. * @param string $url The url to redirect to
  131. * @return void
  132. */
  133. static public function redirect($url=NULL)
  134. {
  135. if (strpos($url, '/') === 0) {
  136. $url = self::getDomain() . $url;
  137. } elseif (!preg_match('#^https?://#i', $url)) {
  138. $prefix = self::getDomain() . self::get();
  139. if (strlen($url)) {
  140. // All URLs that have more than the query string need to
  141. // be appended to the current directory name
  142. if ($url[0] != '?') {
  143. $prefix = preg_replace('#(?<=/)[^/]+$#D', '', $prefix);
  144. }
  145. // Clean up ./ relative URLS
  146. if (substr($url, 0, 2) == './') {
  147. $url = substr($url, 2);
  148. }
  149. // Resolve ../ relative paths as far as possible
  150. while (substr($url, 0, 3) == '../') {
  151. if ($prefix == self::getDomain() . '/') { break; }
  152. $prefix = preg_replace('#(?<=/)[^/]+/?$#D', '', $prefix);
  153. $url = substr($url, 3);
  154. }
  155. }
  156. $url = $prefix . $url;
  157. }
  158. // Strip the ? if there are no query string parameters
  159. if (substr($url, -1) == '?') {
  160. $url = substr($url, 0, -1);
  161. }
  162. header('Location: ' . $url);
  163. exit($url);
  164. }
  165. /**
  166. * Removes one or more parameters from the query string
  167. *
  168. * This method uses the query string from the original URL and will not
  169. * contain any parameters that are from rewrites.
  170. *
  171. * @param string $parameter A parameter to remove from the query string
  172. * @param string ...
  173. * @return string The query string with the parameter(s) specified removed, first character is `?`
  174. */
  175. static public function removeFromQueryString($parameter)
  176. {
  177. $parameters = func_get_args();
  178. parse_str(self::getQueryString(), $qs_array);
  179. if (get_magic_quotes_gpc()) {
  180. $qs_array = array_map('stripslashes', $qs_array);
  181. }
  182. foreach ($parameters as $parameter) {
  183. unset($qs_array[$parameter]);
  184. }
  185. return '?' . http_build_query($qs_array, '', '&');
  186. }
  187. /**
  188. * Replaces a value in the query string
  189. *
  190. * This method uses the query string from the original URL and will not
  191. * contain any parameters that are from rewrites.
  192. *
  193. * @param string|array $parameter The query string parameter
  194. * @param string|array $value The value to set the parameter to
  195. * @return string The full query string with the parameter replaced, first char is `?`
  196. */
  197. static public function replaceInQueryString($parameter, $value)
  198. {
  199. parse_str(self::getQueryString(), $qs_array);
  200. if (get_magic_quotes_gpc()) {
  201. $qs_array = array_map('stripslashes', $qs_array);
  202. }
  203. settype($parameter, 'array');
  204. settype($value, 'array');
  205. if (sizeof($parameter) != sizeof($value)) {
  206. throw new fProgrammerException(
  207. "There are a different number of parameters and values.\nParameters:\n%1\$s\nValues\n%2\$s",
  208. $parameter,
  209. $value
  210. );
  211. }
  212. for ($i=0; $i<sizeof($parameter); $i++) {
  213. $qs_array[$parameter[$i]] = $value[$i];
  214. }
  215. return '?' . http_build_query($qs_array, '', '&');
  216. }
  217. /**
  218. * Forces use as a static class
  219. *
  220. * @return fURL
  221. */
  222. private function __construct() { }
  223. }
  224. /**
  225. * Copyright (c) 2007-2011 Will Bond <will@flourishlib.com>
  226. *
  227. * Permission is hereby granted, free of charge, to any person obtaining a copy
  228. * of this software and associated documentation files (the "Software"), to deal
  229. * in the Software without restriction, including without limitation the rights
  230. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  231. * copies of the Software, and to permit persons to whom the Software is
  232. * furnished to do so, subject to the following conditions:
  233. *
  234. * The above copyright notice and this permission notice shall be included in
  235. * all copies or substantial portions of the Software.
  236. *
  237. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  238. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  239. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  240. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  241. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  242. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  243. * THE SOFTWARE.
  244. */