Overview

Packages

  • Url

Classes

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