2014-06-17 12:00:49 +02:00
|
|
|
<?php
|
2016-02-08 15:41:00 +01:00
|
|
|
/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
|
2014-06-17 12:00:49 +02:00
|
|
|
|
|
|
|
namespace Icinga\Web;
|
|
|
|
|
2015-04-07 12:17:59 +02:00
|
|
|
use Icinga\Exception\MissingParameterException;
|
|
|
|
|
2014-06-17 12:00:49 +02:00
|
|
|
class UrlParams
|
|
|
|
{
|
|
|
|
protected $separator = '&';
|
|
|
|
|
|
|
|
protected $params = array();
|
|
|
|
|
|
|
|
protected $index = array();
|
|
|
|
|
|
|
|
public function isEmpty()
|
|
|
|
{
|
|
|
|
return empty($this->index);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setSeparator($separator)
|
|
|
|
{
|
|
|
|
$this->separator = $separator;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the given parameter
|
|
|
|
*
|
|
|
|
* Returns the last URL param if defined multiple times, $default if not
|
|
|
|
* given at all
|
|
|
|
*
|
|
|
|
* @param string $param The parameter you're interested in
|
|
|
|
* @param string $default An optional default value
|
|
|
|
*
|
|
|
|
* @return mixed
|
|
|
|
*/
|
|
|
|
public function get($param, $default = null)
|
|
|
|
{
|
|
|
|
if (! $this->has($param)) {
|
|
|
|
return $default;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rawurldecode($this->params[ end($this->index[$param]) ][ 1 ]);
|
|
|
|
}
|
|
|
|
|
2015-04-07 12:17:59 +02:00
|
|
|
/**
|
|
|
|
* Require a parameter
|
|
|
|
*
|
|
|
|
* @param string $name Name of the parameter
|
|
|
|
* @param bool $strict Whether the parameter's value must not be the empty string
|
|
|
|
*
|
|
|
|
* @return mixed
|
|
|
|
*
|
|
|
|
* @throws MissingParameterException If the parameter was not given
|
|
|
|
*/
|
2015-05-19 17:12:18 +02:00
|
|
|
public function getRequired($name, $strict = true)
|
2015-04-07 12:17:59 +02:00
|
|
|
{
|
|
|
|
if ($this->has($name)) {
|
|
|
|
$value = $this->get($name);
|
|
|
|
if (! $strict || strlen($value) > 0) {
|
|
|
|
return $value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$e = new MissingParameterException(t('Required parameter \'%s\' missing'), $name);
|
|
|
|
$e->setParameter($name);
|
|
|
|
throw $e;
|
|
|
|
}
|
|
|
|
|
2014-06-17 12:00:49 +02:00
|
|
|
/**
|
|
|
|
* Get all instances of the given parameter
|
|
|
|
*
|
|
|
|
* Returns an array containing all values defined for a given parameter,
|
|
|
|
* $default if none.
|
|
|
|
*
|
|
|
|
* @param string $param The parameter you're interested in
|
|
|
|
* @param string $default An optional default value
|
|
|
|
*
|
|
|
|
* @return mixed
|
|
|
|
*/
|
|
|
|
public function getValues($param, $default = array())
|
|
|
|
{
|
|
|
|
if (! $this->has($param)) {
|
|
|
|
return $default;
|
|
|
|
}
|
|
|
|
|
|
|
|
$ret = array();
|
|
|
|
foreach ($this->index[$param] as $key) {
|
|
|
|
$ret[] = rawurldecode($this->params[$key][1]);
|
|
|
|
}
|
|
|
|
return $ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether the given parameter exists
|
|
|
|
*
|
|
|
|
* Returns true if such a parameter has been defined, false otherwise.
|
|
|
|
*
|
|
|
|
* @param string $param The parameter you're interested in
|
|
|
|
*
|
|
|
|
* @return boolean
|
|
|
|
*/
|
|
|
|
public function has($param)
|
|
|
|
{
|
|
|
|
return array_key_exists($param, $this->index);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get and remove the given parameter
|
|
|
|
*
|
|
|
|
* Returns the last URL param if defined multiple times, $default if not
|
|
|
|
* given at all. The parameter will be removed from this object.
|
|
|
|
*
|
|
|
|
* @param string $param The parameter you're interested in
|
|
|
|
* @param string $default An optional default value
|
|
|
|
*
|
|
|
|
* @return mixed
|
|
|
|
*/
|
|
|
|
public function shift($param = null, $default = null)
|
|
|
|
{
|
|
|
|
if ($param === null) {
|
|
|
|
if (empty($this->params)) {
|
|
|
|
return $default;
|
|
|
|
}
|
|
|
|
$ret = array_shift($this->params);
|
|
|
|
$ret[0] = rawurldecode($ret[0]);
|
|
|
|
$ret[1] = rawurldecode($ret[1]);
|
|
|
|
} else {
|
|
|
|
if (! $this->has($param)) {
|
|
|
|
return $default;
|
|
|
|
}
|
|
|
|
$key = reset($this->index[$param]);
|
|
|
|
$ret = rawurldecode($this->params[$key][1]);
|
|
|
|
unset($this->params[$key]);
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->reIndexAll();
|
|
|
|
return $ret;
|
|
|
|
}
|
|
|
|
|
2015-05-19 17:21:53 +02:00
|
|
|
/**
|
|
|
|
* Require and remove a parameter
|
|
|
|
*
|
|
|
|
* @param string $name Name of the parameter
|
|
|
|
* @param bool $strict Whether the parameter's value must not be the empty string
|
|
|
|
*
|
|
|
|
* @return mixed
|
|
|
|
*
|
|
|
|
* @throws MissingParameterException If the parameter was not given
|
|
|
|
*/
|
|
|
|
public function shiftRequired($name, $strict = true)
|
|
|
|
{
|
|
|
|
if ($this->has($name)) {
|
|
|
|
$value = $this->get($name);
|
|
|
|
if (! $strict || strlen($value) > 0) {
|
|
|
|
$this->shift($name);
|
|
|
|
return $value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$e = new MissingParameterException(t('Required parameter \'%s\' missing'), $name);
|
|
|
|
$e->setParameter($name);
|
|
|
|
throw $e;
|
|
|
|
}
|
|
|
|
|
2014-08-19 09:45:58 +02:00
|
|
|
public function addEncoded($param, $value = true)
|
|
|
|
{
|
|
|
|
$this->params[] = array($param, $this->cleanupValue($value));
|
|
|
|
$this->indexLastOne();
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function urlEncode($value)
|
|
|
|
{
|
2015-11-03 17:16:00 +01:00
|
|
|
return rawurlencode($value instanceof Url ? $value->getAbsoluteUrl() : (string) $value);
|
2014-08-19 09:45:58 +02:00
|
|
|
}
|
|
|
|
|
2014-06-17 12:00:49 +02:00
|
|
|
/**
|
|
|
|
* Add the given parameter with the given value
|
|
|
|
*
|
|
|
|
* This will add the given parameter, regardless of whether it already
|
|
|
|
* exists.
|
|
|
|
*
|
|
|
|
* @param string $param The parameter you're interested in
|
|
|
|
* @param string $value The value to be stored
|
|
|
|
*
|
2015-04-07 14:23:26 +02:00
|
|
|
* @return $this
|
2014-06-17 12:00:49 +02:00
|
|
|
*/
|
2014-06-20 12:41:16 +02:00
|
|
|
public function add($param, $value = true)
|
2014-06-17 12:00:49 +02:00
|
|
|
{
|
2014-08-19 09:45:58 +02:00
|
|
|
return $this->addEncoded($this->urlEncode($param), $this->urlEncode($value));
|
2014-06-17 12:00:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a list of parameters
|
|
|
|
*
|
|
|
|
* This may be used with either a list of values for a single parameter or
|
|
|
|
* with a list of parameter / value pairs.
|
|
|
|
*
|
|
|
|
* @param string $param Parameter name or param/value list
|
|
|
|
* @param string $value The value to be stored
|
|
|
|
*
|
2015-04-07 14:23:26 +02:00
|
|
|
* @return $this
|
2014-06-17 12:00:49 +02:00
|
|
|
*/
|
|
|
|
public function addValues($param, $values = null)
|
|
|
|
{
|
|
|
|
if ($values === null && is_array($param)) {
|
|
|
|
foreach ($param as $k => $v) {
|
2014-06-20 12:41:16 +02:00
|
|
|
$this->add($k, $v);
|
2014-06-17 12:00:49 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
foreach ($values as $value) {
|
2014-06-20 12:41:16 +02:00
|
|
|
$this->add($param, $value);
|
2014-06-17 12:00:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2014-06-20 15:50:55 +02:00
|
|
|
protected function clearValues()
|
|
|
|
{
|
|
|
|
$this->params = array();
|
|
|
|
$this->index = array();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function mergeValues($param, $values = null)
|
|
|
|
{
|
|
|
|
if ($values === null && is_array($param)) {
|
|
|
|
foreach ($param as $k => $v) {
|
|
|
|
$this->set($k, $v);
|
|
|
|
}
|
|
|
|
} else {
|
2014-09-05 13:35:51 +02:00
|
|
|
if (! is_array($values)) {
|
|
|
|
$values = array($values);
|
|
|
|
}
|
2014-06-20 15:50:55 +02:00
|
|
|
foreach ($values as $value) {
|
|
|
|
$this->set($param, $value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setValues($param, $values = null)
|
|
|
|
{
|
|
|
|
$this->clearValues();
|
|
|
|
return $this->addValues($param, $values);
|
|
|
|
}
|
|
|
|
|
2014-06-17 12:00:49 +02:00
|
|
|
/**
|
|
|
|
* Add the given parameter with the given value in front of all other values
|
|
|
|
*
|
|
|
|
* This will add the given parameter in front of all others, regardless of
|
|
|
|
* whether it already exists.
|
|
|
|
*
|
|
|
|
* @param string $param The parameter you're interested in
|
|
|
|
* @param string $value The value to be stored
|
|
|
|
*
|
2015-04-07 14:23:26 +02:00
|
|
|
* @return $this
|
2014-06-17 12:00:49 +02:00
|
|
|
*/
|
|
|
|
public function unshift($param, $value)
|
|
|
|
{
|
2014-08-19 09:45:58 +02:00
|
|
|
array_unshift($this->params, array($this->urlEncode($param), $this->urlEncode($value)));
|
2014-06-17 12:00:49 +02:00
|
|
|
$this->reIndexAll();
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the given parameter with the given value
|
|
|
|
*
|
|
|
|
* This will set the given parameter, and override eventually existing ones.
|
|
|
|
*
|
|
|
|
* @param string $param The parameter you want to set
|
|
|
|
* @param string $value The value to be stored
|
|
|
|
*
|
2015-04-07 14:23:26 +02:00
|
|
|
* @return $this
|
2014-06-17 12:00:49 +02:00
|
|
|
*/
|
|
|
|
public function set($param, $value)
|
|
|
|
{
|
|
|
|
if (! $this->has($param)) {
|
|
|
|
return $this->add($param, $value);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (count($this->index[$param]) > 1) {
|
|
|
|
$remove = array_pop($this->index[$param]);
|
|
|
|
unset($this->params[$remove]);
|
|
|
|
}
|
|
|
|
|
2014-08-19 09:45:58 +02:00
|
|
|
$this->params[$this->index[$param][0]] = array(
|
|
|
|
$this->urlEncode($param),
|
|
|
|
$this->urlEncode($this->cleanupValue($value))
|
|
|
|
);
|
2014-06-17 12:00:49 +02:00
|
|
|
$this->reIndexAll();
|
|
|
|
|
2015-02-03 16:27:59 +01:00
|
|
|
return $this;
|
2014-06-17 12:00:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function remove($param)
|
|
|
|
{
|
|
|
|
$changed = false;
|
|
|
|
|
|
|
|
if (! is_array($param)) {
|
|
|
|
$param = array($param);
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($param as $p) {
|
|
|
|
if ($this->has($p)) {
|
|
|
|
foreach ($this->index[$p] as $key) {
|
|
|
|
unset($this->params[$key]);
|
|
|
|
}
|
2014-08-19 09:49:53 +02:00
|
|
|
$changed = true;
|
2014-06-17 12:00:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($changed) {
|
|
|
|
$this->reIndexAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function without($param)
|
|
|
|
{
|
|
|
|
$params = clone $this;
|
|
|
|
return $params->remove($param);
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: push, pop?
|
|
|
|
|
|
|
|
protected function indexLastOne()
|
|
|
|
{
|
|
|
|
end($this->params);
|
|
|
|
$key = key($this->params);
|
|
|
|
$param = $this->params[$key][0];
|
|
|
|
$this->addParamToIndex($param, $key);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function addParamToIndex($param, $key)
|
|
|
|
{
|
|
|
|
if (! $this->has($param)) {
|
|
|
|
$this->index[$param] = array();
|
|
|
|
}
|
|
|
|
$this->index[$param][] = $key;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function reIndexAll()
|
|
|
|
{
|
|
|
|
$this->index = array();
|
|
|
|
$this->params = array_values($this->params);
|
|
|
|
foreach ($this->params as $key => & $param) {
|
|
|
|
$this->addParamToIndex($param[0], $key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function cleanupValue($value)
|
|
|
|
{
|
|
|
|
return is_bool($value) ? $value : (string) $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function parseQueryString($queryString)
|
|
|
|
{
|
|
|
|
$parts = preg_split('~&~', $queryString, -1, PREG_SPLIT_NO_EMPTY);
|
|
|
|
foreach ($parts as $part) {
|
|
|
|
$this->parseQueryStringPart($part);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function parseQueryStringPart($part)
|
|
|
|
{
|
|
|
|
if (strpos($part, '=') === false) {
|
2014-08-19 09:45:58 +02:00
|
|
|
$this->addEncoded($part, true);
|
2014-06-17 12:00:49 +02:00
|
|
|
} else {
|
|
|
|
list($key, $val) = preg_split('/=/', $part, 2);
|
2014-08-19 09:45:58 +02:00
|
|
|
$this->addEncoded($key, $val);
|
2014-06-17 12:00:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-16 16:01:42 +02:00
|
|
|
/**
|
|
|
|
* Return the parameters of this url as sequenced or associative array
|
|
|
|
*
|
|
|
|
* @param bool $sequenced
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function toArray($sequenced = true)
|
2014-07-16 15:16:05 +02:00
|
|
|
{
|
2015-06-16 16:01:42 +02:00
|
|
|
if ($sequenced) {
|
|
|
|
return $this->params;
|
|
|
|
}
|
|
|
|
|
|
|
|
$params = array();
|
|
|
|
foreach ($this->params as $param) {
|
|
|
|
if ($param[1] === true) {
|
|
|
|
$params[] = $param[0];
|
|
|
|
} else {
|
|
|
|
$params[$param[0]] = $param[1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $params;
|
2014-07-16 15:16:05 +02:00
|
|
|
}
|
|
|
|
|
2014-08-19 09:42:16 +02:00
|
|
|
public function toString($separator = null)
|
2014-06-17 12:00:49 +02:00
|
|
|
{
|
2014-08-19 09:42:16 +02:00
|
|
|
if ($separator === null) {
|
|
|
|
$separator = $this->separator;
|
|
|
|
}
|
2014-06-17 12:00:49 +02:00
|
|
|
$parts = array();
|
|
|
|
foreach ($this->params as $p) {
|
|
|
|
if ($p[1] === true) {
|
|
|
|
$parts[] = $p[0];
|
|
|
|
} else {
|
|
|
|
$parts[] = $p[0] . '=' . $p[1];
|
|
|
|
}
|
|
|
|
}
|
2014-08-19 09:42:16 +02:00
|
|
|
return implode($separator, $parts);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function __toString()
|
|
|
|
{
|
|
|
|
return $this->toString();
|
2014-06-17 12:00:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public static function fromQueryString($queryString = null)
|
|
|
|
{
|
|
|
|
if ($queryString === null) {
|
2014-08-19 14:53:56 +02:00
|
|
|
$queryString = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
|
2014-06-17 12:00:49 +02:00
|
|
|
}
|
|
|
|
$params = new static();
|
|
|
|
$params->parseQueryString($queryString);
|
|
|
|
|
|
|
|
return $params;
|
|
|
|
}
|
|
|
|
}
|