Skip to content

Commit 85a373a

Browse files
committed
:octocat: split non-PSR Uri methods into extended class
1 parent d94b347 commit 85a373a

File tree

6 files changed

+314
-273
lines changed

6 files changed

+314
-273
lines changed

src/Psr17/factory_helpers.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
namespace chillerlan\HTTP\Psr17;
1111

1212
use chillerlan\HTTP\Psr7;
13-
use chillerlan\HTTP\Psr7\{ServerRequest, Stream, Uri};
13+
use chillerlan\HTTP\Psr7\{ServerRequest, Stream, UriExtended};
1414
use InvalidArgumentException;
1515
use Psr\Http\Message\StreamInterface;
1616

@@ -48,9 +48,9 @@ function_exists('getallheaders') ? getallheaders() : [],
4848
/**
4949
* Get a Uri populated with values from $_SERVER.
5050
*
51-
* @return \chillerlan\HTTP\Psr7\Uri|\Psr\Http\Message\UriInterface
51+
* @return \chillerlan\HTTP\Psr7\UriExtended|\Psr\Http\Message\UriInterface
5252
*/
53-
function create_uri_from_globals():Uri{
53+
function create_uri_from_globals():UriExtended{
5454
$parts = [];
5555
$hasPort = false;
5656
$hasQuery = false;
@@ -91,7 +91,7 @@ function create_uri_from_globals():Uri{
9191
$parts['query'] = $_SERVER['QUERY_STRING'];
9292
}
9393

94-
return Uri::fromParts($parts);
94+
return UriExtended::fromParts($parts);
9595
}
9696

9797

src/Psr7/Uri.php

Lines changed: 22 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
use InvalidArgumentException;
1616
use Psr\Http\Message\UriInterface;
1717

18-
final class Uri implements UriInterface{
18+
class Uri implements UriInterface{
1919

20-
private const DEFAULT_PORTS = [
20+
protected const DEFAULT_PORTS = [
2121
'http' => 80,
2222
'https' => 443,
2323
'ftp' => 21,
@@ -34,42 +34,42 @@ final class Uri implements UriInterface{
3434
/**
3535
* @var string
3636
*/
37-
private $scheme = '';
37+
protected $scheme = '';
3838

3939
/**
4040
* @var string
4141
*/
42-
private $user = '';
42+
protected $user = '';
4343

4444
/**
4545
* @var string
4646
*/
47-
private $pass = '';
47+
protected $pass = '';
4848

4949
/**
5050
* @var string
5151
*/
52-
private $host = '';
52+
protected $host = '';
5353

5454
/**
5555
* @var int
5656
*/
57-
private $port = null;
57+
protected $port = null;
5858

5959
/**
6060
* @var string
6161
*/
62-
private $path = '';
62+
protected $path = '';
6363

6464
/**
6565
* @var string
6666
*/
67-
private $query = '';
67+
protected $query = '';
6868

6969
/**
7070
* @var string
7171
*/
72-
private $fragment = '';
72+
protected $fragment = '';
7373

7474
/**
7575
* Uri constructor.
@@ -132,7 +132,7 @@ public function __toString(){
132132
* @return string
133133
* @throws \InvalidArgumentException
134134
*/
135-
private function filterScheme($scheme):string{
135+
protected function filterScheme($scheme):string{
136136

137137
if(!is_string($scheme)){
138138
throw new InvalidArgumentException(sprintf('scheme must be a string'));
@@ -177,7 +177,7 @@ public function withScheme($scheme):UriInterface{
177177
* @return string
178178
* @throws \InvalidArgumentException
179179
*/
180-
private function filterUser($user):string{
180+
protected function filterUser($user):string{
181181

182182
if(!is_string($user)){
183183
throw new InvalidArgumentException(sprintf('user must be a string'));
@@ -192,7 +192,7 @@ private function filterUser($user):string{
192192
* @return string
193193
* @throws \InvalidArgumentException
194194
*/
195-
private function filterPass($pass):string{
195+
protected function filterPass($pass):string{
196196

197197
if(!is_string($pass)){
198198
throw new InvalidArgumentException(sprintf('pass must be a string'));
@@ -259,7 +259,7 @@ public function withUserInfo($user, $password = null):UriInterface{
259259
* @return string
260260
* @throws \InvalidArgumentException
261261
*/
262-
private function filterHost($host):string{
262+
protected function filterHost($host):string{
263263

264264
if(!is_string($host)){
265265
throw new InvalidArgumentException('host must be a string');
@@ -307,7 +307,7 @@ public function withHost($host):UriInterface{
307307
* @return int|null
308308
* @throws \InvalidArgumentException
309309
*/
310-
private function filterPort($port):?int{
310+
protected function filterPort($port):?int{
311311

312312
if($port === null){
313313
return null;
@@ -358,7 +358,7 @@ public function withPort($port):UriInterface{
358358
* @return string
359359
* @throws \InvalidArgumentException
360360
*/
361-
private function filterPath($path):string{
361+
protected function filterPath($path):string{
362362

363363
if(!is_string($path)){
364364
throw new InvalidArgumentException('path must be a string');
@@ -402,7 +402,7 @@ public function withPath($path):UriInterface{
402402
* @return string
403403
* @throws \InvalidArgumentException
404404
*/
405-
private function filterQuery($query):string{
405+
protected function filterQuery($query):string{
406406

407407
if(!is_string($query)){
408408
throw new InvalidArgumentException('query and fragment must be a string');
@@ -445,7 +445,7 @@ public function withQuery($query):UriInterface{
445445
*
446446
* @return string
447447
*/
448-
private function filterFragment($fragment):string{
448+
protected function filterFragment($fragment):string{
449449
return $this->filterQuery($fragment);
450450
}
451451

@@ -479,7 +479,7 @@ public function withFragment($fragment):UriInterface{
479479
*
480480
* @return void
481481
*/
482-
private function parseUriParts(array $parts):void{
482+
protected function parseUriParts(array $parts):void{
483483

484484
foreach(['scheme', 'user', 'pass', 'host', 'port', 'path', 'query', 'fragment'] as $part){
485485

@@ -499,7 +499,7 @@ private function parseUriParts(array $parts):void{
499499
*
500500
* @return string
501501
*/
502-
private function replaceChars(string $str, bool $query = null):string{
502+
protected function replaceChars(string $str, bool $query = null):string{
503503
return preg_replace_callback(
504504
'/(?:[^'
505505
.'a-z\d_\-\.~'
@@ -517,7 +517,7 @@ function(array $match):string{
517517
/**
518518
* @return void
519519
*/
520-
private function removeDefaultPort():void{
520+
protected function removeDefaultPort():void{
521521

522522
if($this->port !== null && (isset($this::DEFAULT_PORTS[$this->scheme]) && $this->port === $this::DEFAULT_PORTS[$this->scheme])){
523523
$this->port = null;
@@ -528,7 +528,7 @@ private function removeDefaultPort():void{
528528
/**
529529
* @return void
530530
*/
531-
private function validateState():void{
531+
protected function validateState():void{
532532

533533
if(empty($this->host) && ($this->scheme === 'http' || $this->scheme === 'https')){
534534
$this->host = 'localhost';
@@ -555,148 +555,4 @@ private function validateState():void{
555555

556556
}
557557

558-
/**
559-
* Additional methods
560-
*/
561-
562-
/**
563-
* @see \parse_url()
564-
*
565-
* @param array $parts
566-
*
567-
* @return \Psr\Http\Message\UriInterface|\chillerlan\HTTP\Psr7\Uri
568-
*/
569-
public static function fromParts(array $parts):UriInterface{
570-
$uri = new self;
571-
572-
$uri->parseUriParts($parts);
573-
$uri->validateState();
574-
575-
return $uri;
576-
}
577-
578-
/**
579-
* Whether the URI is absolute, i.e. it has a scheme.
580-
*
581-
* An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true
582-
* if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative
583-
* to another URI, the base URI. Relative references can be divided into several forms:
584-
* - network-path references, e.g. '//example.com/path'
585-
* - absolute-path references, e.g. '/path'
586-
* - relative-path references, e.g. 'subpath'
587-
*
588-
* @return bool
589-
* @see Uri::isNetworkPathReference
590-
* @see Uri::isAbsolutePathReference
591-
* @see Uri::isRelativePathReference
592-
* @link https://tools.ietf.org/html/rfc3986#section-4
593-
*/
594-
public function isAbsolute():bool{
595-
return $this->getScheme() !== '';
596-
}
597-
598-
/**
599-
* Whether the URI is a network-path reference.
600-
*
601-
* A relative reference that begins with two slash characters is termed an network-path reference.
602-
*
603-
* @return bool
604-
* @link https://tools.ietf.org/html/rfc3986#section-4.2
605-
*/
606-
public function isNetworkPathReference():bool{
607-
return $this->getScheme() === '' && $this->getAuthority() !== '';
608-
}
609-
610-
/**
611-
* Whether the URI is a absolute-path reference.
612-
*
613-
* A relative reference that begins with a single slash character is termed an absolute-path reference.
614-
*
615-
* @return bool
616-
* @link https://tools.ietf.org/html/rfc3986#section-4.2
617-
*/
618-
public function isAbsolutePathReference():bool{
619-
return $this->getScheme() === '' && $this->getAuthority() === '' && isset($this->getPath()[0]) && $this->getPath()[0] === '/';
620-
}
621-
622-
/**
623-
* Whether the URI is a relative-path reference.
624-
*
625-
* A relative reference that does not begin with a slash character is termed a relative-path reference.
626-
*
627-
* @return bool
628-
* @link https://tools.ietf.org/html/rfc3986#section-4.2
629-
*/
630-
public function isRelativePathReference():bool{
631-
return $this->getScheme() === '' && $this->getAuthority() === '' && (!isset($this->getPath()[0]) || $this->getPath()[0] !== '/');
632-
}
633-
634-
/**
635-
* removes a specific query string value.
636-
*
637-
* Any existing query string values that exactly match the provided key are
638-
* removed.
639-
*
640-
* @param string $key Query string key to remove.
641-
*
642-
* @return \Psr\Http\Message\UriInterface|\chillerlan\HTTP\Psr7\Uri
643-
*/
644-
public function withoutQueryValue($key):Uri{
645-
$current = $this->getQuery();
646-
647-
if($current === ''){
648-
return $this;
649-
}
650-
651-
$decodedKey = rawurldecode($key);
652-
653-
$result = array_filter(explode('&', $current), function($part) use ($decodedKey){
654-
return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
655-
});
656-
657-
/** @noinspection PhpIncompatibleReturnTypeInspection */
658-
return $this->withQuery(implode('&', $result));
659-
}
660-
661-
/**
662-
* adds a specific query string value.
663-
*
664-
* Any existing query string values that exactly match the provided key are
665-
* removed and replaced with the given key value pair.
666-
*
667-
* A value of null will set the query string key without a value, e.g. "key"
668-
* instead of "key=value".
669-
*
670-
* @param string $key Key to set.
671-
* @param string|null $value Value to set
672-
*
673-
* @return \Psr\Http\Message\UriInterface|\chillerlan\HTTP\Psr7\Uri
674-
*/
675-
public function withQueryValue($key, $value):Uri{
676-
$current = $this->getQuery();
677-
678-
if($current === ''){
679-
$result = [];
680-
}
681-
else{
682-
$decodedKey = rawurldecode($key);
683-
$result = array_filter(explode('&', $current), function($part) use ($decodedKey){
684-
return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
685-
});
686-
}
687-
688-
// Query string separators ("=", "&") within the key or value need to be encoded
689-
// (while preventing double-encoding) before setting the query string. All other
690-
// chars that need percent-encoding will be encoded by withQuery().
691-
$replaceQuery = ['=' => '%3D', '&' => '%26'];
692-
$key = strtr($key, $replaceQuery);
693-
694-
$result[] = $value !== null
695-
? $key.'='.strtr($value, $replaceQuery)
696-
: $key;
697-
698-
/** @noinspection PhpIncompatibleReturnTypeInspection */
699-
return $this->withQuery(implode('&', $result));
700-
}
701-
702558
}

0 commit comments

Comments
 (0)