@@ -62,6 +62,16 @@ class IncomingRequest extends Request
6262 */
6363 public $ uri ;
6464
65+ /**
66+ * The detected path (relative to SCRIPT_NAME).
67+ * Note: current_url() uses this to build its URI,
68+ * so this becomes the source for the "current URL"
69+ * when working with the share request instance.
70+ *
71+ * @var string|null
72+ */
73+ protected $ path ;
74+
6575 /**
6676 * File collection
6777 *
@@ -159,12 +169,6 @@ public function __construct($config, URI $uri = null, $body = 'php://input', Use
159169
160170 $ this ->detectURI ($ config ->uriProtocol , $ config ->baseURL );
161171
162- // Check if the baseURL scheme needs to be coerced into its secure version
163- if ($ config ->forceGlobalSecureRequests && $ this ->uri ->getScheme () === 'http ' )
164- {
165- $ this ->uri ->setScheme ('https ' );
166- }
167-
168172 $ this ->validLocales = $ config ->supportedLocales ;
169173
170174 $ this ->detectLocale ($ config );
@@ -613,11 +617,34 @@ public function getFile(string $fileID)
613617 */
614618 protected function detectURI (string $ protocol , string $ baseURL )
615619 {
616- $ this ->uri ->setPath ($ this ->detectPath ($ protocol ));
620+ // Passing the config is unnecessary but left for legacy purposes
621+ $ config = clone $ this ->config ;
622+ $ config ->baseURL = $ baseURL ;
623+
624+ $ this ->setPath ($ this ->detectPath ($ protocol ), $ config );
625+ }
626+
627+ /**
628+ * Sets the relative path and updates the URI object.
629+ * Note: Since current_url() accesses the shared request
630+ * instance, this can be used to change the "current URL"
631+ * for testing.
632+ *
633+ * @param string $path URI path relative to SCRIPT_NAME
634+ * @param App $config Optional alternate config to use
635+ *
636+ * @return $this
637+ */
638+ public function setPath (string $ path , App $ config = null )
639+ {
640+ $ this ->path = $ path ;
641+ $ this ->uri ->setPath ($ path );
642+
643+ $ config = $ config ?? $ this ->config ;
617644
618645 // It's possible the user forgot a trailing slash on their
619646 // baseURL, so let's help them out.
620- $ baseURL = $ baseURL === '' ? $ baseURL : rtrim ($ baseURL , '/ ' ) . '/ ' ;
647+ $ baseURL = $ config -> baseURL === '' ? $ config -> baseURL : rtrim ($ config -> baseURL , '/ ' ) . '/ ' ;
621648
622649 // Based on our baseURL provided by the developer
623650 // set our current domain name, scheme
@@ -629,23 +656,44 @@ protected function detectURI(string $protocol, string $baseURL)
629656
630657 // Ensure we have any query vars
631658 $ this ->uri ->setQuery ($ _SERVER ['QUERY_STRING ' ] ?? '' );
632- }
633- else
634- {
635- // @codeCoverageIgnoreStart
636- if (! is_cli ())
659+
660+ // Check if the baseURL scheme needs to be coerced into its secure version
661+ if ($ config ->forceGlobalSecureRequests && $ this ->uri ->getScheme () === 'http ' )
637662 {
638- die ( ' You have an empty or invalid base URL. The baseURL value must be set in Config\App.php, or through the .env file. ' );
663+ $ this -> uri -> setScheme ( ' https ' );
639664 }
640- // @codeCoverageIgnoreEnd
641665 }
666+ // @codeCoverageIgnoreStart
667+ elseif (! is_cli ())
668+ {
669+ die ('You have an empty or invalid base URL. The baseURL value must be set in Config\App.php, or through the .env file. ' );
670+ }
671+ // @codeCoverageIgnoreEnd
672+
673+ return $ this ;
642674 }
643675
644676 //--------------------------------------------------------------------
645677
646678 /**
647- * Based on the URIProtocol Config setting, will attempt to
648- * detect the path portion of the current URI.
679+ * Returns the path relative to SCRIPT_NAME,
680+ * running detection as necessary.
681+ *
682+ * @return string
683+ */
684+ public function getPath (): string
685+ {
686+ if (is_null ($ this ->path ))
687+ {
688+ $ this ->detectPath ($ this ->config ->uriProtocol );
689+ }
690+
691+ return $ this ->path ;
692+ }
693+
694+ /**
695+ * Detects the relative path based on
696+ * the URIProtocol Config setting.
649697 *
650698 * @param string $protocol
651699 *
@@ -661,18 +709,18 @@ public function detectPath(string $protocol = ''): string
661709 switch ($ protocol )
662710 {
663711 case 'REQUEST_URI ' :
664- $ path = $ this ->parseRequestURI ();
712+ $ this -> path = $ this ->parseRequestURI ();
665713 break ;
666714 case 'QUERY_STRING ' :
667- $ path = $ this ->parseQueryString ();
715+ $ this -> path = $ this ->parseQueryString ();
668716 break ;
669717 case 'PATH_INFO ' :
670718 default :
671- $ path = $ this ->fetchGlobal ('server ' , $ protocol ) ?? $ this ->parseRequestURI ();
719+ $ this -> path = $ this ->fetchGlobal ('server ' , $ protocol ) ?? $ this ->parseRequestURI ();
672720 break ;
673721 }
674722
675- return $ path ;
723+ return $ this -> path ;
676724 }
677725
678726 //--------------------------------------------------------------------
@@ -731,23 +779,23 @@ protected function parseRequestURI(): string
731779 $ query = $ parts ['query ' ] ?? '' ;
732780 $ uri = $ parts ['path ' ] ?? '' ;
733781
734- if (isset ($ _SERVER ['SCRIPT_NAME ' ][0 ]) && pathinfo ($ _SERVER ['SCRIPT_NAME ' ], PATHINFO_EXTENSION ) === 'php ' )
782+ // Strip the SCRIPT_NAME path from the URI
783+ if ($ uri !== '' && isset ($ _SERVER ['SCRIPT_NAME ' ][0 ]) && pathinfo ($ _SERVER ['SCRIPT_NAME ' ], PATHINFO_EXTENSION ) === 'php ' )
735784 {
736- // strip the script name from the beginning of the URI
737- if (strpos ($ uri , $ _SERVER ['SCRIPT_NAME ' ]) === 0 && strpos ($ uri , '/index.php ' ) === 0 )
738- {
739- $ uri = (string ) substr ($ uri , strlen ($ _SERVER ['SCRIPT_NAME ' ]));
740- }
741- // if the script is nested, strip the parent folder & script from the URI
742- elseif (strpos ($ uri , $ _SERVER ['SCRIPT_NAME ' ]) > 0 )
743- {
744- $ uri = (string ) substr ($ uri , strpos ($ uri , $ _SERVER ['SCRIPT_NAME ' ]) + strlen ($ _SERVER ['SCRIPT_NAME ' ]));
745- }
746- // or if index.php is implied
747- elseif (strpos ($ uri , dirname ($ _SERVER ['SCRIPT_NAME ' ])) === 0 )
785+ // Compare each segment, dropping them until there is no match
786+ $ segments = $ keep = explode ('/ ' , $ uri );
787+ foreach (explode ('/ ' , $ _SERVER ['SCRIPT_NAME ' ]) as $ i => $ segment )
748788 {
749- $ uri = (string ) substr ($ uri , strlen (dirname ($ _SERVER ['SCRIPT_NAME ' ])));
789+ // If these segments are not the same then we're done
790+ if ($ segment !== $ segments [$ i ])
791+ {
792+ break ;
793+ }
794+
795+ array_shift ($ keep );
750796 }
797+
798+ $ uri = implode ('/ ' , $ keep );
751799 }
752800
753801 // This section ensures that even on servers that require the URI to contain the query string (Nginx) a correct
@@ -763,7 +811,10 @@ protected function parseRequestURI(): string
763811 $ _SERVER ['QUERY_STRING ' ] = $ query ;
764812 }
765813
814+ // Update our globals for values likely to been have changed
766815 parse_str ($ _SERVER ['QUERY_STRING ' ], $ _GET );
816+ $ this ->populateGlobals ('server ' );
817+ $ this ->populateGlobals ('get ' );
767818
768819 $ uri = URI ::removeDotSegments ($ uri );
769820
@@ -795,7 +846,10 @@ protected function parseQueryString(): string
795846 $ uri = $ uri [0 ];
796847 }
797848
849+ // Update our globals for values likely to been have changed
798850 parse_str ($ _SERVER ['QUERY_STRING ' ], $ _GET );
851+ $ this ->populateGlobals ('server ' );
852+ $ this ->populateGlobals ('get ' );
799853
800854 $ uri = URI ::removeDotSegments ($ uri );
801855
0 commit comments