From: Jan Schneider Date: Thu, 3 Dec 2009 14:06:46 +0000 (+0100) Subject: Add basic Horde_Url class. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=7f6ddcffe1c3d9031d499c0dee40f8b37628e5c5;p=horde.git Add basic Horde_Url class. --- diff --git a/framework/Url/lib/Horde/Url.php b/framework/Url/lib/Horde/Url.php new file mode 100644 index 000000000..c2716c506 --- /dev/null +++ b/framework/Url/lib/Horde/Url.php @@ -0,0 +1,161 @@ + + * @author Michael Slusarz + * @category Horde + * @package Horde_Url + */ + +/** + * The Horde_Url class represents a single URL and provides methods for + * manipulating URLs. + * + * @author Jan Schneider + * @author Michael Slusarz + * @category Horde + * @package Horde_Url + */ +class Horde_Url +{ + /** + * The basic URL, without query parameters. + * + * @var string + */ + public $url; + + /** + * The query parameters. + * + * The keys are paramter names, the values parameter values. Array values + * will be added to the URL using name[]=value notation. + * + * @var array + */ + public $parameters; + + /** + * Whether to output the URL in the raw URL format or HTML-encoded. + * + * @var boolean + */ + public $raw; + + /** + * Constructor. + * + * @param string $url The basic URL, with or without query parameters. + * @param boolean $raw Whether to output the URL in the raw URL format or + * HTML-encoded. + */ + public function __construct($url, $raw = false) + { + if (strpos($url, '?') !== false) { + list($url, $query) = explode('?', $url); + + /* Check if the argument separator has been already + * htmlentities-ized in the URL. */ + if (preg_match('/=.*?&.*?=/', $query)) { + $query = html_entity_decode($query); + $raw = false; + } elseif (preg_match('/=.*?&.*?=/', $query)) { + $raw = true; + } + $pairs = explode('&', $query); + foreach ($pairs as $pair) { + @list($parameter, $value) = explode('=', urldecode($pair), 2); + $this->add($parameter, $value); + } + } + + $this->url = $url; + $this->raw = $raw; + } + + /** + * Adds one or more query parameters. + * + * @param mixed $parameters Either the name value or an array of + * name/value pairs. + * @param string $value If specified, the value part ($parameters is + * then assumed to just be the parameter name). + * + * @return Horde_Url This (modified) object, to allow chaining. + */ + public function add($parameters, $value = null) + { + if (!is_array($parameters)) { + $parameters = array($parameters => $value); + } + + foreach ($parameters as $parameter => $value) { + if (substr($parameter, -2) == '[]') { + $parameter = substr($parameter, 0, -2); + if (!isset($this->parameters[$parameter])) { + $this->parameters[$parameter] = array(); + } + $this->parameters[$parameter][] = $value; + } else { + $this->parameters[$parameter] = $value; + } + } + + return $this; + } + + /** + * Removes one ore more parameters. + * + * @param mixed $remove Either a single parameter to remove or an array + * of parameters to remove. + * + * @return Horde_Url This (modified) object, to allow chaining. + */ + public function remove($parameters) + { + if (!is_array($parameters)) { + $parameters = array($parameters); + } + + foreach ($parameters as $parameter) { + unset($this->parameters[$parameter]); + } + + return $this; + } + + /** + * Creates the full URL string. + * + * @return string The string representation of this object. + */ + public function __toString() + { + $url_params = array(); + foreach ($this->parameters as $parameter => $value) { + if (is_array($value)) { + foreach ($value as $val) { + $url_params[] = rawurlencode($parameter) . '[]=' . rawurlencode($val); + } + } else { + if (strlen($value)) { + $url_params[] = rawurlencode($parameter) . '=' . rawurlencode($value); + } else { + $url_params[] = rawurlencode($parameter); + } + } + } + + return count($url_params) + ? $this->url . '?' . implode($this->raw ? '&' : '&', $url_params) + : $this->url; + } + +} \ No newline at end of file diff --git a/framework/Url/package.xml b/framework/Url/package.xml new file mode 100644 index 000000000..37705e6df --- /dev/null +++ b/framework/Url/package.xml @@ -0,0 +1,59 @@ + + + Url + pear.horde.org + Horde Url class + This class represents a single URL and provides methods for manipulating URLs. + + Jan Schneider + jan + jan@horde.org + yes + + + Michael Slusarz + slusarz + slusarz@horde.org + yes + + 2009-12-03 + + 0.1.0 + 0.1.0 + + + beta + beta + + LGPL + * Initial package. + + + + + + + + + + + + + + 5.2.0 + + + 1.5.4 + + + + + + + + + + diff --git a/framework/Url/test/Horde/Url/AddTest.php b/framework/Url/test/Horde/Url/AddTest.php new file mode 100644 index 000000000..33416e681 --- /dev/null +++ b/framework/Url/test/Horde/Url/AddTest.php @@ -0,0 +1,74 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @category Horde + * @package Horde_Url + * @subpackage UnitTests + */ + +class Horde_Url_AddTest extends PHPUnit_Framework_TestCase +{ + public function testAddSimple() + { + $url = new Horde_Url('test'); + $url->add('foo', 1); + $this->assertEquals('test?foo=1', (string)$url); + $url->add('bar', 2); + $this->assertEquals('test?foo=1&bar=2', (string)$url); + $url->add('baz', 3); + $this->assertEquals('test?foo=1&bar=2&baz=3', (string)$url); + } + + public function testAddArray() + { + $url = new Horde_Url('test'); + $url->add(array('foo' => 1, 'bar' => 2)); + $this->assertEquals('test?foo=1&bar=2', (string)$url); + + $url = new Horde_Url('test?foo=1'); + $url->add(array('bar' => 2, 'baz' => 3)); + $this->assertEquals('test?foo=1&bar=2&baz=3', (string)$url); + } + + public function testAddToExistingUrl() + { + $url = new Horde_Url('test?foo=1&bar=2'); + $url->add(array('baz' => 3)); + $this->assertEquals('test?foo=1&bar=2&baz=3', (string)$url); + + $url = new Horde_Url('test?foo=1&bar=2'); + $url->add(array('foo' => 1, 'bar' => 3)); + $this->assertEquals('test?foo=1&bar=3', (string)$url); + + $url = new Horde_Url('test?foo=1&bar=2'); + $url->add('baz', 3); + $this->assertEquals('test?foo=1&bar=2&baz=3', (string)$url); + } + + public function testAddRaw() + { + $url = new Horde_Url('test'); + $url->add('foo', 'bar&baz'); + $this->assertEquals('test?foo=bar%26baz', (string)$url); + $url->add('x', 'y'); + $this->assertEquals('test?foo=bar%26baz&x=y', (string)$url); + $url->raw = true; + $url->add('x', 'y'); + $this->assertEquals('test?foo=bar%26baz&x=y', (string)$url); + + $url = new Horde_Url('test'); + $url->add('x', 'y') + ->add('foo', 'bar&baz'); + $this->assertEquals('test?x=y&foo=bar%26baz', (string)$url); + } + + public function testAddChaining() + { + $url = new Horde_Url('test'); + $url->add('foo', 1) + ->add('bar', 2) + ->add('baz', 3); + $this->assertEquals('test?foo=1&bar=2&baz=3', (string)$url); + } +} diff --git a/framework/Url/test/Horde/Url/AllTests.php b/framework/Url/test/Horde/Url/AllTests.php new file mode 100644 index 000000000..3a34b34b9 --- /dev/null +++ b/framework/Url/test/Horde/Url/AllTests.php @@ -0,0 +1,34 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @category Horde + * @package Horde_Url + * @subpackage UnitTests + */ + +/** + * Define the main method + */ +if (!defined('PHPUnit_MAIN_METHOD')) { + define('PHPUnit_MAIN_METHOD', 'Horde_Url_AllTests::main'); +} + +/** + * Prepare the test setup. + */ +require_once 'Horde/Test/AllTests.php'; + +/** + * @package Horde_Url + * @subpackage UnitTests + */ +class Horde_Url_AllTests extends Horde_Test_AllTests +{ +} + +if (PHPUnit_MAIN_METHOD == 'Horde_Url_AllTests::main') { + Horde_Url_AllTests::main('Horde_Url', __FILE__); +} diff --git a/framework/Url/test/Horde/Url/RemoveTest.php b/framework/Url/test/Horde/Url/RemoveTest.php new file mode 100644 index 000000000..9b06af7bf --- /dev/null +++ b/framework/Url/test/Horde/Url/RemoveTest.php @@ -0,0 +1,47 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @category Horde + * @package Horde_Url + * @subpackage UnitTests + */ + +class Horde_Url_RemoveTest extends PHPUnit_Framework_TestCase +{ + public function testRemoveRaw() + { + $url = new Horde_Url('test?foo=1&bar=2'); + $this->assertEquals('test?bar=2', (string)$url->remove('foo')); + + $url = new Horde_Url('test?foo=1&bar=2'); + $this->assertEquals('test?foo=1', (string)$url->remove('bar')); + + $url = new Horde_Url('test?foo=1&bar=2'); + $this->assertEquals('test', (string)$url->remove(array('foo', 'bar'))); + + $url = new Horde_Url('test?foo=1&bar=2&baz=3'); + $this->assertEquals('test?bar=2&baz=3', (string)$url->remove('foo')); + } + + public function testRemoveEncoded() + { + $url = new Horde_Url('test?foo=1&bar=2'); + $this->assertEquals('test?bar=2', (string)$url->remove('foo')); + + $url = new Horde_Url('test?foo=1&bar=2'); + $this->assertEquals('test?foo=1', (string)$url->remove('bar')); + + $url = new Horde_Url('test?foo=1&bar=2'); + $this->assertEquals('test', (string)$url->remove(array('foo', 'bar'))); + + $url = new Horde_Url('test?foo=1&bar=2&baz=3'); + $this->assertEquals('test?bar=2&baz=3', (string)$url->remove('foo')); + } + + public function testRemoveChaining() + { + $url = new Horde_Url('test?foo=1&bar=2'); + $this->assertEquals('test', (string)$url->remove('foo')->remove('bar')); + } +} diff --git a/framework/Util/lib/Horde/Util.php b/framework/Util/lib/Horde/Util.php index e07b9a3cc..e130fe46b 100644 --- a/framework/Util/lib/Horde/Util.php +++ b/framework/Util/lib/Horde/Util.php @@ -233,56 +233,13 @@ class Horde_Util return $url; } - $add = array(); - $arg = $encode ? '&' : '&'; - - if (strpos($url, '?') !== false) { - list($url, $query) = explode('?', $url); - - /* Check if the argument separator has been already - * htmlentities-ized in the URL. */ - if (preg_match('/=.*?&.*?=/', $query)) { - $query = html_entity_decode($query); - $arg = '&'; - } elseif (preg_match('/=.*?&.*?=/', $query)) { - $arg = '&'; - } - $pairs = explode('&', $query); - foreach ($pairs as $pair) { - $pair = explode('=', urldecode($pair), 2); - $pair_val = (count($pair) == 2) ? $pair[1] : ''; - if (substr($pair[0], -2) == '[]') { - $name = substr($pair[0], 0, -2); - if (!isset($add[$name])) { - $add[$name] = array(); - } - $add[$name][] = $pair_val; - } else { - $add[$pair[0]] = $pair_val; - } - } - } - - if (is_array($parameter)) { - $add = array_merge($add, $parameter); - } else { - $add[$parameter] = $value; - } - - $url_params = array(); - foreach ($add as $parameter => $value) { - if (is_array($value)) { - foreach ($value as $val) { - $url_params[] = rawurlencode($parameter) . '[]=' . rawurlencode($val); - } - } else { - $url_params[] = rawurlencode($parameter) . '=' . rawurlencode($value); - } + if ($url instanceof Horde_Url) { + $url->raw = !$encode; + return $url->add($parameter, $value); } - return count($url_params) - ? $url . '?' . implode($arg, $url_params) - : $url; + $horde_url = new Horde_Url($url, !$encode); + return $horde_url->add($parameter, $value); } /** @@ -296,61 +253,13 @@ class Horde_Util */ static public function removeParameter($url, $remove) { - if (!is_array($remove)) { - $remove = array($remove); - } - - /* Return immediately if there are no parameters to remove. */ - if (($pos = strpos($url, '?')) === false) { - return $url; - } - - $entities = false; - list($url, $query) = explode('?', $url, 2); - - /* Check if the argument separator has been already - * htmlentities-ized in the URL. */ - if (preg_match('/=.*?&.*?=/', $query)) { - $entities = true; - $query = html_entity_decode($query); - } - - /* Get the list of parameters. */ - $pairs = explode('&', $query); - $params = array(); - foreach ($pairs as $pair) { - $pair = explode('=', $pair, 2); - $params[$pair[0]] = count($pair) == 2 ? $pair[1] : ''; - } - - /* Remove the parameters. */ - foreach ($remove as $param) { - unset($params[$param]); - } - - if (!count($params)) { - return $url; - } - - /* Flatten arrays. - * FIXME: should handle more than one array level somehow. */ - $add = array(); - foreach ($params as $key => $val) { - if (is_array($val)) { - foreach ($val as $v) { - $add[] = $key . '[]=' . $v; - } - } else { - $add[] = $key . '=' . $val; - } - } + $horde_url = new Horde_Url($url); - $query = implode('&', $add); - if ($entities) { - $query = htmlentities($query); + if ($url instanceof Horde_Url) { + return $url->remove($parameter); } - return $url . '?' . $query; + return $horde_url->remove($remove); } /** diff --git a/framework/Util/test/Horde/Util/addParameter.phpt b/framework/Util/test/Horde/Util/addParameter.phpt index 3bc4fb905..b7690400c 100644 --- a/framework/Util/test/Horde/Util/addParameter.phpt +++ b/framework/Util/test/Horde/Util/addParameter.phpt @@ -3,6 +3,7 @@ Horde_Util::addParameter() tests --FILE--