1515use InvalidArgumentException ;
1616use 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