From f8c73e7a779d94b004082770838f4c4d38129072 Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Wed, 20 Mar 2024 12:12:31 -0400 Subject: [PATCH 01/15] Install Folio for testing and get very basic route list working --- composer.json | 1 + src/Ziggy.php | 52 ++++++++++++++++++------- tests/Unit/FolioTest.php | 84 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 13 deletions(-) create mode 100644 tests/Unit/FolioTest.php diff --git a/composer.json b/composer.json index 342c2c03..4c8e709c 100644 --- a/composer.json +++ b/composer.json @@ -29,6 +29,7 @@ "laravel/framework": ">=9.0" }, "require-dev": { + "laravel/folio": "^1.1", "orchestra/testbench": "^7.0 || ^8.0 || ^9.0", "phpunit/phpunit": "^9.5 || ^10.3" }, diff --git a/src/Ziggy.php b/src/Ziggy.php index 9b3be04a..00c55b5d 100644 --- a/src/Ziggy.php +++ b/src/Ziggy.php @@ -5,9 +5,11 @@ use Illuminate\Contracts\Routing\UrlRoutable; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; +use Illuminate\Support\Collection; use Illuminate\Support\Reflector; use Illuminate\Support\Str; use JsonSerializable; +use Laravel\Folio\FolioRoutes; use ReflectionClass; use ReflectionMethod; use ReflectionProperty; @@ -137,19 +139,21 @@ private function nameKeyedRoutes() $routes->put($name, $route); }); - return $routes->map(function ($route) use ($bindings) { - return collect($route)->only(['uri', 'methods', 'wheres']) - ->put('domain', $route->domain()) - ->put('parameters', $route->parameterNames()) - ->put('bindings', $bindings[$route->getName()] ?? []) - ->when($middleware = config('ziggy.middleware'), function ($collection) use ($middleware, $route) { - if (is_array($middleware)) { - return $collection->put('middleware', collect($route->middleware())->intersect($middleware)->values()->all()); - } - - return $collection->put('middleware', $route->middleware()); - })->filter(); - }); + return $this->folioRoutes()->merge( + $routes->map(function ($route) use ($bindings) { + return collect($route)->only(['uri', 'methods', 'wheres']) + ->put('domain', $route->domain()) + ->put('parameters', $route->parameterNames()) + ->put('bindings', $bindings[$route->getName()] ?? []) + ->when($middleware = config('ziggy.middleware'), function ($collection) use ($middleware, $route) { + if (is_array($middleware)) { + return $collection->put('middleware', collect($route->middleware())->intersect($middleware)->values()->all()); + } + + return $collection->put('middleware', $route->middleware()); + })->filter(); + }) + ); } /** @@ -218,4 +222,26 @@ private function resolveBindings(array $routes): array return $routes; } + + private function folioRoutes(): Collection + { + if (app()->has(FolioRoutes::class)) { + $routes = app(FolioRoutes::class); + + return collect($routes->routes())->map(function (array $route, string $name) { + // wheres, parameters, bindings, middleware + return collect([ + // 'uri' => '', + 'methods' => ['GET'], + // 'wheres' => [], + // 'domain' => $route['domain'], + // 'parameters' => [], + // 'bindings' => [], + // 'middleware' => [], + ])->filter(); + }); + } + + return collect(); + } } diff --git a/tests/Unit/FolioTest.php b/tests/Unit/FolioTest.php new file mode 100644 index 00000000..c0faf283 --- /dev/null +++ b/tests/Unit/FolioTest.php @@ -0,0 +1,84 @@ +get('home', $this->noop())->name('home'); + $router->get('posts', $this->noop())->name('posts.index'); + + $router->getRoutes()->refreshNameLookups(); + } + + protected function tearDown(): void + { + File::deleteDirectories(resource_path('views')); + + parent::tearDown(); + } + + protected function getPackageProviders($app) + { + return [ + ZiggyServiceProvider::class, + FolioServiceProvider::class, + ]; + } + + /** @test */ + public function include_folio_routes() + { + // middleware! + // route model binding + // wheres? + File::ensureDirectoryExists(resource_path('views/pages')); + File::put(resource_path('views/pages/about.blade.php'), 'routes()); + + $this->assertSame([ + 'about' => [ + // 'uri' => 'about', + 'methods' => ['GET'], + ], + 'users.show' => [ + // 'uri' => 'users/{id}', + 'methods' => ['GET'], + // 'parameters' => ['id'], + ], + 'home' => [ + 'uri' => 'home', + 'methods' => ['GET', 'HEAD'], + ], + 'posts.index' => [ + 'uri' => 'posts', + 'methods' => ['GET', 'HEAD'], + ], + 'laravel-folio' => [ + 'uri' => '{fallbackPlaceholder}', + 'methods' => ['GET', 'HEAD'], + 'wheres' => ['fallbackPlaceholder' => '.*'], + 'parameters' => ['fallbackPlaceholder'], + ], + ], (new Ziggy())->toArray()['routes']); + } +} From 4bf68b157aba4fbbb07856c543a9c35bbd2af791 Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Wed, 20 Mar 2024 13:33:48 -0400 Subject: [PATCH 02/15] Wip and add more tests --- src/Ziggy.php | 47 ++++++++++++++---- tests/Unit/FolioTest.php | 101 ++++++++++++++++++++++++++++----------- 2 files changed, 112 insertions(+), 36 deletions(-) diff --git a/src/Ziggy.php b/src/Ziggy.php index 00c55b5d..4ff096e7 100644 --- a/src/Ziggy.php +++ b/src/Ziggy.php @@ -10,6 +10,7 @@ use Illuminate\Support\Str; use JsonSerializable; use Laravel\Folio\FolioRoutes; +use Laravel\Folio\Pipeline\PotentiallyBindablePathSegment; use ReflectionClass; use ReflectionMethod; use ReflectionProperty; @@ -223,23 +224,51 @@ private function resolveBindings(array $routes): array return $routes; } + /** + * @see https://github.com/laravel/folio/blob/master/src/Console/ListCommand.php + */ private function folioRoutes(): Collection { if (app()->has(FolioRoutes::class)) { - $routes = app(FolioRoutes::class); + // Use already-registered named Folio routes (not all relevant view files) to respect route caching + return collect(app(FolioRoutes::class)->routes())->map(function (array $route, string $name) { + $uri = rtrim($route['baseUri'], '/') . str_replace($route['mountPath'], '', $route['path']); + $uri = str_replace('.blade.php', '', $uri); + + $parameters = []; + $bindings = []; + + $segments = explode('/', $uri); - return collect($routes->routes())->map(function (array $route, string $name) { - // wheres, parameters, bindings, middleware - return collect([ - // 'uri' => '', + foreach ($segments as $i => $segment) { + // Folio doesn't support sub-segment parameters + if (Str::startsWith($segment, '[')) { + $param = new PotentiallyBindablePathSegment($segment); + + $parameters[] = $name = $param->trimmed(); + $segments[$i] = str_replace(['[', ']'], ['{', '}'], $segment); + + if ($field = $param->field()) { + $bindings[$name] = $field; + } + } + } + + $uri = implode('/', $segments); + + $uri = str_replace(['/index', '/index/'], ['', '/'], $uri); + + return array_filter([ + 'uri' => $uri === '' ? '/' : trim($uri, '/'), 'methods' => ['GET'], // 'wheres' => [], - // 'domain' => $route['domain'], - // 'parameters' => [], - // 'bindings' => [], + 'domain' => $route['domain'], + 'parameters' => $parameters, + 'bindings' => $bindings, // 'middleware' => [], - ])->filter(); + ]); }); + } return collect(); diff --git a/tests/Unit/FolioTest.php b/tests/Unit/FolioTest.php index c0faf283..1586d0ca 100644 --- a/tests/Unit/FolioTest.php +++ b/tests/Unit/FolioTest.php @@ -2,7 +2,6 @@ namespace Tests\Unit; -use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\File; use Laravel\Folio\Folio; use Laravel\Folio\FolioRoutes; @@ -13,18 +12,6 @@ class FolioTest extends TestCase { - protected function setUp(): void - { - parent::setUp(); - - $router = app('router'); - - $router->get('home', $this->noop())->name('home'); - $router->get('posts', $this->noop())->name('posts.index'); - - $router->getRoutes()->refreshNameLookups(); - } - protected function tearDown(): void { File::deleteDirectories(resource_path('views')); @@ -45,33 +32,23 @@ public function include_folio_routes() { // middleware! // route model binding - // wheres? File::ensureDirectoryExists(resource_path('views/pages')); File::put(resource_path('views/pages/about.blade.php'), 'routes()); + Folio::path(resource_path('views/pages')); $this->assertSame([ 'about' => [ - // 'uri' => 'about', + 'uri' => 'about', 'methods' => ['GET'], ], 'users.show' => [ - // 'uri' => 'users/{id}', + 'uri' => 'users/{id}', 'methods' => ['GET'], - // 'parameters' => ['id'], - ], - 'home' => [ - 'uri' => 'home', - 'methods' => ['GET', 'HEAD'], - ], - 'posts.index' => [ - 'uri' => 'posts', - 'methods' => ['GET', 'HEAD'], + 'parameters' => ['id'], ], 'laravel-folio' => [ 'uri' => '{fallbackPlaceholder}', @@ -81,4 +58,74 @@ public function include_folio_routes() ], ], (new Ziggy())->toArray()['routes']); } + + /** @test */ + public function normal_routes_override_folio_routes() + { + app('router')->get('about', $this->noop())->name('about'); + app('router')->getRoutes()->refreshNameLookups(); + + File::ensureDirectoryExists(resource_path('views/pages')); + File::put(resource_path('views/pages/about.blade.php'), 'assertSame([ + 'uri' => 'about', + // Folio routes don't respond to 'HEAD', so we know this is the web route + 'methods' => ['GET', 'HEAD'], + ], (new Ziggy())->toArray()['routes']['about']); + } + + /** @test */ + public function handle_parameters() + { + File::ensureDirectoryExists(resource_path('views/pages/users')); + File::put(resource_path('views/pages/users/[id].blade.php'), 'assertSame([ + 'uri' => 'users/{id}', + 'methods' => ['GET'], + 'parameters' => ['id'], + ], (new Ziggy())->toArray()['routes']['users.show']); + + $this->assertSame([ + 'uri' => 'users/{...ids}', + 'methods' => ['GET'], + 'parameters' => ['ids'], + ], (new Ziggy())->toArray()['routes']['users.some']); + } + + /** @test */ + public function handle_binding_fields() + { + // + } + + /** @test */ + public function handle_domains() + { + // + } + + /** @test */ + public function handle_middleware() + { + // + } + + /** @test */ + public function handle_multiple_root_paths() + { + // + } + + /** @test */ + public function handle_index_pages() + { + // + } } From a76b87b401a98e24f50a8b8b55577b213b7de846 Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Wed, 20 Mar 2024 14:31:14 -0400 Subject: [PATCH 03/15] Wip --- src/Ziggy.php | 23 +++++-- tests/Unit/FolioTest.php | 138 ++++++++++++++++++++++++++++++++++----- 2 files changed, 141 insertions(+), 20 deletions(-) diff --git a/src/Ziggy.php b/src/Ziggy.php index 4ff096e7..47e96146 100644 --- a/src/Ziggy.php +++ b/src/Ziggy.php @@ -9,7 +9,9 @@ use Illuminate\Support\Reflector; use Illuminate\Support\Str; use JsonSerializable; +use Laravel\Folio\FolioManager; use Laravel\Folio\FolioRoutes; +use Laravel\Folio\Pipeline\MatchedView; use Laravel\Folio\Pipeline\PotentiallyBindablePathSegment; use ReflectionClass; use ReflectionMethod; @@ -230,8 +232,10 @@ private function resolveBindings(array $routes): array private function folioRoutes(): Collection { if (app()->has(FolioRoutes::class)) { + $mountPaths = app(FolioManager::class)->mountPaths(); + // Use already-registered named Folio routes (not all relevant view files) to respect route caching - return collect(app(FolioRoutes::class)->routes())->map(function (array $route, string $name) { + return collect(app(FolioRoutes::class)->routes())->map(function (array $route) use ($mountPaths) { $uri = rtrim($route['baseUri'], '/') . str_replace($route['mountPath'], '', $route['path']); $uri = str_replace('.blade.php', '', $uri); @@ -245,8 +249,8 @@ private function folioRoutes(): Collection if (Str::startsWith($segment, '[')) { $param = new PotentiallyBindablePathSegment($segment); - $parameters[] = $name = $param->trimmed(); - $segments[$i] = str_replace(['[', ']'], ['{', '}'], $segment); + $parameters[] = $name = (string) Str::of($param->trimmed())->afterLast('.')->before(':')->before('-')->camel(); + $segments[$i] = "{{$name}}"; if ($field = $param->field()) { $bindings[$name] = $field; @@ -258,6 +262,13 @@ private function folioRoutes(): Collection $uri = str_replace(['/index', '/index/'], ['', '/'], $uri); + if ($route['domain'] && str_contains($route['domain'], '{')) { + $parameters = [Str::between($route['domain'], '{', '}'), ...$parameters]; + } + + $matchedView = new MatchedView(realpath($route['path']), [], $route['mountPath']); + $mountPath = Arr::first($mountPaths, fn ($mountPath) => $mountPath->path === realpath($route['mountPath'])); + return array_filter([ 'uri' => $uri === '' ? '/' : trim($uri, '/'), 'methods' => ['GET'], @@ -265,7 +276,11 @@ private function folioRoutes(): Collection 'domain' => $route['domain'], 'parameters' => $parameters, 'bindings' => $bindings, - // 'middleware' => [], + 'middleware' => $mountPath->middleware + ->match($matchedView) + ->prepend('web') + ->merge($matchedView->inlineMiddleware()) + ->unique()->values()->all(), ]); }); diff --git a/tests/Unit/FolioTest.php b/tests/Unit/FolioTest.php index 1586d0ca..67f968ef 100644 --- a/tests/Unit/FolioTest.php +++ b/tests/Unit/FolioTest.php @@ -2,9 +2,9 @@ namespace Tests\Unit; +use Illuminate\Support\Arr; use Illuminate\Support\Facades\File; use Laravel\Folio\Folio; -use Laravel\Folio\FolioRoutes; use Laravel\Folio\FolioServiceProvider; use Tests\TestCase; use Tighten\Ziggy\Ziggy; @@ -30,8 +30,6 @@ protected function getPackageProviders($app) /** @test */ public function include_folio_routes() { - // middleware! - // route model binding File::ensureDirectoryExists(resource_path('views/pages')); File::put(resource_path('views/pages/about.blade.php'), ' [ 'uri' => 'about', 'methods' => ['GET'], + 'middleware' => ['web'], ], 'users.show' => [ 'uri' => 'users/{id}', 'methods' => ['GET'], 'parameters' => ['id'], + 'middleware' => ['web'], ], 'laravel-folio' => [ 'uri' => '{fallbackPlaceholder}', @@ -72,13 +72,13 @@ public function normal_routes_override_folio_routes() $this->assertSame([ 'uri' => 'about', - // Folio routes don't respond to 'HEAD', so we know this is the web route + // Folio routes only respond to 'GET', so this is the web route 'methods' => ['GET', 'HEAD'], ], (new Ziggy())->toArray()['routes']['about']); } /** @test */ - public function handle_parameters() + public function parameters() { File::ensureDirectoryExists(resource_path('views/pages/users')); File::put(resource_path('views/pages/users/[id].blade.php'), ' 'users/{id}', 'methods' => ['GET'], 'parameters' => ['id'], + 'middleware' => ['web'], ], (new Ziggy())->toArray()['routes']['users.show']); $this->assertSame([ - 'uri' => 'users/{...ids}', + 'uri' => 'users/{ids}', 'methods' => ['GET'], 'parameters' => ['ids'], + 'middleware' => ['web'], ], (new Ziggy())->toArray()['routes']['users.some']); } /** @test */ - public function handle_binding_fields() + public function domains() { - // + File::ensureDirectoryExists(resource_path('views/pages/admin')); + File::put(resource_path('views/pages/admin/[...ids].blade.php'), 'path(resource_path('views/pages/admin'))->uri('admin'); + + $this->assertSame([ + 'admins.some' => [ + 'uri' => 'admin/{ids}', + 'methods' => ['GET'], + 'domain' => '{account}.ziggy.dev', + 'parameters' => ['account', 'ids'], + 'middleware' => ['web'], + ], + ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); } /** @test */ - public function handle_domains() + public function paths_and_uris() { - // + File::ensureDirectoryExists(resource_path('views/pages/guest')); + File::ensureDirectoryExists(resource_path('views/pages/admin')); + File::put(resource_path('views/pages/guest/[id].blade.php'), 'uri('/'); + Folio::path(resource_path('views/pages/admin'))->uri('/admin'); + + $this->assertSame([ + 'guests.show' => [ + 'uri' => '{id}', + 'methods' => ['GET'], + 'parameters' => ['id'], + 'middleware' => ['web'], + ], + 'admins.some' => [ + 'uri' => 'admin/{ids}', + 'methods' => ['GET'], + 'parameters' => ['ids'], + 'middleware' => ['web'], + ], + ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); } /** @test */ - public function handle_middleware() + public function index_pages() { - // + File::ensureDirectoryExists(resource_path('views/pages/blog/releases')); + File::put(resource_path('views/pages/blog/index.blade.php'), 'assertSame([ + 'blog.index' => [ + 'uri' => 'blog', + 'methods' => ['GET'], + 'middleware' => ['web'], + ], + 'blog.categories.releases.index' => [ + 'uri' => 'blog/releases', + 'methods' => ['GET'], + 'middleware' => ['web'], + ], + ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); } /** @test */ - public function handle_multiple_root_paths() + public function middleware() { - // + File::ensureDirectoryExists(resource_path('views/pages/admin')); + File::put(resource_path('views/pages/admin/index.blade.php'), 'uri('admin') + ->middleware(['*' => ['auth']]); + + $this->assertSame([ + 'admin.index' => [ + 'uri' => 'admin', + 'methods' => ['GET'], + 'middleware' => ['web', 'auth'], + ], + 'admin.special' => [ + 'uri' => 'admin/special', + 'methods' => ['GET'], + 'middleware' => ['web', 'auth', 'special'], + ], + ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); } /** @test */ - public function handle_index_pages() + public function binding_fields() { - // + File::ensureDirectoryExists(resource_path('views/pages/users')); + File::put(resource_path('views/pages/users/[User].blade.php'), 'assertSame([ + 'posts.show' => [ + 'uri' => 'posts/{post}', + 'methods' => ['GET'], + 'parameters' => ['post'], + 'bindings' => [ + 'post' => 'slug', + ], + 'middleware' => ['web'], + ], + 'users.show' => [ + 'uri' => 'users/{user}', + 'methods' => ['GET'], + 'parameters' => ['user'], + 'middleware' => ['web'], + ], + 'teams.show' => [ + 'uri' => 'teams/{team}', + 'methods' => ['GET'], + 'parameters' => ['team'], + 'bindings' => [ + 'team' => 'uid', + ], + 'middleware' => ['web'], + ], + ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); } } From 4ed192894f29dfca723379766a0816771282acc8 Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Wed, 20 Mar 2024 14:35:37 -0400 Subject: [PATCH 04/15] Fix numeric route names --- src/Ziggy.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Ziggy.php b/src/Ziggy.php index 47e96146..6e36d55c 100644 --- a/src/Ziggy.php +++ b/src/Ziggy.php @@ -142,9 +142,12 @@ private function nameKeyedRoutes() $routes->put($name, $route); }); - return $this->folioRoutes()->merge( - $routes->map(function ($route) use ($bindings) { - return collect($route)->only(['uri', 'methods', 'wheres']) + $allRoutes = $this->folioRoutes(); + + $routes->map(function ($route, $name) use ($bindings, $allRoutes) { + $allRoutes->put( + $name, + collect($route)->only(['uri', 'methods', 'wheres']) ->put('domain', $route->domain()) ->put('parameters', $route->parameterNames()) ->put('bindings', $bindings[$route->getName()] ?? []) @@ -154,9 +157,12 @@ private function nameKeyedRoutes() } return $collection->put('middleware', $route->middleware()); - })->filter(); - }) - ); + }) + ->filter() + ); + }); + + return $allRoutes; } /** From 62f0f5027935128ba7e6b55986f8a6d75d7cdf20 Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Wed, 20 Mar 2024 14:51:38 -0400 Subject: [PATCH 05/15] Formatting --- src/Ziggy.php | 3 +-- tests/Unit/FolioTest.php | 35 +++++++++++++++++++---------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/Ziggy.php b/src/Ziggy.php index 6e36d55c..827d5884 100644 --- a/src/Ziggy.php +++ b/src/Ziggy.php @@ -240,7 +240,7 @@ private function folioRoutes(): Collection if (app()->has(FolioRoutes::class)) { $mountPaths = app(FolioManager::class)->mountPaths(); - // Use already-registered named Folio routes (not all relevant view files) to respect route caching + // Use already-registered named Folio routes (instead of searching for all relevant view files) to respect route caching return collect(app(FolioRoutes::class)->routes())->map(function (array $route) use ($mountPaths) { $uri = rtrim($route['baseUri'], '/') . str_replace($route['mountPath'], '', $route['path']); $uri = str_replace('.blade.php', '', $uri); @@ -278,7 +278,6 @@ private function folioRoutes(): Collection return array_filter([ 'uri' => $uri === '' ? '/' : trim($uri, '/'), 'methods' => ['GET'], - // 'wheres' => [], 'domain' => $route['domain'], 'parameters' => $parameters, 'bindings' => $bindings, diff --git a/tests/Unit/FolioTest.php b/tests/Unit/FolioTest.php index 67f968ef..e85d7ce3 100644 --- a/tests/Unit/FolioTest.php +++ b/tests/Unit/FolioTest.php @@ -71,10 +71,12 @@ public function normal_routes_override_folio_routes() Folio::path(resource_path('views/pages')); $this->assertSame([ - 'uri' => 'about', - // Folio routes only respond to 'GET', so this is the web route - 'methods' => ['GET', 'HEAD'], - ], (new Ziggy())->toArray()['routes']['about']); + 'about' => [ + 'uri' => 'about', + // Folio routes only respond to 'GET', so this is the web route + 'methods' => ['GET', 'HEAD'], + ], + ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); } /** @test */ @@ -87,18 +89,19 @@ public function parameters() Folio::path(resource_path('views/pages')); $this->assertSame([ - 'uri' => 'users/{id}', - 'methods' => ['GET'], - 'parameters' => ['id'], - 'middleware' => ['web'], - ], (new Ziggy())->toArray()['routes']['users.show']); - - $this->assertSame([ - 'uri' => 'users/{ids}', - 'methods' => ['GET'], - 'parameters' => ['ids'], - 'middleware' => ['web'], - ], (new Ziggy())->toArray()['routes']['users.some']); + 'users.show' => [ + 'uri' => 'users/{id}', + 'methods' => ['GET'], + 'parameters' => ['id'], + 'middleware' => ['web'], + ], + 'users.some' => [ + 'uri' => 'users/{ids}', + 'methods' => ['GET'], + 'parameters' => ['ids'], + 'middleware' => ['web'], + ], + ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); } /** @test */ From bcc76b4f838fe47e8e622bae4c6c0405b5f40739 Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Wed, 20 Mar 2024 14:58:51 -0400 Subject: [PATCH 06/15] Uninstall Folio and skip tests on Laravel <10 --- .github/workflows/test.yml | 2 ++ tests/Unit/FolioTest.php | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ec8b900a..be013226 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,6 +34,8 @@ jobs: with: node-version: 20 cache: 'npm' + - run: composer remove laravel/folio --dev --no-update --no-interaction + if: matrix.laravel == 9 - run: composer require laravel/framework:"${{ matrix.laravel }}.*" --no-update --no-interaction - uses: ramsey/composer-install@v2 with: diff --git a/tests/Unit/FolioTest.php b/tests/Unit/FolioTest.php index e85d7ce3..d2dd47f8 100644 --- a/tests/Unit/FolioTest.php +++ b/tests/Unit/FolioTest.php @@ -12,6 +12,15 @@ class FolioTest extends TestCase { + protected function setUp(): void + { + parent::setUp(); + + if ((int) head(explode('.', app()->version())) < 10) { + $this->markTestSkipped('Folio requires Laravel >=10'); + } + } + protected function tearDown(): void { File::deleteDirectories(resource_path('views')); From aedbc16bf558eeb5ececfe2999cfc313e33e1df4 Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Wed, 20 Mar 2024 15:13:13 -0400 Subject: [PATCH 07/15] Wip --- tests/Unit/FolioTest.php | 70 +++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/tests/Unit/FolioTest.php b/tests/Unit/FolioTest.php index d2dd47f8..030d87e4 100644 --- a/tests/Unit/FolioTest.php +++ b/tests/Unit/FolioTest.php @@ -32,7 +32,7 @@ protected function getPackageProviders($app) { return [ ZiggyServiceProvider::class, - FolioServiceProvider::class, + ...((int) head(explode('.', app()->version())) >= 10 ? [FolioServiceProvider::class] : []), ]; } @@ -194,17 +194,15 @@ public function middleware() ->middleware(['*' => ['auth']]); $this->assertSame([ - 'admin.index' => [ - 'uri' => 'admin', - 'methods' => ['GET'], - 'middleware' => ['web', 'auth'], - ], - 'admin.special' => [ - 'uri' => 'admin/special', - 'methods' => ['GET'], - 'middleware' => ['web', 'auth', 'special'], - ], - ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); + 'uri' => 'admin', + 'methods' => ['GET'], + 'middleware' => ['web', 'auth'], + ], (new Ziggy())->toArray()['routes']['admin.index']); + $this->assertSame([ + 'uri' => 'admin/special', + 'methods' => ['GET'], + 'middleware' => ['web', 'auth', 'special'], + ], (new Ziggy())->toArray()['routes']['admin.special']); } /** @test */ @@ -220,30 +218,28 @@ public function binding_fields() Folio::path(resource_path('views/pages')); $this->assertSame([ - 'posts.show' => [ - 'uri' => 'posts/{post}', - 'methods' => ['GET'], - 'parameters' => ['post'], - 'bindings' => [ - 'post' => 'slug', - ], - 'middleware' => ['web'], - ], - 'users.show' => [ - 'uri' => 'users/{user}', - 'methods' => ['GET'], - 'parameters' => ['user'], - 'middleware' => ['web'], - ], - 'teams.show' => [ - 'uri' => 'teams/{team}', - 'methods' => ['GET'], - 'parameters' => ['team'], - 'bindings' => [ - 'team' => 'uid', - ], - 'middleware' => ['web'], - ], - ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); + 'uri' => 'posts/{post}', + 'methods' => ['GET'], + 'parameters' => ['post'], + 'bindings' => [ + 'post' => 'slug', + ], + 'middleware' => ['web'], + ], (new Ziggy())->toArray()['routes']['posts.show']); + $this->assertSame([ + 'uri' => 'users/{user}', + 'methods' => ['GET'], + 'parameters' => ['user'], + 'middleware' => ['web'], + ], (new Ziggy())->toArray()['routes']['users.show']); + $this->assertSame([ + 'uri' => 'teams/{team}', + 'methods' => ['GET'], + 'parameters' => ['team'], + 'bindings' => [ + 'team' => 'uid', + ], + 'middleware' => ['web'], + ], (new Ziggy())->toArray()['routes']['teams.show']); } } From 33280d333d61047c55a2d3a98f090dbfb232e107 Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Wed, 20 Mar 2024 18:06:41 -0400 Subject: [PATCH 08/15] Fix tests on Windows --- tests/Unit/FolioTest.php | 50 +++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/tests/Unit/FolioTest.php b/tests/Unit/FolioTest.php index 030d87e4..52b91d57 100644 --- a/tests/Unit/FolioTest.php +++ b/tests/Unit/FolioTest.php @@ -98,19 +98,17 @@ public function parameters() Folio::path(resource_path('views/pages')); $this->assertSame([ - 'users.show' => [ - 'uri' => 'users/{id}', - 'methods' => ['GET'], - 'parameters' => ['id'], - 'middleware' => ['web'], - ], - 'users.some' => [ - 'uri' => 'users/{ids}', - 'methods' => ['GET'], - 'parameters' => ['ids'], - 'middleware' => ['web'], - ], - ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); + 'uri' => 'users/{id}', + 'methods' => ['GET'], + 'parameters' => ['id'], + 'middleware' => ['web'], + ], (new Ziggy())->toArray()['routes']['users.show']); + $this->assertSame([ + 'uri' => 'users/{ids}', + 'methods' => ['GET'], + 'parameters' => ['ids'], + 'middleware' => ['web'], + ], (new Ziggy())->toArray()['routes']['users.some']); } /** @test */ @@ -210,22 +208,26 @@ public function binding_fields() { File::ensureDirectoryExists(resource_path('views/pages/users')); File::put(resource_path('views/pages/users/[User].blade.php'), 'assertSame([ - 'uri' => 'posts/{post}', - 'methods' => ['GET'], - 'parameters' => ['post'], - 'bindings' => [ - 'post' => 'slug', - ], - 'middleware' => ['web'], - ], (new Ziggy())->toArray()['routes']['posts.show']); + if (! str_starts_with(strtoupper(PHP_OS), 'WIN')) { + $this->assertSame([ + 'uri' => 'posts/{post}', + 'methods' => ['GET'], + 'parameters' => ['post'], + 'bindings' => [ + 'post' => 'slug', + ], + 'middleware' => ['web'], + ], (new Ziggy())->toArray()['routes']['posts.show']); + } $this->assertSame([ 'uri' => 'users/{user}', 'methods' => ['GET'], From b1047ba91238c6dd3a1c1c26156b91497bc34fec Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Thu, 21 Mar 2024 14:49:36 -0400 Subject: [PATCH 09/15] Add tests and implicit route model binding --- src/Ziggy.php | 8 +++ tests/Unit/FolioTest.php | 103 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/src/Ziggy.php b/src/Ziggy.php index 827d5884..6265aa77 100644 --- a/src/Ziggy.php +++ b/src/Ziggy.php @@ -260,6 +260,14 @@ private function folioRoutes(): Collection if ($field = $param->field()) { $bindings[$name] = $field; + } elseif ($param->bindable()) { + $override = (new ReflectionClass($param->class()))->isInstantiable() && ( + (new ReflectionMethod($param->class(), 'getRouteKeyName'))->class !== Model::class + || (new ReflectionMethod($param->class(), 'getKeyName'))->class !== Model::class + || (new ReflectionProperty($param->class(), 'primaryKey'))->class !== Model::class + ); + + $bindings[$name] = $override ? app($param->class())->getRouteKeyName() : 'id'; } } } diff --git a/tests/Unit/FolioTest.php b/tests/Unit/FolioTest.php index 52b91d57..d0b15edf 100644 --- a/tests/Unit/FolioTest.php +++ b/tests/Unit/FolioTest.php @@ -2,6 +2,7 @@ namespace Tests\Unit; +use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Support\Facades\File; use Laravel\Folio\Folio; @@ -244,4 +245,106 @@ public function binding_fields() 'middleware' => ['web'], ], (new Ziggy())->toArray()['routes']['teams.show']); } + + /** @test */ + public function custom_model_paths() + { + File::ensureDirectoryExists(resource_path('views/pages/users')); + File::put(resource_path('views/pages/users/[.App.User].blade.php'), 'assertSame([ + 'uri' => 'posts/{post}', + 'methods' => ['GET'], + 'parameters' => ['post'], + 'bindings' => [ + 'post' => 'slug', + ], + 'middleware' => ['web'], + ], (new Ziggy())->toArray()['routes']['posts.show']); + } + $this->assertSame([ + 'uri' => 'users/{user}', + 'methods' => ['GET'], + 'parameters' => ['user'], + 'middleware' => ['web'], + ], (new Ziggy())->toArray()['routes']['users.show']); + $this->assertSame([ + 'uri' => 'teams/{team}', + 'methods' => ['GET'], + 'parameters' => ['team'], + 'bindings' => [ + 'team' => 'uid', + ], + 'middleware' => ['web'], + ], (new Ziggy())->toArray()['routes']['teams.show']); + } + + /** @test */ + public function implicit_route_model_bindings() + { + File::ensureDirectoryExists(resource_path('views/pages/users')); + File::put(resource_path('views/pages/users/[.Tests.Unit.User].blade.php'), 'assertSame([ + 'uri' => 'users/{user}', + 'methods' => ['GET'], + 'parameters' => ['user'], + 'bindings' => [ + 'user' => 'uuid', + ], + 'middleware' => ['web'], + ], (new Ziggy)->toArray()['routes']['users.show']); + $this->assertSame([ + 'uri' => 'tags/{tag}', + 'methods' => ['GET'], + 'parameters' => ['tag'], + 'bindings' => [ + 'tag' => 'id', + ], + 'middleware' => ['web'], + ], (new Ziggy)->toArray()['routes']['tags.show']); + + $this->assertTrue(User::$wasBooted); + $this->assertFalse(Tag::$wasBooted); + } +} + +class User extends Model +{ + public static $wasBooted = false; + + public static function boot() + { + parent::boot(); + static::$wasBooted = true; + } + + public function getRouteKeyName() + { + return 'uuid'; + } +} + +class Tag extends Model +{ + public static $wasBooted = false; + + public static function boot() + { + parent::boot(); + static::$wasBooted = true; + } } From 2a89f026861bf9baa18537fbf42a97abf5695106 Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Thu, 21 Mar 2024 14:54:42 -0400 Subject: [PATCH 10/15] Fix test --- tests/Unit/FolioTest.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/Unit/FolioTest.php b/tests/Unit/FolioTest.php index d0b15edf..2256f95e 100644 --- a/tests/Unit/FolioTest.php +++ b/tests/Unit/FolioTest.php @@ -292,37 +292,37 @@ public function custom_model_paths() public function implicit_route_model_bindings() { File::ensureDirectoryExists(resource_path('views/pages/users')); - File::put(resource_path('views/pages/users/[.Tests.Unit.User].blade.php'), 'assertSame([ - 'uri' => 'users/{user}', + 'uri' => 'users/{folioUser}', 'methods' => ['GET'], - 'parameters' => ['user'], + 'parameters' => ['folioUser'], 'bindings' => [ - 'user' => 'uuid', + 'folioUser' => 'uuid', ], 'middleware' => ['web'], ], (new Ziggy)->toArray()['routes']['users.show']); $this->assertSame([ - 'uri' => 'tags/{tag}', + 'uri' => 'tags/{folioTag}', 'methods' => ['GET'], - 'parameters' => ['tag'], + 'parameters' => ['folioTag'], 'bindings' => [ - 'tag' => 'id', + 'folioTag' => 'id', ], 'middleware' => ['web'], ], (new Ziggy)->toArray()['routes']['tags.show']); - $this->assertTrue(User::$wasBooted); - $this->assertFalse(Tag::$wasBooted); + $this->assertTrue(FolioUser::$wasBooted); + $this->assertFalse(FolioTag::$wasBooted); } } -class User extends Model +class FolioUser extends Model { public static $wasBooted = false; @@ -338,7 +338,7 @@ public function getRouteKeyName() } } -class Tag extends Model +class FolioTag extends Model { public static $wasBooted = false; From 6148acf0d37024bec5eafe9ccd1231a546f7dbcd Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Thu, 21 Mar 2024 15:24:41 -0400 Subject: [PATCH 11/15] Wip --- src/Ziggy.php | 103 ++++++++++++++++++++------------------- tests/Unit/FolioTest.php | 19 +------- 2 files changed, 56 insertions(+), 66 deletions(-) diff --git a/src/Ziggy.php b/src/Ziggy.php index 6265aa77..13e0508b 100644 --- a/src/Ziggy.php +++ b/src/Ziggy.php @@ -147,7 +147,7 @@ private function nameKeyedRoutes() $routes->map(function ($route, $name) use ($bindings, $allRoutes) { $allRoutes->put( $name, - collect($route)->only(['uri', 'methods', 'wheres']) + collect($route)->only(['uri', 'methods', 'wheres']) ->put('domain', $route->domain()) ->put('parameters', $route->parameterNames()) ->put('bindings', $bindings[$route->getName()] ?? []) @@ -237,68 +237,73 @@ private function resolveBindings(array $routes): array */ private function folioRoutes(): Collection { - if (app()->has(FolioRoutes::class)) { - $mountPaths = app(FolioManager::class)->mountPaths(); - - // Use already-registered named Folio routes (instead of searching for all relevant view files) to respect route caching - return collect(app(FolioRoutes::class)->routes())->map(function (array $route) use ($mountPaths) { - $uri = rtrim($route['baseUri'], '/') . str_replace($route['mountPath'], '', $route['path']); - $uri = str_replace('.blade.php', '', $uri); + if (! app()->has(FolioRoutes::class)) { + return collect(); + } - $parameters = []; - $bindings = []; + // Use existing named Folio routes (instead of searching view files) to respect route caching + return collect(app(FolioRoutes::class)->routes())->map(function (array $route) { + $uri = rtrim($route['baseUri'], '/') . str_replace([$route['mountPath'], '.blade.php'], '', $route['path']); - $segments = explode('/', $uri); + $segments = explode('/', $uri); + $parameters = []; + $bindings = []; - foreach ($segments as $i => $segment) { - // Folio doesn't support sub-segment parameters - if (Str::startsWith($segment, '[')) { - $param = new PotentiallyBindablePathSegment($segment); + foreach ($segments as $i => $segment) { + // Folio doesn't support sub-segment parameters + if (Str::startsWith($segment, '[')) { + $param = new PotentiallyBindablePathSegment($segment); - $parameters[] = $name = (string) Str::of($param->trimmed())->afterLast('.')->before(':')->before('-')->camel(); - $segments[$i] = "{{$name}}"; + $parameters[] = $name = (string) Str::of($param->trimmed())->afterLast('.')->before(':')->before('-')->camel(); + $segments[$i] = "{{$name}}"; - if ($field = $param->field()) { - $bindings[$name] = $field; - } elseif ($param->bindable()) { - $override = (new ReflectionClass($param->class()))->isInstantiable() && ( - (new ReflectionMethod($param->class(), 'getRouteKeyName'))->class !== Model::class - || (new ReflectionMethod($param->class(), 'getKeyName'))->class !== Model::class - || (new ReflectionProperty($param->class(), 'primaryKey'))->class !== Model::class - ); + if ($field = $param->field()) { + $bindings[$name] = $field; + } elseif ($param->bindable()) { + $override = (new ReflectionClass($param->class()))->isInstantiable() && ( + (new ReflectionMethod($param->class(), 'getRouteKeyName'))->class !== Model::class + || (new ReflectionMethod($param->class(), 'getKeyName'))->class !== Model::class + || (new ReflectionProperty($param->class(), 'primaryKey'))->class !== Model::class + ); - $bindings[$name] = $override ? app($param->class())->getRouteKeyName() : 'id'; - } + $bindings[$name] = $override ? app($param->class())->getRouteKeyName() : 'id'; } } + } - $uri = implode('/', $segments); + $uri = implode('/', $segments); + $uri = str_replace('/index', '', $uri); - $uri = str_replace(['/index', '/index/'], ['', '/'], $uri); + if ($route['domain'] && str_contains($route['domain'], '{')) { + array_unshift($parameters, Str::between($route['domain'], '{', '}')); + } - if ($route['domain'] && str_contains($route['domain'], '{')) { - $parameters = [Str::between($route['domain'], '{', '}'), ...$parameters]; - } + $middleware = []; + if ($ziggyMiddleware = config('ziggy.middleware')) { + $mountPath = Arr::first( + app(FolioManager::class)->mountPaths(), + fn ($mountPath) => $mountPath->path === realpath($route['mountPath']) + ); $matchedView = new MatchedView(realpath($route['path']), [], $route['mountPath']); - $mountPath = Arr::first($mountPaths, fn ($mountPath) => $mountPath->path === realpath($route['mountPath'])); - - return array_filter([ - 'uri' => $uri === '' ? '/' : trim($uri, '/'), - 'methods' => ['GET'], - 'domain' => $route['domain'], - 'parameters' => $parameters, - 'bindings' => $bindings, - 'middleware' => $mountPath->middleware - ->match($matchedView) - ->prepend('web') - ->merge($matchedView->inlineMiddleware()) - ->unique()->values()->all(), - ]); - }); - } + $middleware = $mountPath->middleware + ->match($matchedView) + ->prepend('web') + ->merge($matchedView->inlineMiddleware()) + ->unique() + ->when(is_array($ziggyMiddleware), fn ($middleware) => $middleware->intersect($ziggyMiddleware)) + ->values()->all(); + } - return collect(); + return array_filter([ + 'uri' => $uri === '' ? '/' : trim($uri, '/'), + 'methods' => ['GET'], + 'domain' => $route['domain'], + 'parameters' => $parameters, + 'bindings' => $bindings, + 'middleware' => $middleware, + ]); + }); } } diff --git a/tests/Unit/FolioTest.php b/tests/Unit/FolioTest.php index 2256f95e..6a0980be 100644 --- a/tests/Unit/FolioTest.php +++ b/tests/Unit/FolioTest.php @@ -52,13 +52,11 @@ public function include_folio_routes() 'about' => [ 'uri' => 'about', 'methods' => ['GET'], - 'middleware' => ['web'], ], 'users.show' => [ 'uri' => 'users/{id}', 'methods' => ['GET'], 'parameters' => ['id'], - 'middleware' => ['web'], ], 'laravel-folio' => [ 'uri' => '{fallbackPlaceholder}', @@ -102,13 +100,11 @@ public function parameters() 'uri' => 'users/{id}', 'methods' => ['GET'], 'parameters' => ['id'], - 'middleware' => ['web'], ], (new Ziggy())->toArray()['routes']['users.show']); $this->assertSame([ 'uri' => 'users/{ids}', 'methods' => ['GET'], 'parameters' => ['ids'], - 'middleware' => ['web'], ], (new Ziggy())->toArray()['routes']['users.some']); } @@ -126,7 +122,6 @@ public function domains() 'methods' => ['GET'], 'domain' => '{account}.ziggy.dev', 'parameters' => ['account', 'ids'], - 'middleware' => ['web'], ], ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); } @@ -147,13 +142,11 @@ public function paths_and_uris() 'uri' => '{id}', 'methods' => ['GET'], 'parameters' => ['id'], - 'middleware' => ['web'], ], 'admins.some' => [ 'uri' => 'admin/{ids}', 'methods' => ['GET'], 'parameters' => ['ids'], - 'middleware' => ['web'], ], ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); } @@ -171,12 +164,10 @@ public function index_pages() 'blog.index' => [ 'uri' => 'blog', 'methods' => ['GET'], - 'middleware' => ['web'], ], 'blog.categories.releases.index' => [ 'uri' => 'blog/releases', 'methods' => ['GET'], - 'middleware' => ['web'], ], ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); } @@ -192,6 +183,8 @@ public function middleware() ->uri('admin') ->middleware(['*' => ['auth']]); + config(['ziggy.middleware' => true]); + $this->assertSame([ 'uri' => 'admin', 'methods' => ['GET'], @@ -226,14 +219,12 @@ public function binding_fields() 'bindings' => [ 'post' => 'slug', ], - 'middleware' => ['web'], ], (new Ziggy())->toArray()['routes']['posts.show']); } $this->assertSame([ 'uri' => 'users/{user}', 'methods' => ['GET'], 'parameters' => ['user'], - 'middleware' => ['web'], ], (new Ziggy())->toArray()['routes']['users.show']); $this->assertSame([ 'uri' => 'teams/{team}', @@ -242,7 +233,6 @@ public function binding_fields() 'bindings' => [ 'team' => 'uid', ], - 'middleware' => ['web'], ], (new Ziggy())->toArray()['routes']['teams.show']); } @@ -268,14 +258,12 @@ public function custom_model_paths() 'bindings' => [ 'post' => 'slug', ], - 'middleware' => ['web'], ], (new Ziggy())->toArray()['routes']['posts.show']); } $this->assertSame([ 'uri' => 'users/{user}', 'methods' => ['GET'], 'parameters' => ['user'], - 'middleware' => ['web'], ], (new Ziggy())->toArray()['routes']['users.show']); $this->assertSame([ 'uri' => 'teams/{team}', @@ -284,7 +272,6 @@ public function custom_model_paths() 'bindings' => [ 'team' => 'uid', ], - 'middleware' => ['web'], ], (new Ziggy())->toArray()['routes']['teams.show']); } @@ -305,7 +292,6 @@ public function implicit_route_model_bindings() 'bindings' => [ 'folioUser' => 'uuid', ], - 'middleware' => ['web'], ], (new Ziggy)->toArray()['routes']['users.show']); $this->assertSame([ 'uri' => 'tags/{folioTag}', @@ -314,7 +300,6 @@ public function implicit_route_model_bindings() 'bindings' => [ 'folioTag' => 'id', ], - 'middleware' => ['web'], ], (new Ziggy)->toArray()['routes']['tags.show']); $this->assertTrue(FolioUser::$wasBooted); From 56da37440250f9d2855c32b78f07966bb2dbb9cb Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Thu, 21 Mar 2024 16:37:18 -0400 Subject: [PATCH 12/15] Wip --- src/Ziggy.php | 7 +- tests/Unit/FolioTest.php | 135 +++++++++++++++++++++++++++++++++++---- 2 files changed, 125 insertions(+), 17 deletions(-) diff --git a/src/Ziggy.php b/src/Ziggy.php index 13e0508b..bc23dcb0 100644 --- a/src/Ziggy.php +++ b/src/Ziggy.php @@ -254,7 +254,7 @@ private function folioRoutes(): Collection if (Str::startsWith($segment, '[')) { $param = new PotentiallyBindablePathSegment($segment); - $parameters[] = $name = (string) Str::of($param->trimmed())->afterLast('.')->before(':')->before('-')->camel(); + $parameters[] = $name = $param->variable(); $segments[$i] = "{{$name}}"; if ($field = $param->field()) { @@ -272,10 +272,11 @@ private function folioRoutes(): Collection } $uri = implode('/', $segments); - $uri = str_replace('/index', '', $uri); + $uri = Str::replaceEnd('/index', '', $uri); if ($route['domain'] && str_contains($route['domain'], '{')) { - array_unshift($parameters, Str::between($route['domain'], '{', '}')); + preg_match_all('/{(.*?)}/', $route['domain'], $matches); + array_unshift($parameters, ...$matches[1]); } $middleware = []; diff --git a/tests/Unit/FolioTest.php b/tests/Unit/FolioTest.php index 6a0980be..291056b1 100644 --- a/tests/Unit/FolioTest.php +++ b/tests/Unit/FolioTest.php @@ -114,14 +114,14 @@ public function domains() File::ensureDirectoryExists(resource_path('views/pages/admin')); File::put(resource_path('views/pages/admin/[...ids].blade.php'), 'path(resource_path('views/pages/admin'))->uri('admin'); + Folio::domain('{account}.{org}.ziggy.dev')->path(resource_path('views/pages/admin'))->uri('admin'); $this->assertSame([ 'admins.some' => [ 'uri' => 'admin/{ids}', 'methods' => ['GET'], - 'domain' => '{account}.ziggy.dev', - 'parameters' => ['account', 'ids'], + 'domain' => '{account}.{org}.ziggy.dev', + 'parameters' => ['account', 'org', 'ids'], ], ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); } @@ -154,24 +154,67 @@ public function paths_and_uris() /** @test */ public function index_pages() { - File::ensureDirectoryExists(resource_path('views/pages/blog/releases')); - File::put(resource_path('views/pages/blog/index.blade.php'), 'assertSame([ - 'blog.index' => [ - 'uri' => 'blog', + 'root' => [ + 'uri' => '/', 'methods' => ['GET'], ], - 'blog.categories.releases.index' => [ - 'uri' => 'blog/releases', + 'index.index' => [ + 'uri' => 'index/index', 'methods' => ['GET'], ], ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); } + /** @test */ + public function nested_pages() + { + File::ensureDirectoryExists(resource_path('views/pages/[slug]')); + File::put(resource_path('views/pages/[slug]/[id].blade.php'), 'assertSame([ + 'nested' => [ + 'uri' => '{slug}/{id}', + 'methods' => ['GET'], + 'parameters' => ['slug', 'id'], + ], + ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); + } + + /** @test */ + public function custom_view_data_variable_names() + { + File::ensureDirectoryExists(resource_path('views/pages/users/[.App.User-$leader]/users')); + File::put(resource_path('views/pages/users/[.App.User-$leader]/users/[.App.User-$follower].blade.php'), 'assertSame([ + 'uri' => 'users/{leader}/users/{follower}', + 'methods' => ['GET'], + 'parameters' => ['leader', 'follower'], + ], (new Ziggy())->toArray()['routes']['follower']); + if (! windows_os()) { + $this->assertSame([ + 'uri' => 'linux-users/{leader}/users/{follower}', + 'methods' => ['GET'], + 'parameters' => ['leader', 'follower'], + ], (new Ziggy())->toArray()['routes']['linux.follower']); + } + } + /** @test */ public function middleware() { @@ -202,7 +245,7 @@ public function binding_fields() { File::ensureDirectoryExists(resource_path('views/pages/users')); File::put(resource_path('views/pages/users/[User].blade.php'), 'assertSame([ 'uri' => 'posts/{post}', 'methods' => ['GET'], @@ -241,7 +284,7 @@ public function custom_model_paths() { File::ensureDirectoryExists(resource_path('views/pages/users')); File::put(resource_path('views/pages/users/[.App.User].blade.php'), 'assertSame([ 'uri' => 'posts/{post}', 'methods' => ['GET'], @@ -305,6 +348,70 @@ public function implicit_route_model_bindings() $this->assertTrue(FolioUser::$wasBooted); $this->assertFalse(FolioTag::$wasBooted); } + + /** @test */ + public function implicit_route_model_bindings_with_custom_variable() + { + File::ensureDirectoryExists(resource_path('views/pages/users')); + File::put(resource_path('views/pages/users/[.Tests.Unit.FolioUser-$user].blade.php'), 'assertSame([ + 'uri' => 'users/{user}', + 'methods' => ['GET'], + 'parameters' => ['user'], + 'bindings' => [ + 'user' => 'uuid', + ], + ], (new Ziggy)->toArray()['routes']['users.show']); + if (! windows_os()) { + $this->assertSame([ + 'uri' => 'tags/{tag}', + 'methods' => ['GET'], + 'parameters' => ['tag'], + 'bindings' => [ + 'tag' => 'id', + ], + ], (new Ziggy)->toArray()['routes']['tags.show']); + } + } + + /** @test */ + public function model_bindings_with_both_custom_field_and_custom_variable() + { + File::ensureDirectoryExists(resource_path('views/pages/users')); + File::put(resource_path('views/pages/users/[.Tests.Unit.FolioUser:email|user].blade.php'), 'assertSame([ + 'uri' => 'users/{user}', + 'methods' => ['GET'], + 'parameters' => ['user'], + 'bindings' => [ + 'user' => 'email', + ], + ], (new Ziggy)->toArray()['routes']['users.show']); + if (! windows_os()) { + $this->assertSame([ + 'uri' => 'tags/{tag}', + 'methods' => ['GET'], + 'parameters' => ['tag'], + 'bindings' => [ + 'tag' => 'slug', + ], + ], (new Ziggy)->toArray()['routes']['tags.show']); + } + } } class FolioUser extends Model From 60ff5350ed0c6cf3ea4395c46d061d5ea2280cd7 Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Thu, 21 Mar 2024 16:44:42 -0400 Subject: [PATCH 13/15] Fix test --- tests/Unit/FolioTest.php | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tests/Unit/FolioTest.php b/tests/Unit/FolioTest.php index 291056b1..857712a5 100644 --- a/tests/Unit/FolioTest.php +++ b/tests/Unit/FolioTest.php @@ -38,7 +38,7 @@ protected function getPackageProviders($app) } /** @test */ - public function include_folio_routes() + public function include_named_folio_routes() { File::ensureDirectoryExists(resource_path('views/pages')); File::put(resource_path('views/pages/about.blade.php'), 'assertSame([ - 'root' => [ - 'uri' => '/', - 'methods' => ['GET'], - ], - 'index.index' => [ - 'uri' => 'index/index', - 'methods' => ['GET'], - ], - ], Arr::except((new Ziggy())->toArray()['routes'], 'laravel-folio')); + 'uri' => '/', + 'methods' => ['GET'], + ], (new Ziggy())->toArray()['routes']['root']); + $this->assertSame([ + 'uri' => 'index/index', + 'methods' => ['GET'], + ], (new Ziggy())->toArray()['routes']['index.index']); } /** @test */ From ea2d06abde6178b31ea89fc28a82c90db9aacbf0 Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Thu, 21 Mar 2024 16:47:47 -0400 Subject: [PATCH 14/15] Fix test --- tests/Unit/FolioTest.php | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/Unit/FolioTest.php b/tests/Unit/FolioTest.php index 857712a5..664db3aa 100644 --- a/tests/Unit/FolioTest.php +++ b/tests/Unit/FolioTest.php @@ -382,33 +382,33 @@ public function implicit_route_model_bindings_with_custom_variable() /** @test */ public function model_bindings_with_both_custom_field_and_custom_variable() { - File::ensureDirectoryExists(resource_path('views/pages/users')); - File::put(resource_path('views/pages/users/[.Tests.Unit.FolioUser:email|user].blade.php'), 'assertSame([ - 'uri' => 'users/{user}', - 'methods' => ['GET'], - 'parameters' => ['user'], - 'bindings' => [ - 'user' => 'email', - ], - ], (new Ziggy)->toArray()['routes']['users.show']); if (! windows_os()) { $this->assertSame([ - 'uri' => 'tags/{tag}', + 'uri' => 'users/{user}', 'methods' => ['GET'], - 'parameters' => ['tag'], + 'parameters' => ['user'], 'bindings' => [ - 'tag' => 'slug', + 'user' => 'email', ], - ], (new Ziggy)->toArray()['routes']['tags.show']); + ], (new Ziggy)->toArray()['routes']['users.show']); } + $this->assertSame([ + 'uri' => 'tags/{tag}', + 'methods' => ['GET'], + 'parameters' => ['tag'], + 'bindings' => [ + 'tag' => 'slug', + ], + ], (new Ziggy)->toArray()['routes']['tags.show']); } } From bbcc2bbb1c24a3d7b19f6822ce6a2acde54c162c Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Thu, 16 May 2024 14:32:28 -0400 Subject: [PATCH 15/15] Wip --- src/Ziggy.php | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Ziggy.php b/src/Ziggy.php index bc23dcb0..247029e4 100644 --- a/src/Ziggy.php +++ b/src/Ziggy.php @@ -142,10 +142,8 @@ private function nameKeyedRoutes() $routes->put($name, $route); }); - $allRoutes = $this->folioRoutes(); - - $routes->map(function ($route, $name) use ($bindings, $allRoutes) { - $allRoutes->put( + return tap($this->folioRoutes(), fn ($all) => $routes->each( + fn ($route, $name) => $all->put( $name, collect($route)->only(['uri', 'methods', 'wheres']) ->put('domain', $route->domain()) @@ -159,10 +157,8 @@ private function nameKeyedRoutes() return $collection->put('middleware', $route->middleware()); }) ->filter() - ); - }); - - return $allRoutes; + ) + )); } /**