diff --git a/src/Url.php b/src/Url.php index 5dce7a06..adb96cd0 100644 --- a/src/Url.php +++ b/src/Url.php @@ -2,6 +2,7 @@ namespace ipl\Web; +use Icinga\Web\UrlParams; use ipl\Stdlib\Filter\Rule; use ipl\Web\Filter\QueryString; @@ -10,27 +11,57 @@ */ class Url extends \Icinga\Web\Url { + /** @var ?Rule */ + private $filter; + /** - * Set the given filter and preserve existing query parameters + * Set the filter * - * @param Rule $filter + * @param ?Rule $filter * * @return $this */ - public function setFilter(Rule $filter): self + public function setFilter(?Rule $filter): self + { + $this->filter = $filter; + + return $this; + } + + /** + * Get the filter + * + * @return ?Rule + */ + public function getFilter(): ?Rule { - $existingParams = $this->getParams(); - $this->setQueryString(QueryString::render($filter)); - foreach ($existingParams->toArray(false) as $name => $value) { + return $this->filter; + } + + /** + * Render and return the filter and parameters as query string + * + * @param ?string $separator + * + * @return string + */ + public function getQueryString($separator = null) + { + if ($this->filter === null) { + return parent::getQueryString($separator); + } + + $params = UrlParams::fromQueryString(QueryString::render($this->filter)); + foreach ($this->getParams()->toArray(false) as $name => $value) { if (is_int($name)) { $name = $value; $value = true; } - $this->getParams()->addEncoded($name, $value); + $params->addEncoded($name, $value); } - return $this; + return $params->toString($separator); } public function __toString() diff --git a/tests/UrlTest.php b/tests/UrlTest.php index cce21f7a..42687669 100644 --- a/tests/UrlTest.php +++ b/tests/UrlTest.php @@ -45,6 +45,34 @@ public function testSetFilterPreservesExistingParameters() ); } + /** @depends testSetFilterPreservesExistingParameters */ + public function testSetFilterAcceptsNullAndStillPreservesExistingParameters() + { + $url = Url::fromPath('test', ['oof' => 'rab'], $this->createRequestMock()); + + $url->setFilter(Filter::equal('bar', 'foo')); + $url->setFilter(null); + + $this->assertSame( + '/test?oof=rab', + $url->getAbsoluteUrl() + ); + } + + /** @depends testSetFilterPreservesExistingParameters */ + public function testSetFilterOverridesCurrentFilterButKeepsOtherParameters() + { + $url = Url::fromPath('test', ['oof' => 'rab'], $this->createRequestMock()); + + $url->setFilter(Filter::equal('bar', 'foo')); + $url->setFilter(Filter::equal('foo', 'bar')); + + $this->assertSame( + '/test?foo=bar&oof=rab', + $url->getAbsoluteUrl() + ); + } + protected function createRequestMock() { return $this->createConfiguredMock(Request::class, [