From 1bb8f524982cef6a814d070550efe11d3d61966b Mon Sep 17 00:00:00 2001 From: Francesco Ciannavei Date: Wed, 18 Jun 2025 15:24:39 +0200 Subject: [PATCH 01/14] fix: fixed the codeigniter routing for installations in subdirectories with the page index. I fixed the codeigniter routing for installations in subdirectories by adding a check to see if the project is running in a subdirectory and removing the public directory from the script name. I am still testing the change as it's in a very sensible area of the code. I also still need to write tests for this change. I will do that soon. --- system/HTTP/SiteURIFactory.php | 42 ++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/system/HTTP/SiteURIFactory.php b/system/HTTP/SiteURIFactory.php index c87898c0470e..979eac61d3ee 100644 --- a/system/HTTP/SiteURIFactory.php +++ b/system/HTTP/SiteURIFactory.php @@ -111,9 +111,43 @@ public function detectRoutePath(string $protocol = ''): string */ private function parseRequestURI(): string { + $serverScriptName = $this->superglobals->server('SCRIPT_NAME'); // This is the SCRIPT_NAME, it's a variable that contains the name of the script being executed, it's used from the codeigniter framework to perform the routing process. + // We need to check if the project is in a subdirectory + $projectIsInSubDir = false; // Variable used to check if the project is in a subdirectory + $baseURLConfig = config(\Config\App::class)->baseURL; // Base URL configuration from the Config\App class or .env file + $baseUrlParsed = parse_url($baseURLConfig); // PHP function to parse the URL + $baseUrlPath = ""; // If the url does not have a / at the end like https://example.com the path will not be set by parse_url + if(isset($baseUrlParsed['path'])) { // Check if the path is set in the parsed URL (read the line above) + $baseUrlPath = $baseUrlParsed['path'] ?? ""; + } + + // We need to check that the project is in a subdirectory, if it is in a subdirectory we need to remove the public directory from the script name + $baseUrlPathArr = explode('/', $baseUrlPath); + foreach($baseUrlPathArr as $i => $pathFragment){ + if($pathFragment === "") unset($baseUrlPathArr[$i]); + } + if(count($baseUrlPathArr) > 0){ // Check that the path has at least one fragment + $projectIsInSubDir = true; // The project is running in a subdirectory + } + + // We need to remove public from the script name, this way we can correctly perform the routing + if($projectIsInSubDir){ + $subDirPath = "/" . implode("/", $baseUrlPathArr); // This is the path of the subdirectory, we are using arrays because it can be multiple levels deep + $subDirPathPosition = strpos($serverScriptName, $subDirPath."/public"); // This is the position of the public directory in the script name. The strpos function returns only the first instance + if ($subDirPathPosition !== false) { // We are checking if the public directory is found in the script name. + $serverScriptName = substr_replace( + $serverScriptName, // The input string. + $subDirPath, // The replacement string. + $subDirPathPosition, // The offset from where we are replacing. + strlen($subDirPath."/public") // The length of the portion of string which is to be replaced. + ); + } + } + + if ( $this->superglobals->server('REQUEST_URI') === null - || $this->superglobals->server('SCRIPT_NAME') === null + || $serverScriptName === null ) { return ''; } @@ -128,13 +162,13 @@ private function parseRequestURI(): string // Strip the SCRIPT_NAME path from the URI if ( - $path !== '' && $this->superglobals->server('SCRIPT_NAME') !== '' - && pathinfo($this->superglobals->server('SCRIPT_NAME'), PATHINFO_EXTENSION) === 'php' + $path !== '' && $serverScriptName !== '' + && pathinfo($serverScriptName, PATHINFO_EXTENSION) === 'php' ) { // Compare each segment, dropping them until there is no match $segments = $keep = explode('/', $path); - foreach (explode('/', $this->superglobals->server('SCRIPT_NAME')) as $i => $segment) { + foreach (explode('/', $serverScriptName) as $i => $segment) { // If these segments are not the same then we're done if (! isset($segments[$i]) || $segment !== $segments[$i]) { break; From b65b1f51f6e0b1a5ea45fa1d44fb7f0c8112a31f Mon Sep 17 00:00:00 2001 From: Francesco Ciannavei Date: Mon, 23 Jun 2025 09:20:46 +0200 Subject: [PATCH 02/14] Revert "fix: fixed the codeigniter routing for installations in subdirectories with the page index." This reverts commit 1bb8f524982cef6a814d070550efe11d3d61966b. --- system/HTTP/SiteURIFactory.php | 42 ++++------------------------------ 1 file changed, 4 insertions(+), 38 deletions(-) diff --git a/system/HTTP/SiteURIFactory.php b/system/HTTP/SiteURIFactory.php index 979eac61d3ee..c87898c0470e 100644 --- a/system/HTTP/SiteURIFactory.php +++ b/system/HTTP/SiteURIFactory.php @@ -111,43 +111,9 @@ public function detectRoutePath(string $protocol = ''): string */ private function parseRequestURI(): string { - $serverScriptName = $this->superglobals->server('SCRIPT_NAME'); // This is the SCRIPT_NAME, it's a variable that contains the name of the script being executed, it's used from the codeigniter framework to perform the routing process. - // We need to check if the project is in a subdirectory - $projectIsInSubDir = false; // Variable used to check if the project is in a subdirectory - $baseURLConfig = config(\Config\App::class)->baseURL; // Base URL configuration from the Config\App class or .env file - $baseUrlParsed = parse_url($baseURLConfig); // PHP function to parse the URL - $baseUrlPath = ""; // If the url does not have a / at the end like https://example.com the path will not be set by parse_url - if(isset($baseUrlParsed['path'])) { // Check if the path is set in the parsed URL (read the line above) - $baseUrlPath = $baseUrlParsed['path'] ?? ""; - } - - // We need to check that the project is in a subdirectory, if it is in a subdirectory we need to remove the public directory from the script name - $baseUrlPathArr = explode('/', $baseUrlPath); - foreach($baseUrlPathArr as $i => $pathFragment){ - if($pathFragment === "") unset($baseUrlPathArr[$i]); - } - if(count($baseUrlPathArr) > 0){ // Check that the path has at least one fragment - $projectIsInSubDir = true; // The project is running in a subdirectory - } - - // We need to remove public from the script name, this way we can correctly perform the routing - if($projectIsInSubDir){ - $subDirPath = "/" . implode("/", $baseUrlPathArr); // This is the path of the subdirectory, we are using arrays because it can be multiple levels deep - $subDirPathPosition = strpos($serverScriptName, $subDirPath."/public"); // This is the position of the public directory in the script name. The strpos function returns only the first instance - if ($subDirPathPosition !== false) { // We are checking if the public directory is found in the script name. - $serverScriptName = substr_replace( - $serverScriptName, // The input string. - $subDirPath, // The replacement string. - $subDirPathPosition, // The offset from where we are replacing. - strlen($subDirPath."/public") // The length of the portion of string which is to be replaced. - ); - } - } - - if ( $this->superglobals->server('REQUEST_URI') === null - || $serverScriptName === null + || $this->superglobals->server('SCRIPT_NAME') === null ) { return ''; } @@ -162,13 +128,13 @@ private function parseRequestURI(): string // Strip the SCRIPT_NAME path from the URI if ( - $path !== '' && $serverScriptName !== '' - && pathinfo($serverScriptName, PATHINFO_EXTENSION) === 'php' + $path !== '' && $this->superglobals->server('SCRIPT_NAME') !== '' + && pathinfo($this->superglobals->server('SCRIPT_NAME'), PATHINFO_EXTENSION) === 'php' ) { // Compare each segment, dropping them until there is no match $segments = $keep = explode('/', $path); - foreach (explode('/', $serverScriptName) as $i => $segment) { + foreach (explode('/', $this->superglobals->server('SCRIPT_NAME')) as $i => $segment) { // If these segments are not the same then we're done if (! isset($segments[$i]) || $segment !== $segments[$i]) { break; From 4343fe4d35384257215ea9ab225d1607235a42c4 Mon Sep 17 00:00:00 2001 From: Francesco Ciannavei Date: Mon, 23 Jun 2025 09:59:06 +0200 Subject: [PATCH 03/14] fix: fixed the codeigniter routing for installations in subdirectories with the page index. I fixed the codeigniter routing for installations in subdirectories by removing the path to the subdirectory from the uri during the routing process in the SiteURIFactory. I am still testing the change as it's in a very sensible area of the code. I also still need to write tests for this change. I will do that soon. --- system/HTTP/SiteURIFactory.php | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/system/HTTP/SiteURIFactory.php b/system/HTTP/SiteURIFactory.php index c87898c0470e..36f0a1a6528b 100644 --- a/system/HTTP/SiteURIFactory.php +++ b/system/HTTP/SiteURIFactory.php @@ -111,8 +111,32 @@ public function detectRoutePath(string $protocol = ''): string */ private function parseRequestURI(): string { + $appConfig = config(\Config\App::class); + $baseUrl = $appConfig->baseURL; + $indexPage = $appConfig->indexPage; + $baseUri = false; + $parsedUrl = parse_url($baseUrl); + + if(isset($parsedUrl['path'])){ // The path could be empty if the url is just a domain + $baseUri = $parsedUrl['path']; + } + if($baseUri){ + $baseUriArray = explode('/', $baseUri); + $baseUriArray = array_filter($baseUriArray); // We remove the empty strings from the array + $baseUri = implode('/', $baseUriArray); // We join the array back into a string with slashes + if(strlen($baseUri) > 0){ + $baseUri = "/" . $baseUri; // We add a slash at the beginning of the base Uri as implode will not do that + }else{ + $baseUri = false; + } + } + + $serverRequestUri = $this->superglobals->server('REQUEST_URI'); // We get the request URI from the server superglobals + if($baseUri) $serverRequestUri = ltrim($serverRequestUri, $baseUri); // We remove the base Uri from the request URI if it exists, baseUri is the path to the subdirectory + if($indexPage) $serverRequestUri = ltrim($serverRequestUri, "/" . $indexPage); // We remove the index page from the request URI if it exists + if ( - $this->superglobals->server('REQUEST_URI') === null + $serverRequestUri === null || $this->superglobals->server('SCRIPT_NAME') === null ) { return ''; @@ -122,7 +146,7 @@ private function parseRequestURI(): string // string contains a colon followed by a number. So we attach a dummy // host since REQUEST_URI does not include the host. This allows us to // parse out the query string and path. - $parts = parse_url('http://dummy' . $this->superglobals->server('REQUEST_URI')); + $parts = parse_url('http://dummy' . $serverRequestUri); $query = $parts['query'] ?? ''; $path = $parts['path'] ?? ''; From 89ce426f88c8e3d7008d89c63c0d23ee95cfbe3a Mon Sep 17 00:00:00 2001 From: Francesco Ciannavei Date: Mon, 23 Jun 2025 10:33:28 +0200 Subject: [PATCH 04/14] fix: fixed the codeigniter routing for installations in subdirectories with the page index 2. - in the SiteURIFactory I made sure the requestUri starts with a slash - in the SiteURIFactory I checked that the requestUri is not null The code passes the SiteURIFactoryTest --- system/HTTP/SiteURIFactory.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/system/HTTP/SiteURIFactory.php b/system/HTTP/SiteURIFactory.php index 36f0a1a6528b..46cf085079e0 100644 --- a/system/HTTP/SiteURIFactory.php +++ b/system/HTTP/SiteURIFactory.php @@ -132,8 +132,10 @@ private function parseRequestURI(): string } $serverRequestUri = $this->superglobals->server('REQUEST_URI'); // We get the request URI from the server superglobals - if($baseUri) $serverRequestUri = ltrim($serverRequestUri, $baseUri); // We remove the base Uri from the request URI if it exists, baseUri is the path to the subdirectory - if($indexPage) $serverRequestUri = ltrim($serverRequestUri, "/" . $indexPage); // We remove the index page from the request URI if it exists + + if($baseUri && !is_null($serverRequestUri)) $serverRequestUri = ltrim($serverRequestUri, $baseUri); // We remove the base Uri from the request URI if it exists, baseUri is the path to the subdirectory + if($indexPage && !is_null($serverRequestUri)) $serverRequestUri = ltrim($serverRequestUri, "/" . $indexPage); // We remove the index page from the request URI if it exists + $serverRequestUri = "/". ltrim($serverRequestUri, '/'); // makes sure that the uri starts with a slash if ( $serverRequestUri === null From 74ef94a63ad3fc54f730d23546e12695f77856ac Mon Sep 17 00:00:00 2001 From: Francesco Ciannavei Date: Mon, 23 Jun 2025 10:50:57 +0200 Subject: [PATCH 05/14] fix: fixed the codeigniter routing for installations in subdirectories with the page index 3. in the SiteURIFactory I checked that the requestUri is not null --- system/HTTP/SiteURIFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/HTTP/SiteURIFactory.php b/system/HTTP/SiteURIFactory.php index 46cf085079e0..7fb49ba5ff21 100644 --- a/system/HTTP/SiteURIFactory.php +++ b/system/HTTP/SiteURIFactory.php @@ -135,7 +135,7 @@ private function parseRequestURI(): string if($baseUri && !is_null($serverRequestUri)) $serverRequestUri = ltrim($serverRequestUri, $baseUri); // We remove the base Uri from the request URI if it exists, baseUri is the path to the subdirectory if($indexPage && !is_null($serverRequestUri)) $serverRequestUri = ltrim($serverRequestUri, "/" . $indexPage); // We remove the index page from the request URI if it exists - $serverRequestUri = "/". ltrim($serverRequestUri, '/'); // makes sure that the uri starts with a slash + if(!is_null($serverRequestUri)) $serverRequestUri = "/". ltrim($serverRequestUri, '/'); // makes sure that the uri starts with a slash if ( $serverRequestUri === null From 9063df578d9739bf6467856be5df2808540929aa Mon Sep 17 00:00:00 2001 From: Francesco Ciannavei Date: Mon, 23 Jun 2025 15:33:33 +0200 Subject: [PATCH 06/14] fix: fixed the codeigniter routing for installations in subdirectories with the page index 4. I replaced the instances of ltrim with a combination of str_starts_with and substr --- system/HTTP/SiteURIFactory.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/system/HTTP/SiteURIFactory.php b/system/HTTP/SiteURIFactory.php index 7fb49ba5ff21..395296aa6b60 100644 --- a/system/HTTP/SiteURIFactory.php +++ b/system/HTTP/SiteURIFactory.php @@ -133,9 +133,11 @@ private function parseRequestURI(): string $serverRequestUri = $this->superglobals->server('REQUEST_URI'); // We get the request URI from the server superglobals - if($baseUri && !is_null($serverRequestUri)) $serverRequestUri = ltrim($serverRequestUri, $baseUri); // We remove the base Uri from the request URI if it exists, baseUri is the path to the subdirectory - if($indexPage && !is_null($serverRequestUri)) $serverRequestUri = ltrim($serverRequestUri, "/" . $indexPage); // We remove the index page from the request URI if it exists - if(!is_null($serverRequestUri)) $serverRequestUri = "/". ltrim($serverRequestUri, '/'); // makes sure that the uri starts with a slash + if(!is_null($serverRequestUri)){ + if($baseUri && str_starts_with($serverRequestUri, $baseUri)) $serverRequestUri = substr($serverRequestUri, strlen($baseUri)); // We remove the base Uri from the request URI if it exists, baseUri is the path to the subdirectory + if($indexPage && str_starts_with($serverRequestUri, "/" . $indexPage)) $serverRequestUri = substr($serverRequestUri, strlen("/" . $indexPage)); // We remove the index page from the request URI if it exists + $serverRequestUri = "/". ltrim($serverRequestUri, '/'); // makes sure that the uri starts with a slash + } if ( $serverRequestUri === null From 20607d84c0827fe374823620700da85355b9a1af Mon Sep 17 00:00:00 2001 From: Francesco Ciannavei Date: Mon, 23 Jun 2025 17:11:49 +0200 Subject: [PATCH 07/14] fix: Error: Only booleans are allowed in &&, string given on the left side. --- system/HTTP/SiteURIFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/HTTP/SiteURIFactory.php b/system/HTTP/SiteURIFactory.php index 395296aa6b60..1bbc8bc4cd15 100644 --- a/system/HTTP/SiteURIFactory.php +++ b/system/HTTP/SiteURIFactory.php @@ -135,7 +135,7 @@ private function parseRequestURI(): string if(!is_null($serverRequestUri)){ if($baseUri && str_starts_with($serverRequestUri, $baseUri)) $serverRequestUri = substr($serverRequestUri, strlen($baseUri)); // We remove the base Uri from the request URI if it exists, baseUri is the path to the subdirectory - if($indexPage && str_starts_with($serverRequestUri, "/" . $indexPage)) $serverRequestUri = substr($serverRequestUri, strlen("/" . $indexPage)); // We remove the index page from the request URI if it exists + if($indexPage != false && str_starts_with($serverRequestUri, "/" . $indexPage)) $serverRequestUri = substr($serverRequestUri, strlen("/" . $indexPage)); // We remove the index page from the request URI if it exists $serverRequestUri = "/". ltrim($serverRequestUri, '/'); // makes sure that the uri starts with a slash } From f60db2cf341e98d4cc3250d8eb0fbefab2cf660f Mon Sep 17 00:00:00 2001 From: Francesco Ciannavei Date: Mon, 23 Jun 2025 17:17:30 +0200 Subject: [PATCH 08/14] fix: ran "php-cs-fixer fix" to make the SiteURIFactory follow the changes conform to style guide --- system/HTTP/SiteURIFactory.php | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/system/HTTP/SiteURIFactory.php b/system/HTTP/SiteURIFactory.php index 1bbc8bc4cd15..7e41e3a40d55 100644 --- a/system/HTTP/SiteURIFactory.php +++ b/system/HTTP/SiteURIFactory.php @@ -111,32 +111,36 @@ public function detectRoutePath(string $protocol = ''): string */ private function parseRequestURI(): string { - $appConfig = config(\Config\App::class); - $baseUrl = $appConfig->baseURL; + $appConfig = config(App::class); + $baseUrl = $appConfig->baseURL; $indexPage = $appConfig->indexPage; - $baseUri = false; + $baseUri = false; $parsedUrl = parse_url($baseUrl); - - if(isset($parsedUrl['path'])){ // The path could be empty if the url is just a domain + + if (isset($parsedUrl['path'])) { // The path could be empty if the url is just a domain $baseUri = $parsedUrl['path']; } - if($baseUri){ + if ($baseUri) { $baseUriArray = explode('/', $baseUri); $baseUriArray = array_filter($baseUriArray); // We remove the empty strings from the array - $baseUri = implode('/', $baseUriArray); // We join the array back into a string with slashes - if(strlen($baseUri) > 0){ - $baseUri = "/" . $baseUri; // We add a slash at the beginning of the base Uri as implode will not do that - }else{ + $baseUri = implode('/', $baseUriArray); // We join the array back into a string with slashes + if ($baseUri !== '') { + $baseUri = '/' . $baseUri; // We add a slash at the beginning of the base Uri as implode will not do that + } else { $baseUri = false; } } $serverRequestUri = $this->superglobals->server('REQUEST_URI'); // We get the request URI from the server superglobals - if(!is_null($serverRequestUri)){ - if($baseUri && str_starts_with($serverRequestUri, $baseUri)) $serverRequestUri = substr($serverRequestUri, strlen($baseUri)); // We remove the base Uri from the request URI if it exists, baseUri is the path to the subdirectory - if($indexPage != false && str_starts_with($serverRequestUri, "/" . $indexPage)) $serverRequestUri = substr($serverRequestUri, strlen("/" . $indexPage)); // We remove the index page from the request URI if it exists - $serverRequestUri = "/". ltrim($serverRequestUri, '/'); // makes sure that the uri starts with a slash + if (null !== $serverRequestUri) { + if ($baseUri && str_starts_with($serverRequestUri, $baseUri)) { + $serverRequestUri = substr($serverRequestUri, strlen($baseUri)); + } // We remove the base Uri from the request URI if it exists, baseUri is the path to the subdirectory + if ($indexPage !== false && str_starts_with($serverRequestUri, '/' . $indexPage)) { + $serverRequestUri = substr($serverRequestUri, strlen('/' . $indexPage)); + } // We remove the index page from the request URI if it exists + $serverRequestUri = '/' . ltrim($serverRequestUri, '/'); // makes sure that the uri starts with a slash } if ( From 1639f88bde5f3896e7ff3e3d4707ffb097e2809d Mon Sep 17 00:00:00 2001 From: Francesco Ciannavei Date: Tue, 24 Jun 2025 19:55:20 +0200 Subject: [PATCH 09/14] refactor: Replaced config(App::class) with $this->appConfig inside the SiteURIFactory --- system/HTTP/SiteURIFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/HTTP/SiteURIFactory.php b/system/HTTP/SiteURIFactory.php index 7e41e3a40d55..e920ba1634b3 100644 --- a/system/HTTP/SiteURIFactory.php +++ b/system/HTTP/SiteURIFactory.php @@ -111,7 +111,7 @@ public function detectRoutePath(string $protocol = ''): string */ private function parseRequestURI(): string { - $appConfig = config(App::class); + $appConfig = $this->appConfig; $baseUrl = $appConfig->baseURL; $indexPage = $appConfig->indexPage; $baseUri = false; From 5e518faf158048c82b7b56b5f25dfa82ffebbd51 Mon Sep 17 00:00:00 2001 From: Francesco Ciannavei Date: Tue, 24 Jun 2025 23:45:12 +0200 Subject: [PATCH 10/14] feat: added tests for the fix on the SiteURIFactory - I wrote some tests for the fixes I made to the SiteURIFactory - I reverted the retrieval of the config from the App class within SiteURIFactory, the reason is explained in the pull request: https://github.com/codeigniter4/CodeIgniter4/pull/9607/files/f60db2cf341e98d4cc3250d8eb0fbefab2cf660f#diff-2bdcab9f3781f203b6582279dec4886d261349628487f14baed6e8b53f3e772e --- system/HTTP/SiteURIFactory.php | 2 +- tests/system/HTTP/SiteURIFactoryTest.php | 40 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/system/HTTP/SiteURIFactory.php b/system/HTTP/SiteURIFactory.php index e920ba1634b3..7e41e3a40d55 100644 --- a/system/HTTP/SiteURIFactory.php +++ b/system/HTTP/SiteURIFactory.php @@ -111,7 +111,7 @@ public function detectRoutePath(string $protocol = ''): string */ private function parseRequestURI(): string { - $appConfig = $this->appConfig; + $appConfig = config(App::class); $baseUrl = $appConfig->baseURL; $indexPage = $appConfig->indexPage; $baseUri = false; diff --git a/tests/system/HTTP/SiteURIFactoryTest.php b/tests/system/HTTP/SiteURIFactoryTest.php index b26fde04b245..59ccfea84967 100644 --- a/tests/system/HTTP/SiteURIFactoryTest.php +++ b/tests/system/HTTP/SiteURIFactoryTest.php @@ -171,4 +171,44 @@ public static function provideCreateFromStringWithoutIndexPage(): iterable ], ]; } + + public function testCreateFromStringWithIndexPageSubDirCombinations(){ + $standardUrl = "http://localhost:8080"; + $subDirectoryAppsOptions = array( + array( + "subDir" => "", + "indexPage" => "" + ), + array( + "subDir" => "", + "indexPage" => "index.php" + ), + array( + "subDir" => "/subdir", + "indexPage" => "" + ), + array( + "subDir" => "/subdir", + "indexPage" => "index.php" + ), + array( + "subDir" => "/subdir/subsubdir", + "indexPage" => "index.php" + ), + ); + foreach($subDirectoryAppsOptions as $option){ + $route = "woot"; + config(App::class)->baseURL = $standardUrl . $option["subDir"]; + config(App::class)->indexPage = $option["indexPage"]; + + $_SERVER['PATH_INFO'] = '/' . $route; + $_SERVER['REQUEST_URI'] = $option["subDir"] . "/" . $option["indexPage"] . $_SERVER['PATH_INFO']; + $_SERVER['SCRIPT_NAME'] = $option["subDir"] . "/" .$option["indexPage"]; + $_SERVER['HTTP_HOST'] = $standardUrl; + + $factory = $this->createSiteURIFactory(); + $detectedRoutePath = $factory->detectRoutePath(); + $this->assertSame($route, $detectedRoutePath); + } + } } From 94a8d8362e9908a2ac8e1cce079c0f9e6c8db33a Mon Sep 17 00:00:00 2001 From: Francesco Ciannavei Date: Tue, 24 Jun 2025 23:52:55 +0200 Subject: [PATCH 11/14] fix: Apply Rector code style fixes --- tests/system/HTTP/SiteURIFactoryTest.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/system/HTTP/SiteURIFactoryTest.php b/tests/system/HTTP/SiteURIFactoryTest.php index 59ccfea84967..f8996262f478 100644 --- a/tests/system/HTTP/SiteURIFactoryTest.php +++ b/tests/system/HTTP/SiteURIFactoryTest.php @@ -174,28 +174,28 @@ public static function provideCreateFromStringWithoutIndexPage(): iterable public function testCreateFromStringWithIndexPageSubDirCombinations(){ $standardUrl = "http://localhost:8080"; - $subDirectoryAppsOptions = array( - array( + $subDirectoryAppsOptions = [ + [ "subDir" => "", "indexPage" => "" - ), - array( + ], + [ "subDir" => "", "indexPage" => "index.php" - ), - array( + ], + [ "subDir" => "/subdir", "indexPage" => "" - ), - array( + ], + [ "subDir" => "/subdir", "indexPage" => "index.php" - ), - array( + ], + [ "subDir" => "/subdir/subsubdir", "indexPage" => "index.php" - ), - ); + ], + ]; foreach($subDirectoryAppsOptions as $option){ $route = "woot"; config(App::class)->baseURL = $standardUrl . $option["subDir"]; From ee2013d168fe43240cd3209ae5b6fd527386bd82 Mon Sep 17 00:00:00 2001 From: Francesco Ciannavei Date: Tue, 24 Jun 2025 23:57:51 +0200 Subject: [PATCH 12/14] fix: Apply Rector code style fixes 2 --- tests/system/HTTP/SiteURIFactoryTest.php | 48 ++++++++++++------------ 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/tests/system/HTTP/SiteURIFactoryTest.php b/tests/system/HTTP/SiteURIFactoryTest.php index f8996262f478..365000238729 100644 --- a/tests/system/HTTP/SiteURIFactoryTest.php +++ b/tests/system/HTTP/SiteURIFactoryTest.php @@ -172,41 +172,43 @@ public static function provideCreateFromStringWithoutIndexPage(): iterable ]; } - public function testCreateFromStringWithIndexPageSubDirCombinations(){ - $standardUrl = "http://localhost:8080"; + public function testCreateFromStringWithIndexPageSubDirCombinations(): void + { + $standardUrl = 'http://localhost:8080'; $subDirectoryAppsOptions = [ [ - "subDir" => "", - "indexPage" => "" + 'subDir' => '', + 'indexPage' => '', ], [ - "subDir" => "", - "indexPage" => "index.php" + 'subDir' => '', + 'indexPage' => 'index.php', ], [ - "subDir" => "/subdir", - "indexPage" => "" + 'subDir' => '/subdir', + 'indexPage' => '', ], [ - "subDir" => "/subdir", - "indexPage" => "index.php" + 'subDir' => '/subdir', + 'indexPage' => 'index.php', ], [ - "subDir" => "/subdir/subsubdir", - "indexPage" => "index.php" + 'subDir' => '/subdir/subsubdir', + 'indexPage' => 'index.php', ], ]; - foreach($subDirectoryAppsOptions as $option){ - $route = "woot"; - config(App::class)->baseURL = $standardUrl . $option["subDir"]; - config(App::class)->indexPage = $option["indexPage"]; - - $_SERVER['PATH_INFO'] = '/' . $route; - $_SERVER['REQUEST_URI'] = $option["subDir"] . "/" . $option["indexPage"] . $_SERVER['PATH_INFO']; - $_SERVER['SCRIPT_NAME'] = $option["subDir"] . "/" .$option["indexPage"]; - $_SERVER['HTTP_HOST'] = $standardUrl; - - $factory = $this->createSiteURIFactory(); + + foreach ($subDirectoryAppsOptions as $option) { + $route = 'woot'; + config(App::class)->baseURL = $standardUrl . $option['subDir']; + config(App::class)->indexPage = $option['indexPage']; + + $_SERVER['PATH_INFO'] = '/' . $route; + $_SERVER['REQUEST_URI'] = $option['subDir'] . '/' . $option['indexPage'] . $_SERVER['PATH_INFO']; + $_SERVER['SCRIPT_NAME'] = $option['subDir'] . '/' . $option['indexPage']; + $_SERVER['HTTP_HOST'] = $standardUrl; + + $factory = $this->createSiteURIFactory(); $detectedRoutePath = $factory->detectRoutePath(); $this->assertSame($route, $detectedRoutePath); } From ff0c9b3665eb415e6832fc684a53029465d209ef Mon Sep 17 00:00:00 2001 From: Francesco Ciannavei Date: Thu, 26 Jun 2025 14:34:08 +0200 Subject: [PATCH 13/14] refactor: test for index page and subdir combinations Refactors testCreateFromStringWithIndexPageSubDirCombinations to use a data provider for better clarity and maintainability. The test now receives parameters for subdirectory and index page, and the data provider supplies various combinations to test route detection. --- tests/system/HTTP/SiteURIFactoryTest.php | 72 +++++++++++++----------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/tests/system/HTTP/SiteURIFactoryTest.php b/tests/system/HTTP/SiteURIFactoryTest.php index 365000238729..9c5a5902c840 100644 --- a/tests/system/HTTP/SiteURIFactoryTest.php +++ b/tests/system/HTTP/SiteURIFactoryTest.php @@ -172,45 +172,51 @@ public static function provideCreateFromStringWithoutIndexPage(): iterable ]; } - public function testCreateFromStringWithIndexPageSubDirCombinations(): void + #[DataProvider('provideCreateFromStringWithIndexPageSubDirCombinations')] + public function testCreateFromStringWithIndexPageSubDirCombinations( + string $subDir, + string $indexPage, + ): void { + $standardUrl = 'http://localhost:8080'; + $standardScriptName = '/public/index.php'; + + $route = 'controller/method'; + config(App::class)->baseURL = $standardUrl . $subDir; + config(App::class)->indexPage = $indexPage; + + $_SERVER['PATH_INFO'] = '/' . $route; + $_SERVER['REQUEST_URI'] = $subDir . '/' . $indexPage . $_SERVER['PATH_INFO']; + $_SERVER['SCRIPT_NAME'] = $subDir . $standardScriptName; + $_SERVER['HTTP_HOST'] = $standardUrl; + + $factory = $this->createSiteURIFactory(); + $detectedRoutePath = $factory->detectRoutePath(); + $this->assertSame($route, $detectedRoutePath); + } + + public static function provideCreateFromStringWithIndexPageSubDirCombinations(): iterable { - $standardUrl = 'http://localhost:8080'; - $subDirectoryAppsOptions = [ - [ - 'subDir' => '', - 'indexPage' => '', + return [ + 'no subdir and no index' => [ + '', + '', ], - [ - 'subDir' => '', - 'indexPage' => 'index.php', + 'no subdir and index' => [ + '', + 'index.php', ], - [ - 'subDir' => '/subdir', - 'indexPage' => '', + 'subdir and no index' => [ + '/subdir', + '', ], - [ - 'subDir' => '/subdir', - 'indexPage' => 'index.php', + 'subdir and index' => [ + '/subdir', + 'index.php', ], - [ - 'subDir' => '/subdir/subsubdir', - 'indexPage' => 'index.php', + 'subdir 2 levels deep string and index' => [ + '/subdir/subsubdir', + 'index.php', ], ]; - - foreach ($subDirectoryAppsOptions as $option) { - $route = 'woot'; - config(App::class)->baseURL = $standardUrl . $option['subDir']; - config(App::class)->indexPage = $option['indexPage']; - - $_SERVER['PATH_INFO'] = '/' . $route; - $_SERVER['REQUEST_URI'] = $option['subDir'] . '/' . $option['indexPage'] . $_SERVER['PATH_INFO']; - $_SERVER['SCRIPT_NAME'] = $option['subDir'] . '/' . $option['indexPage']; - $_SERVER['HTTP_HOST'] = $standardUrl; - - $factory = $this->createSiteURIFactory(); - $detectedRoutePath = $factory->detectRoutePath(); - $this->assertSame($route, $detectedRoutePath); - } } } From 20d43daf6d90872dab8441453fff20c8615d21e7 Mon Sep 17 00:00:00 2001 From: Francesco Ciannavei Date: Thu, 26 Jun 2025 21:45:31 +0200 Subject: [PATCH 14/14] Refactor SiteURIFactory to use injected App config Replaces usage of global config(App::class) with the injected $appConfig property in SiteURIFactory. Updates related test to pass App config instance directly, improving test isolation and code clarity. --- system/HTTP/SiteURIFactory.php | 2 +- tests/system/HTTP/SiteURIFactoryTest.php | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/system/HTTP/SiteURIFactory.php b/system/HTTP/SiteURIFactory.php index 7e41e3a40d55..e920ba1634b3 100644 --- a/system/HTTP/SiteURIFactory.php +++ b/system/HTTP/SiteURIFactory.php @@ -111,7 +111,7 @@ public function detectRoutePath(string $protocol = ''): string */ private function parseRequestURI(): string { - $appConfig = config(App::class); + $appConfig = $this->appConfig; $baseUrl = $appConfig->baseURL; $indexPage = $appConfig->indexPage; $baseUri = false; diff --git a/tests/system/HTTP/SiteURIFactoryTest.php b/tests/system/HTTP/SiteURIFactoryTest.php index 9c5a5902c840..737e2d8ddeb1 100644 --- a/tests/system/HTTP/SiteURIFactoryTest.php +++ b/tests/system/HTTP/SiteURIFactoryTest.php @@ -180,16 +180,17 @@ public function testCreateFromStringWithIndexPageSubDirCombinations( $standardUrl = 'http://localhost:8080'; $standardScriptName = '/public/index.php'; - $route = 'controller/method'; - config(App::class)->baseURL = $standardUrl . $subDir; - config(App::class)->indexPage = $indexPage; + $route = 'controller/method'; + $appConfig = new App(); + $appConfig->baseURL = $standardUrl . $subDir; + $appConfig->indexPage = $indexPage; $_SERVER['PATH_INFO'] = '/' . $route; $_SERVER['REQUEST_URI'] = $subDir . '/' . $indexPage . $_SERVER['PATH_INFO']; $_SERVER['SCRIPT_NAME'] = $subDir . $standardScriptName; $_SERVER['HTTP_HOST'] = $standardUrl; - $factory = $this->createSiteURIFactory(); + $factory = $this->createSiteURIFactory($appConfig); $detectedRoutePath = $factory->detectRoutePath(); $this->assertSame($route, $detectedRoutePath); }