PageRenderTime 26ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/php-horde-Horde-Url-1.0.2/Horde_Url-1.0.2/lib/Horde/Url.php

#
PHP | 362 lines | 178 code | 33 blank | 151 comment | 27 complexity | 940976aa0f9b3f67a1cc7680ccbe0a6d MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /**
  3. * This file contains the Horde_Url class for manipulating URLs.
  4. *
  5. * Copyright 2009-2012 Horde LLC (http://www.horde.org/)
  6. *
  7. * See the enclosed file COPYING for license information (LGPL). If you
  8. * did not receive this file, see http://www.horde.org/licenses/lgpl21.
  9. *
  10. * @author Jan Schneider <jan@horde.org>
  11. * @author Michael Slusarz <slusarz@horde.org>
  12. * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
  13. * @category Horde
  14. * @package Url
  15. */
  16. /**
  17. * The Horde_Url class represents a single URL and provides methods for
  18. * manipulating URLs.
  19. *
  20. * @author Jan Schneider <jan@horde.org>
  21. * @author Michael Slusarz <slusarz@horde.org>
  22. * @category Horde
  23. * @package Url
  24. */
  25. class Horde_Url
  26. {
  27. /**
  28. * The basic URL, without query parameters.
  29. *
  30. * @var string
  31. */
  32. public $url;
  33. /**
  34. * Whether to output the URL in the raw URL format or HTML-encoded.
  35. *
  36. * @var boolean
  37. */
  38. public $raw;
  39. /**
  40. * The query parameters.
  41. *
  42. * The keys are paramter names, the values parameter values. Array values
  43. * will be added to the URL using name[]=value notation.
  44. *
  45. * @var array
  46. */
  47. public $parameters = array();
  48. /**
  49. * Any PATH_INFO to be added to the URL.
  50. *
  51. * @var string
  52. */
  53. public $pathInfo;
  54. /**
  55. * The anchor string.
  56. *
  57. * @var string
  58. */
  59. public $anchor = '';
  60. /**
  61. * A callback function to use when converting to a string.
  62. *
  63. * @var callback
  64. */
  65. public $toStringCallback;
  66. /**
  67. * Constructor.
  68. *
  69. * @param string $url The basic URL, with or without query parameters.
  70. * @param boolean $raw Whether to output the URL in the raw URL format or
  71. * HTML-encoded.
  72. */
  73. public function __construct($url, $raw = null)
  74. {
  75. if ($url instanceof Horde_Url) {
  76. $this->anchor = $url->anchor;
  77. $this->parameters = $url->parameters;
  78. $this->pathInfo = $url->pathInfo;
  79. $this->raw = is_null($raw) ? $url->raw : $raw;
  80. $this->url = $url->url;
  81. return;
  82. }
  83. if (($pos = strrpos($url, '#')) !== false) {
  84. $this->anchor = urldecode(substr($url, $pos + 1));
  85. $url = substr($url, 0, $pos);
  86. }
  87. if (($pos = strrpos($url, '?')) !== false) {
  88. $query = substr($url, $pos + 1);
  89. $url = substr($url, 0, $pos);
  90. /* Check if the argument separator has been already
  91. * htmlentities-ized in the URL. */
  92. if (preg_match('/&amp;/', $query)) {
  93. $query = html_entity_decode($query);
  94. if (is_null($raw)) {
  95. $raw = false;
  96. }
  97. } elseif (preg_match('/&/', $query)) {
  98. if (is_null($raw)) {
  99. $raw = true;
  100. }
  101. }
  102. $pairs = explode('&', $query);
  103. foreach ($pairs as $pair) {
  104. $result = explode('=', urldecode($pair), 2);
  105. $this->add($result[0], isset($result[1]) ? $result[1] : null);
  106. }
  107. }
  108. $this->url = $url;
  109. $this->raw = $raw;
  110. }
  111. /**
  112. * Returns a clone of this object. Useful for chaining.
  113. *
  114. * @return Horde_Url A clone of this object.
  115. */
  116. public function copy()
  117. {
  118. $url = clone $this;
  119. return $url;
  120. }
  121. /**
  122. * Adds one or more query parameters.
  123. *
  124. * @param mixed $parameters Either the name value or an array of
  125. * name/value pairs.
  126. * @param string $value If specified, the value part ($parameters is
  127. * then assumed to just be the parameter name).
  128. *
  129. * @return Horde_Url This (modified) object, to allow chaining.
  130. */
  131. public function add($parameters, $value = null)
  132. {
  133. if (!is_array($parameters)) {
  134. $parameters = array($parameters => $value);
  135. }
  136. foreach ($parameters as $parameter => $value) {
  137. if (substr($parameter, -2) == '[]') {
  138. $parameter = substr($parameter, 0, -2);
  139. if (!isset($this->parameters[$parameter])) {
  140. $this->parameters[$parameter] = array();
  141. }
  142. $this->parameters[$parameter][] = $value;
  143. } else {
  144. $this->parameters[$parameter] = $value;
  145. }
  146. }
  147. return $this;
  148. }
  149. /**
  150. * Removes one ore more parameters.
  151. *
  152. * @param mixed $remove Either a single parameter to remove or an array
  153. * of parameters to remove.
  154. *
  155. * @return Horde_Url This (modified) object, to allow chaining.
  156. */
  157. public function remove($parameters)
  158. {
  159. if (!is_array($parameters)) {
  160. $parameters = array($parameters);
  161. }
  162. foreach ($parameters as $parameter) {
  163. unset($this->parameters[$parameter]);
  164. }
  165. return $this;
  166. }
  167. /**
  168. * Sets the URL anchor.
  169. *
  170. * @param string $anchor An anchor to add.
  171. *
  172. * @return Horde_Url This (modified) object, to allow chaining.
  173. */
  174. public function setAnchor($anchor)
  175. {
  176. $this->anchor = $anchor;
  177. return $this;
  178. }
  179. /**
  180. * Sets the $raw value. This call can be chained.
  181. *
  182. * @param boolean $raw Whether to output the URL in the raw URL format or
  183. * HTML-encoded.
  184. *
  185. * @return Horde_Url This object, to allow chaining.
  186. */
  187. public function setRaw($raw)
  188. {
  189. $this->raw = $raw;
  190. return $this;
  191. }
  192. /**
  193. * Creates the full URL string.
  194. *
  195. * @param boolean $raw Whether to output the URL in the raw URL format
  196. * or HTML-encoded.
  197. * @param boolean $full Output the full URL?
  198. *
  199. * @return string The string representation of this object.
  200. */
  201. public function toString($raw = false, $full = true)
  202. {
  203. if ($this->toStringCallback) {
  204. $callback = $this->toStringCallback;
  205. $this->toStringCallback = null;
  206. $ret = call_user_func($callback, $this);
  207. $this->toStringCallback = $callback;
  208. return $ret;
  209. }
  210. $url_params = array();
  211. foreach ($this->parameters as $parameter => $value) {
  212. if (is_array($value)) {
  213. foreach ($value as $val) {
  214. $url_params[] = rawurlencode($parameter) . '[]=' . rawurlencode($val);
  215. }
  216. } else {
  217. if (strlen($value)) {
  218. $url_params[] = rawurlencode($parameter) . '=' . rawurlencode($value);
  219. } else {
  220. $url_params[] = rawurlencode($parameter);
  221. }
  222. }
  223. }
  224. $url = $full
  225. ? $this->url
  226. : parse_url($this->url, PHP_URL_PATH);
  227. if (strlen($this->pathInfo)) {
  228. $url = rtrim($url, '/');
  229. $url .= '/' . $this->pathInfo;
  230. }
  231. if (count($url_params)) {
  232. $url .= '?' . implode($raw ? '&' : '&amp;', $url_params);
  233. }
  234. if ($this->anchor) {
  235. $url .= '#' . ($raw ? $this->anchor : rawurlencode($this->anchor));
  236. }
  237. return strval($url);
  238. }
  239. /**
  240. * Creates the full URL string.
  241. *
  242. * @return string The string representation of this object.
  243. */
  244. public function __toString()
  245. {
  246. return $this->toString($this->raw);
  247. }
  248. /**
  249. * Generates a HTML link tag out of this URL.
  250. *
  251. * @param array $attributes A hash with any additional attributes to be
  252. * added to the link. If the attribute name is
  253. * suffixed with ".raw", the attribute value
  254. * won't be HTML-encoded.
  255. *
  256. * @return string An <a> tag representing this URL.
  257. */
  258. public function link(array $attributes = array())
  259. {
  260. $url = (string)$this->setRaw(false);
  261. $link = '<a';
  262. if (!empty($url)) {
  263. $link .= " href=\"$url\"";
  264. }
  265. foreach ($attributes as $name => $value) {
  266. if (!strlen($value)) {
  267. continue;
  268. }
  269. if (substr($name, -4) == '.raw') {
  270. $link .= ' ' . htmlspecialchars(substr($name, 0, -4))
  271. . '="' . $value . '"';
  272. } else {
  273. $link .= ' ' . htmlspecialchars($name)
  274. . '="' . htmlspecialchars($value) . '"';
  275. }
  276. }
  277. return $link . '>';
  278. }
  279. /**
  280. * Add a unique parameter to the URL to aid in cache-busting.
  281. *
  282. * @return Horde_Url This (modified) object, to allow chaining.
  283. */
  284. public function unique()
  285. {
  286. return $this->add('u', uniqid(mt_rand()));
  287. }
  288. /**
  289. * Sends a redirect request to the browser to the URL in this object.
  290. *
  291. * @throws Horde_Url_Exception
  292. */
  293. public function redirect()
  294. {
  295. $url = strval($this->setRaw(true));
  296. if (!strlen($url)) {
  297. throw new Horde_Url_Exception('Redirect failed: URL is empty.');
  298. }
  299. header('Location: ' . $url);
  300. exit;
  301. }
  302. /**
  303. * URL-safe base64 encoding, with trimmed '='.
  304. *
  305. * @param string $string String to encode.
  306. *
  307. * @return string URL-safe, base64 encoded data.
  308. */
  309. static public function uriB64Encode($string)
  310. {
  311. return str_replace(array('+', '/', '='), array('-', '_', ''), base64_encode($string));
  312. }
  313. /**
  314. * Decode URL-safe base64 data, dealing with missing '='.
  315. *
  316. * @param string $string Encoded data.
  317. *
  318. * @return string Decoded data.
  319. */
  320. static public function uriB64Decode($string)
  321. {
  322. $data = str_replace(array('-', '_'), array('+', '/'), $string);
  323. $mod4 = strlen($data) % 4;
  324. if ($mod4) {
  325. $data .= substr('====', $mod4);
  326. }
  327. return base64_decode($data);
  328. }
  329. }