|
9 | 9 | namespace chillerlan\HTTP\Psr7; |
10 | 10 |
|
11 | 11 | use InvalidArgumentException, TypeError; |
12 | | -use Psr\Http\Message\{MessageInterface, RequestInterface, ResponseInterface, UploadedFileInterface}; |
| 12 | +use Psr\Http\Message\{MessageInterface, RequestInterface, ResponseInterface, UploadedFileInterface, UriInterface}; |
13 | 13 |
|
14 | | -use function array_combine, array_keys, array_map, array_merge, array_values, call_user_func_array, count, explode, |
| 14 | +use function array_combine, array_filter, array_keys, array_map, array_merge, array_values, call_user_func_array, count, explode, |
15 | 15 | gzdecode, gzinflate, gzuncompress, implode, is_array, is_bool, is_iterable, is_numeric, is_scalar, is_string, |
16 | | - json_decode, json_encode, parse_str, parse_url, rawurlencode, simplexml_load_string, sort, strtolower, trim, |
| 16 | + json_decode, json_encode, parse_str, parse_url, rawurldecode, rawurlencode, simplexml_load_string, sort, strtolower, trim, |
17 | 17 | ucfirst, uksort; |
18 | 18 |
|
19 | 19 | use const PHP_URL_QUERY, SORT_STRING; |
@@ -499,3 +499,119 @@ function decompress_content(MessageInterface $message):string{ |
499 | 499 | } |
500 | 500 |
|
501 | 501 | } |
| 502 | + |
| 503 | +/** |
| 504 | + * Whether the URI is absolute, i.e. it has a scheme. |
| 505 | + * |
| 506 | + * An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true |
| 507 | + * if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative |
| 508 | + * to another URI, the base URI. Relative references can be divided into several forms: |
| 509 | + * - network-path references, e.g. '//example.com/path' |
| 510 | + * - absolute-path references, e.g. '/path' |
| 511 | + * - relative-path references, e.g. 'subpath' |
| 512 | + * |
| 513 | + * @see Uri::isNetworkPathReference |
| 514 | + * @see Uri::isAbsolutePathReference |
| 515 | + * @see Uri::isRelativePathReference |
| 516 | + * @link https://tools.ietf.org/html/rfc3986#section-4 |
| 517 | + */ |
| 518 | +function uriIsAbsolute(UriInterface $uri):bool{ |
| 519 | + return $uri->getScheme() !== ''; |
| 520 | +} |
| 521 | + |
| 522 | +/** |
| 523 | + * Whether the URI is a network-path reference. |
| 524 | + * |
| 525 | + * A relative reference that begins with two slash characters is termed an network-path reference. |
| 526 | + * |
| 527 | + * @link https://tools.ietf.org/html/rfc3986#section-4.2 |
| 528 | + */ |
| 529 | +function uriIsNetworkPathReference(UriInterface $uri):bool{ |
| 530 | + return $uri->getScheme() === '' && $uri->getAuthority() !== ''; |
| 531 | +} |
| 532 | + |
| 533 | +/** |
| 534 | + * Whether the URI is a absolute-path reference. |
| 535 | + * |
| 536 | + * A relative reference that begins with a single slash character is termed an absolute-path reference. |
| 537 | + * |
| 538 | + * @link https://tools.ietf.org/html/rfc3986#section-4.2 |
| 539 | + */ |
| 540 | +function uriIsAbsolutePathReference(UriInterface $uri):bool{ |
| 541 | + return $uri->getScheme() === '' && $uri->getAuthority() === '' && isset($uri->getPath()[0]) && $uri->getPath()[0] === '/'; |
| 542 | +} |
| 543 | + |
| 544 | +/** |
| 545 | + * Whether the URI is a relative-path reference. |
| 546 | + * |
| 547 | + * A relative reference that does not begin with a slash character is termed a relative-path reference. |
| 548 | + * |
| 549 | + * @return bool |
| 550 | + * @link https://tools.ietf.org/html/rfc3986#section-4.2 |
| 551 | + */ |
| 552 | +function uriIsRelativePathReference(UriInterface $uri):bool{ |
| 553 | + return $uri->getScheme() === '' && $uri->getAuthority() === '' && (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/'); |
| 554 | +} |
| 555 | + |
| 556 | +/** |
| 557 | + * removes a specific query string value. |
| 558 | + * |
| 559 | + * Any existing query string values that exactly match the provided key are |
| 560 | + * removed. |
| 561 | + * |
| 562 | + * @param string $key Query string key to remove. |
| 563 | + */ |
| 564 | +function uriWithoutQueryValue(UriInterface $uri, string $key):UriInterface{ |
| 565 | + $current = $uri->getQuery(); |
| 566 | + |
| 567 | + if($current === ''){ |
| 568 | + return $uri; |
| 569 | + } |
| 570 | + |
| 571 | + $decodedKey = rawurldecode($key); |
| 572 | + |
| 573 | + $result = array_filter(explode('&', $current), function($part) use ($decodedKey){ |
| 574 | + return rawurldecode(explode('=', $part)[0]) !== $decodedKey; |
| 575 | + }); |
| 576 | + |
| 577 | + return $uri->withQuery(implode('&', $result)); |
| 578 | +} |
| 579 | + |
| 580 | +/** |
| 581 | + * adds a specific query string value. |
| 582 | + * |
| 583 | + * Any existing query string values that exactly match the provided key are |
| 584 | + * removed and replaced with the given key value pair. |
| 585 | + * |
| 586 | + * A value of null will set the query string key without a value, e.g. "key" |
| 587 | + * instead of "key=value". |
| 588 | + * |
| 589 | + * @param string $key Key to set. |
| 590 | + * @param string|null $value Value to set |
| 591 | + */ |
| 592 | +function uriWithQueryValue(UriInterface $uri, string $key, string $value = null):UriInterface{ |
| 593 | + $current = $uri->getQuery(); |
| 594 | + |
| 595 | + if($current === ''){ |
| 596 | + $result = []; |
| 597 | + } |
| 598 | + else{ |
| 599 | + $decodedKey = rawurldecode($key); |
| 600 | + $result = array_filter(explode('&', $current), function($part) use ($decodedKey){ |
| 601 | + return rawurldecode(explode('=', $part)[0]) !== $decodedKey; |
| 602 | + }); |
| 603 | + } |
| 604 | + |
| 605 | + // Query string separators ("=", "&") within the key or value need to be encoded |
| 606 | + // (while preventing double-encoding) before setting the query string. All other |
| 607 | + // chars that need percent-encoding will be encoded by withQuery(). |
| 608 | + $replaceQuery = ['=' => '%3D', '&' => '%26']; |
| 609 | + $key = strtr($key, $replaceQuery); |
| 610 | + |
| 611 | + $result[] = $value !== null |
| 612 | + ? $key.'='.strtr($value, $replaceQuery) |
| 613 | + : $key; |
| 614 | + |
| 615 | + return $uri->withQuery(implode('&', $result)); |
| 616 | +} |
| 617 | + |
0 commit comments