Skip to content

Commit

Permalink
Add queryString method using crwlr/query-string
Browse files Browse the repository at this point in the history
When installed the new queryString method provides advanced access to
the url query via the Query class from the new crwlr/query-string
package. The new package requires PHP version 8, and the url package
requires only 7.2. If there will be another major version of the url
package it will at least require 8.0 and require the query-string
package. For now it's only suggested. The method throws an exception
when the query-string package isn't installed.
  • Loading branch information
otsch committed Jun 1, 2022
1 parent ba7b44f commit 1ba8838
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 16 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- The new `queryString()` method can be used to access and
manipulate the query via a `Query` object when the
`crwlr/query-string` package is installed.

## [1.1.1] - 2022-01-12
### Fixed
Expand Down
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,31 @@ array(2) {
}
```

If you're already on PHP 8 you can additionally install the
`crwlr/query-string` package for a more advanced API to access and manipulate
the query string.

```bash
composer require crwlr/query-string
```

After the package is installed the `queryString()` method returns an instance
of the `Query` class from that package. You can find the docs for this
class [here](https://www.crwlr.software/packages/query-string/v1.0/getting-started).
A quick example:

```php
$url = Url::parse('https://www.example.com/listing?page[number]=3&page[size]=25');

$url->queryString()
->get('page')
->set('number', '4');

var_dump($url->__toString());

// string(68) "https://www.example.com/listing?page%5Bnumber%5D=4&page%5Bsize%5D=25"
```

### Modifying urls

All methods that are used to get a component's value can also be used to
Expand Down
6 changes: 5 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
"require-dev": {
"phpunit/phpunit": "^8.0",
"friendsofphp/php-cs-fixer": "^3.4",
"phpstan/phpstan": "^1.3"
"phpstan/phpstan": "^1.3",
"crwlr/query-string": "dev-main"
},
"autoload": {
"psr-4": {
Expand All @@ -54,5 +55,8 @@
"update-schemes": "@php bin/update-schemes",
"update-default-ports": "@php bin/update-default-ports",
"add-git-hooks": "@php bin/add-git-hooks"
},
"suggest": {
"crwlr/query-string": "The queryString() method requires this additional package"
}
}
82 changes: 67 additions & 15 deletions src/Url.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

namespace Crwlr\Url;

use Crwlr\QueryString\Query;
use Crwlr\Url\Exceptions\InvalidUrlComponentException;
use Crwlr\Url\Exceptions\InvalidUrlException;
use Crwlr\Url\Psr\Uri;
use Exception;
use InvalidArgumentException;

/**
Expand Down Expand Up @@ -55,7 +57,7 @@ class Url
private $path;

/**
* @var string|null
* @var string|Query|null
*/
private $query;

Expand Down Expand Up @@ -87,6 +89,7 @@ class Url
'path',
'query',
'queryArray',
'queryString',
'fragment',
'root',
'relative',
Expand Down Expand Up @@ -164,7 +167,7 @@ public static function parsePsr7(string $url = ''): Uri
*
* @param null|string $scheme
* @return string|null|Url
* @throws InvalidUrlComponentException
* @throws InvalidUrlComponentException|Exception
*/
public function scheme(?string $scheme = null)
{
Expand All @@ -184,7 +187,7 @@ public function scheme(?string $scheme = null)
*
* @param null|string $authority
* @return string|null|Url
* @throws InvalidUrlComponentException
* @throws InvalidUrlComponentException|Exception
*/
public function authority(?string $authority = null)
{
Expand Down Expand Up @@ -218,7 +221,7 @@ public function authority(?string $authority = null)
*
* @param null|string $user
* @return string|null|Url
* @throws InvalidUrlComponentException
* @throws InvalidUrlComponentException|Exception
*/
public function user(?string $user = null)
{
Expand All @@ -238,7 +241,7 @@ public function user(?string $user = null)
*
* @param null|string $password
* @return string|null|Url
* @throws InvalidUrlComponentException
* @throws InvalidUrlComponentException|Exception
*/
public function password(?string $password = null)
{
Expand All @@ -258,7 +261,7 @@ public function password(?string $password = null)
*
* @param null|string $pass
* @return string|null|Url
* @throws InvalidUrlComponentException
* @throws InvalidUrlComponentException|Exception
*/
public function pass(?string $pass = null)
{
Expand All @@ -270,7 +273,7 @@ public function pass(?string $pass = null)
*
* @param string|null $userInfo
* @return string|null|Url
* @throws InvalidUrlComponentException
* @throws InvalidUrlComponentException|Exception
*/
public function userInfo(?string $userInfo = null)
{
Expand All @@ -297,7 +300,7 @@ public function userInfo(?string $userInfo = null)
*
* @param null|string $host
* @return string|null|Url
* @throws InvalidUrlComponentException
* @throws InvalidUrlComponentException|Exception
*/
public function host(?string $host = null)
{
Expand All @@ -322,7 +325,7 @@ public function host(?string $host = null)
*
* @param null|string $domain
* @return string|null|Url
* @throws InvalidUrlComponentException
* @throws InvalidUrlComponentException|Exception
*/
public function domain(?string $domain = null)
{
Expand All @@ -349,7 +352,7 @@ public function domain(?string $domain = null)
*
* @param null|string $domainLabel
* @return string|null|Url
* @throws InvalidUrlComponentException
* @throws InvalidUrlComponentException|Exception
*/
public function domainLabel(?string $domainLabel = null)
{
Expand Down Expand Up @@ -378,7 +381,7 @@ public function domainLabel(?string $domainLabel = null)
*
* @param null|string $domainSuffix
* @return string|null|Url
* @throws InvalidUrlComponentException
* @throws InvalidUrlComponentException|Exception
*/
public function domainSuffix(?string $domainSuffix = null)
{
Expand Down Expand Up @@ -407,7 +410,7 @@ public function domainSuffix(?string $domainSuffix = null)
*
* @param null|string $subdomain
* @return string|null|Url
* @throws InvalidUrlComponentException
* @throws InvalidUrlComponentException|Exception
*/
public function subdomain(?string $subdomain = null)
{
Expand Down Expand Up @@ -435,7 +438,7 @@ public function subdomain(?string $subdomain = null)
*
* @param null|int $port
* @return int|null|Url
* @throws InvalidUrlComponentException
* @throws InvalidUrlComponentException|Exception
*/
public function port(?int $port = null)
{
Expand All @@ -452,6 +455,8 @@ public function port(?int $port = null)

/**
* Reset the port component to null.
*
* @throws Exception
*/
public function resetPort(): void
{
Expand All @@ -464,6 +469,7 @@ public function resetPort(): void
*
* @param null|string $path
* @return string|null|Url
* @throws Exception
*/
public function path(?string $path = null)
{
Expand All @@ -481,11 +487,12 @@ public function path(?string $path = null)
*
* @param null|string $query
* @return string|null|Url
* @throws Exception
*/
public function query(?string $query = null)
{
if ($query === null) {
return $this->query;
return $this->query instanceof Query ? $this->query->toString() : $this->query;
} elseif ($query === '') {
$this->query = null;
} else {
Expand All @@ -500,10 +507,15 @@ public function query(?string $query = null)
*
* @param null|array|string[] $query
* @return string[]|Url
* @throws Exception
*/
public function queryArray(?array $query = null)
{
if ($query === null) {
if ($this->query instanceof Query) {
return $this->query->toArray();
}

return $this->query ? Helpers::queryStringToArray($this->query) : [];
} else {
$this->query = $this->validateComponentValue('query', http_build_query($query));
Expand All @@ -512,11 +524,44 @@ public function queryArray(?array $query = null)
return $this->updateFullUrlAndReturnInstance();
}

/**
* @throws Exception
*/
public function queryString(): Query
{
if (version_compare(PHP_VERSION, '8.0.0', '<')) {
throw new Exception(
'The queryString() method uses the crwlr/query-string composer package under the hood, which ' .
'requires PHP version 8.0.0 or above.'
);
}

if (!class_exists(Query::class)) {
throw new Exception(
'The queryString() method uses the crwlr/query-string composer package under the hood, but it isn\'t ' .
'installed yet. Install it by running: composer require crwlr/query-string.'
);
}

if (!$this->query instanceof Query) {
$this->query = Query::fromString($this->query ?? '');

$url = $this;

$this->query->setDirtyHook(function () use ($url) {
$url->updateFullUrl();
});
}

return $this->query;
}

/**
* Get or set the fragment component.
*
* @param null|string $fragment
* @return string|null|Url
* @throws Exception
*/
public function fragment(?string $fragment = null)
{
Expand All @@ -537,6 +582,7 @@ public function fragment(?string $fragment = null)
* https://www.example.com/path?query=string => https://www.example.com
*
* @return string
* @throws Exception
*/
public function root(): string
{
Expand All @@ -554,6 +600,7 @@ public function root(): string
* If that's the case, starting slashes in the path are reduced to one in the return value of this method.
*
* @return string
* @throws Exception
*/
public function relative(): string
{
Expand All @@ -575,6 +622,7 @@ public function relative(): string
* https://tools.ietf.org/html/rfc3986#section-4.1
*
* @return bool
* @throws Exception
*/
public function isRelativeReference(): bool
{
Expand Down Expand Up @@ -908,6 +956,8 @@ private function validateComponentValue(string $componentName, $componentValue)

/**
* Regenerate the full url after changing components.
*
* @throws Exception
*/
private function updateFullUrl(): void
{
Expand All @@ -916,6 +966,7 @@ private function updateFullUrl(): void

/**
* @return Url
* @throws Exception
*/
private function updateFullUrlAndReturnInstance(): Url
{
Expand All @@ -930,7 +981,7 @@ private function updateFullUrlAndReturnInstance(): Url
* Used in authority and host methods, because it's not allowed to set an authority when path doesn't start with
* slash.
*
* @throws InvalidUrlComponentException
* @throws InvalidUrlComponentException|Exception
*/
private function validatePathStartsWithSlash(): void
{
Expand Down Expand Up @@ -987,6 +1038,7 @@ private function compare($compareToUrl, ?string $componentName = null): bool

/**
* @return array|(string|int)[]
* @throws Exception
*/
private function authorityComponents(): array
{
Expand Down
Loading

0 comments on commit 1ba8838

Please sign in to comment.