diff --git a/src/App.php b/src/App.php index 0ee5de37ba..d099091bd2 100644 --- a/src/App.php +++ b/src/App.php @@ -673,14 +673,21 @@ public function url($page = [], array $extraRequestUrlArgs = []): string if ($pagePath === '') { // TODO path must always start with '/' $pagePath = '/'; } - if (substr($pagePath, -1) === '/') { - $pagePath = $this->urlBuildingIndexPage; - } else { - $pagePath = basename($pagePath, $this->urlBuildingExt); - } } - if (!str_contains(basename($pagePath), '.')) { - $pagePath .= $this->urlBuildingExt; + + if (substr($pagePath, -1) === '/') { + $pagePath = $pagePath . $this->urlBuildingIndexPage . $this->urlBuildingExt; + } elseif ($pagePath === '') { + $pagePath = '/' . $pagePath . $this->urlBuildingIndexPage . $this->urlBuildingExt; + } else { + $pagePathPart = trim(dirname($pagePath), '.'); + $pagePathFile = basename($pagePath, $this->urlBuildingExt); + + if ($pagePathPart !== '') { + $pagePathPart .= '/'; + } + + $pagePath = str_replace('//', '/', $pagePathPart . $pagePathFile) . $this->urlBuildingExt; } $args = $extraRequestUrlArgs; diff --git a/tests/AppTest.php b/tests/AppTest.php index 3d2c998a81..5c3e315a27 100644 --- a/tests/AppTest.php +++ b/tests/AppTest.php @@ -7,6 +7,7 @@ use Atk4\Core\Phpunit\TestCase; use Atk4\Ui\Exception\LateOutputError; use Atk4\Ui\HtmlTemplate; +use Nyholm\Psr7\Factory\Psr17Factory; class AppTest extends TestCase { @@ -65,4 +66,96 @@ public function testUnexpectedOutputLateError(): void ob_end_clean(); } } + + public function provideUrlBuildingCases(): iterable + { + return [ + // simple cases + [[], [], '/', '/index.php', '/default.php8', '/'], + [[], [], '/test/', '/test/index.php', '/test/default.php8', '/test/'], + + // simple cases with query args in request + [[], [], '/?test=atk4', '/index.php?test=atk4', '/default.php8?test=atk4', '/?test=atk4'], + [[], [], '/test/?test=atk4', '/test/index.php?test=atk4', '/test/default.php8?test=atk4', '/test/?test=atk4'], + + // simple cases with extra query args in request + [[], ['extra_args' => 'atk4'], '/?test=atk4', '/index.php?extra_args=atk4&test=atk4', '/default.php8?extra_args=atk4&test=atk4', '/?extra_args=atk4&test=atk4'], + [[], ['extra_args' => 'atk4'], '/test/?test=atk4', '/test/index.php?extra_args=atk4&test=atk4', '/test/default.php8?extra_args=atk4&test=atk4', '/test/?extra_args=atk4&test=atk4'], + + // simple cases with page as string + ['test', [], '/', 'test.php', 'test.php8', 'test'], + ['test/test/a', [], '/', 'test/test/a.php', 'test/test/a.php8', 'test/test/a'], + ['test/index', [], '/', 'test/index.php', 'test/index.php8', 'test/index'], + ['test/index', [], '/test/', 'test/index.php', 'test/index.php8', 'test/index'], + // failing on linux, failing on Windows for different/dirname reason ['/index.php', [], '/', '/index.php', '/default.php8', '/'], + // failing on Windows for dirname reason ['/request-url', [], '/request-url', '/request-url.php', '/request-url.php8', '/request-url'], + ['/request-url/', [], '/request-url/', '/request-url/index.php', '/request-url/default.php8', '/request-url/'], + ['/test/', [], '/test/', '/test/index.php', '/test/default.php8', '/test/'], + + // simple cases with page as array with 0 => string + [['test'], [], '/', 'test.php', 'test.php8', 'test'], + [['test/test/a'], [], '/', 'test/test/a.php', 'test/test/a.php8', 'test/test/a'], + [['test/index'], [], '/test/', 'test/index.php', 'test/index.php8', 'test/index'], + + // query args in page cases + [['test', 'extra_args' => 'atk4'], [], '/', 'test.php?extra_args=atk4', 'test.php8?extra_args=atk4', 'test?extra_args=atk4'], + [['test/test/a', 'extra_args' => 'atk4'], [], '/', 'test/test/a.php?extra_args=atk4', 'test/test/a.php8?extra_args=atk4', 'test/test/a?extra_args=atk4'], + [['test/index', 'extra_args' => 'atk4'], [], '/test/', 'test/index.php?extra_args=atk4', 'test/index.php8?extra_args=atk4', 'test/index?extra_args=atk4'], + + // extra query args cases + [['test'], ['extra_args' => 'atk4'], '/', 'test.php?extra_args=atk4', 'test.php8?extra_args=atk4', 'test?extra_args=atk4'], + [['test/test/a'], ['extra_args' => 'atk4'], '/', 'test/test/a.php?extra_args=atk4', 'test/test/a.php8?extra_args=atk4', 'test/test/a?extra_args=atk4'], + [['test/index'], ['extra_args' => 'atk4'], '/test/', 'test/index.php?extra_args=atk4', 'test/index.php8?extra_args=atk4', 'test/index?extra_args=atk4'], + + // query args in page cases and query args in request cases and extra query args cases + [['test', 'page_args' => 'atk4'], ['extra_args' => 'atk4'], '/?extra_args=atk4&query_args=atk4&page_args=atk4', 'test.php?extra_args=atk4&query_args=atk4&page_args=atk4', 'test.php8?extra_args=atk4&query_args=atk4&page_args=atk4', 'test?extra_args=atk4&query_args=atk4&page_args=atk4'], + [['test/test/a', 'page_args' => 'atk4'], ['extra_args' => 'atk4'], '/?extra_args=atk4&query_args=atk4&page_args=atk4', 'test/test/a.php?extra_args=atk4&query_args=atk4&page_args=atk4', 'test/test/a.php8?extra_args=atk4&query_args=atk4&page_args=atk4', 'test/test/a?extra_args=atk4&query_args=atk4&page_args=atk4'], + [['test/index', 'page_args' => 'atk4'], ['extra_args' => 'atk4'], '/test/?extra_args=atk4&query_args=atk4&page_args=atk4', 'test/index.php?extra_args=atk4&query_args=atk4&page_args=atk4', 'test/index.php8?extra_args=atk4&query_args=atk4&page_args=atk4', 'test/index?extra_args=atk4&query_args=atk4&page_args=atk4'], + [['test', 'page_args' => 'atk4', 'check_unset_page' => false], ['extra_args' => 'atk4'], '/?extra_args=atk4&query_args=atk4&page_args=atk4', 'test.php?extra_args=atk4&query_args=atk4&page_args=atk4', 'test.php8?extra_args=atk4&query_args=atk4&page_args=atk4', 'test?extra_args=atk4&query_args=atk4&page_args=atk4'], + ]; + } + + /** + * @dataProvider provideUrlBuildingCases + * + * @param string|array<0|string, string|int|false> $page URL as string or array with page name as first element and other GET arguments + * @param array $extraRequestUrlArgs Additional URL arguments, deleting sticky can delete them + */ + public function testUrlBuilding($page, array $extraRequestUrlArgs, string $requestUrl, string $exceptedStd, string $exceptedCustom, string $exceptedRouting): void + { + $factory = new Psr17Factory(); + $request = $factory->createServerRequest('GET', 'http://127.0.0.1' . $requestUrl); + + $stickyGetArguments = array_merge([ + '__atk_json' => false, + '__atk_tab' => false, + ], $request->getQueryParams()); + + $app = $this->createApp([ + 'request' => $request, + 'stickyGetArguments' => $stickyGetArguments, + ]); + + self::assertSame($exceptedStd, $app->url($page, $extraRequestUrlArgs)); + self::assertSame($exceptedStd, $app->jsUrl($page, $extraRequestUrlArgs)); + + $app = $this->createApp([ + 'request' => $request, + 'stickyGetArguments' => $stickyGetArguments, + 'urlBuildingIndexPage' => 'default', + 'urlBuildingExt' => '.php8', + ]); + + self::assertSame($exceptedCustom, $app->url($page, $extraRequestUrlArgs)); + self::assertSame($exceptedCustom, $app->jsUrl($page, $extraRequestUrlArgs)); + + $app = $this->createApp([ + 'request' => $request, + 'stickyGetArguments' => $stickyGetArguments, + 'urlBuildingIndexPage' => '', + 'urlBuildingExt' => '', + ]); + self::assertSame($exceptedRouting, $app->url($page, $extraRequestUrlArgs)); + self::assertSame($exceptedRouting, $app->jsUrl($page, $extraRequestUrlArgs)); + } } diff --git a/tests/CallbackTest.php b/tests/CallbackTest.php index b4eaacf158..9f8d75a30c 100644 --- a/tests/CallbackTest.php +++ b/tests/CallbackTest.php @@ -89,8 +89,8 @@ public function testViewUrlCallback(): void $this->simulateCallbackTriggering($cbApp); $this->simulateCallbackTriggering($cb); - $expectedUrlCbApp = 'index.php?' . Callback::URL_QUERY_TRIGGER_PREFIX . 'aa=callback&' . Callback::URL_QUERY_TARGET . '=aa'; - $expectedUrlCb = 'index.php?' . /* Callback::URL_QUERY_TRIGGER_PREFIX . 'aa=1&' . */ Callback::URL_QUERY_TRIGGER_PREFIX . 'bb=callback&' . Callback::URL_QUERY_TARGET . '=bb'; + $expectedUrlCbApp = '/index.php?' . Callback::URL_QUERY_TRIGGER_PREFIX . 'aa=callback&' . Callback::URL_QUERY_TARGET . '=aa'; + $expectedUrlCb = '/index.php?' . /* Callback::URL_QUERY_TRIGGER_PREFIX . 'aa=1&' . */ Callback::URL_QUERY_TRIGGER_PREFIX . 'bb=callback&' . Callback::URL_QUERY_TARGET . '=bb'; self::assertSame($expectedUrlCbApp, $cbApp->getUrl()); self::assertSame($expectedUrlCb, $cb->getUrl());