diff --git a/src/Entries/Collection.php b/src/Entries/Collection.php index 7836916ad9..cff88d55b8 100644 --- a/src/Entries/Collection.php +++ b/src/Entries/Collection.php @@ -831,7 +831,7 @@ public function taxonomies($taxonomies = null) return Blink::once($key, function () use ($taxonomies) { return collect($taxonomies)->map(function ($taxonomy) { - return Taxonomy::findByHandle($taxonomy); + return Taxonomy::findByHandle($taxonomy)?->collection($this); })->filter(); }); }) diff --git a/src/Taxonomies/LocalizedTerm.php b/src/Taxonomies/LocalizedTerm.php index 86e5488372..3bf2c8cd8a 100644 --- a/src/Taxonomies/LocalizedTerm.php +++ b/src/Taxonomies/LocalizedTerm.php @@ -29,6 +29,7 @@ use Statamic\Facades\Antlers; use Statamic\Facades\Blink; use Statamic\Facades\Site; +use Statamic\Facades\URL; use Statamic\GraphQL\ResolvesValues; use Statamic\Http\Responses\DataResponse; use Statamic\Revisions\Revisable; @@ -346,14 +347,16 @@ public function apiUrl() public function route() { - $route = '/'.str_replace('_', '-', $this->taxonomyHandle()).'/{slug}'; + $taxonomySlug = Str::replace('_', '-', $this->taxonomyHandle()); - if ($this->collection()) { - $collectionUrl = $this->collection()->uri($this->locale()) ?? $this->collection()->handle(); - $route = $collectionUrl.$route; + if (! $this->taxonomy()->isAssignedToCollection()) { + return URL::tidy("/{$taxonomySlug}/{slug}"); } - return $route; + $collectionUri = $this->collection()->uri($this->locale()) + ?? Str::replace('_', '-', $this->collection()->handle()); + + return URL::tidy("/{$collectionUri}/{$taxonomySlug}/{slug}"); } public function routeData() diff --git a/src/Taxonomies/Taxonomy.php b/src/Taxonomies/Taxonomy.php index 8c61204c02..efa80c42ea 100644 --- a/src/Taxonomies/Taxonomy.php +++ b/src/Taxonomies/Taxonomy.php @@ -345,11 +345,16 @@ public function absoluteUrl() public function uri() { - $site = Site::current(); + $taxonomySlug = Str::replace('_', '-', $this->handle); - $prefix = $this->collection() ? $this->collection()->uri($site->handle()) : '/'; + if (! $this->isAssignedToCollection()) { + return URL::tidy("/{$taxonomySlug}"); + } + + $collectionUri = $this->collection()->uri(Site::current()->handle()) + ?? Str::replace('_', '-', $this->collection()->handle()); - return URL::tidy($prefix.str_replace('_', '-', '/'.$this->handle)); + return URL::tidy("/{$collectionUri}/{$taxonomySlug}"); } public function collection($collection = null) @@ -367,6 +372,11 @@ public function collections() })->values(); } + public function isAssignedToCollection() + { + return $this->collections()->contains($this->collection()); + } + public function toResponse($request) { if (! view()->exists($this->template())) { diff --git a/src/Taxonomies/Term.php b/src/Taxonomies/Term.php index 667b9f466e..b826aec4ed 100644 --- a/src/Taxonomies/Term.php +++ b/src/Taxonomies/Term.php @@ -58,7 +58,7 @@ public function taxonomy($taxonomy = null) }) ->getter(function ($taxonomy) { return $taxonomy ? Blink::once("taxonomy-{$taxonomy}", function () use ($taxonomy) { - return Taxonomy::findByHandle($taxonomy); + return Taxonomy::findByHandle($taxonomy)?->collection($this->collection()); }) : null; }) ->args(func_get_args()); diff --git a/tests/Antlers/Runtime/ParserIsolationTest.php b/tests/Antlers/Runtime/ParserIsolationTest.php index fcbcb5a748..5c91f25748 100644 --- a/tests/Antlers/Runtime/ParserIsolationTest.php +++ b/tests/Antlers/Runtime/ParserIsolationTest.php @@ -84,7 +84,7 @@ public function test_parser_isolation_considers_all_options_after_taxonomy() $expected = <<<'EOT' - + diff --git a/tests/Data/Entries/CollectionTest.php b/tests/Data/Entries/CollectionTest.php index a751ec419f..4869231431 100644 --- a/tests/Data/Entries/CollectionTest.php +++ b/tests/Data/Entries/CollectionTest.php @@ -9,6 +9,7 @@ use PHPUnit\Framework\Attributes\Test; use Statamic\Contracts\Data\Augmentable; use Statamic\Contracts\Entries\Entry; +use Statamic\Contracts\Taxonomies\Taxonomy; use Statamic\Entries\Collection; use Statamic\Events\CollectionCreated; use Statamic\Events\CollectionCreating; @@ -431,6 +432,26 @@ public function it_dispatches_an_event_when_getting_entry_blueprint() }); } + #[Test] + public function it_gets_and_sets_taxonomies() + { + Facades\Taxonomy::make('tags')->save(); + Facades\Taxonomy::make('categories')->save(); + Facades\Taxonomy::make('sizes')->save(); + + $collection = Facades\Collection::make('test')->save(); + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $collection->taxonomies()); + $this->assertEquals([], $collection->taxonomies()->all()); + + $return = $collection->taxonomies(['tags', 'categories']); + + $this->assertEquals($collection, $return); + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $taxonomies = $collection->taxonomies()); + $this->assertEveryItemIsInstanceOf(Taxonomy::class, $taxonomies); + $this->assertEquals(['test', 'test'], $taxonomies->map(fn ($taxonomy) => $taxonomy->collection()?->handle())->all()); + $this->assertEquals(['tags', 'categories'], $taxonomies->map->handle()->all()); + } + #[Test] public function it_gets_sort_field_and_direction() { diff --git a/tests/Data/Taxonomies/TaxonomyTest.php b/tests/Data/Taxonomies/TaxonomyTest.php index 7c76a3c91c..408f9a98f6 100644 --- a/tests/Data/Taxonomies/TaxonomyTest.php +++ b/tests/Data/Taxonomies/TaxonomyTest.php @@ -167,20 +167,34 @@ public function it_gets_the_url_when_the_site_is_using_a_subdirectory() } #[Test] - public function it_gets_the_url_with_a_collection() + public function it_gets_the_url_with_a_collection_that_has_a_mount() { $entry = $this->mock(EntryContract::class); $entry->shouldReceive('in')->andReturnSelf(); - $entry->shouldReceive('uri')->andReturn('/blog'); - Entry::shouldReceive('find')->with('blog-page')->andReturn($entry); + $entry->shouldReceive('uri')->andReturn('/blog-articles'); + Entry::shouldReceive('find')->with('blog-articles')->andReturn($entry); - $collection = tap(Collection::make('blog')->mount('blog-page'))->save(); + $taxonomy = tap((new Taxonomy)->handle('tags'))->save(); + $collection = tap(Collection::make('blog')->taxonomies(['tags'])->mount('blog-articles'))->save(); - $taxonomy = (new Taxonomy)->handle('tags')->collection($collection); + $taxonomy = $taxonomy->collection($collection); - $this->assertEquals('/blog/tags', $taxonomy->uri()); - $this->assertEquals('/blog/tags', $taxonomy->url()); - $this->assertEquals('http://localhost/blog/tags', $taxonomy->absoluteUrl()); + $this->assertEquals('/blog-articles/tags', $taxonomy->uri()); + $this->assertEquals('/blog-articles/tags', $taxonomy->url()); + $this->assertEquals('http://localhost/blog-articles/tags', $taxonomy->absoluteUrl()); + } + + #[Test] + public function it_gets_the_url_with_a_collection_that_has_no_mount() + { + $taxonomy = tap((new Taxonomy)->handle('tags'))->save(); + $collection = tap(Collection::make('blog_articles')->taxonomies(['tags']))->save(); + + $taxonomy = $taxonomy->collection($collection); + + $this->assertEquals('/blog-articles/tags', $taxonomy->uri()); + $this->assertEquals('/blog-articles/tags', $taxonomy->url()); + $this->assertEquals('http://localhost/blog-articles/tags', $taxonomy->absoluteUrl()); } #[Test] diff --git a/tests/Data/Taxonomies/TermTest.php b/tests/Data/Taxonomies/TermTest.php index b2352c3bb7..fef59d01b3 100644 --- a/tests/Data/Taxonomies/TermTest.php +++ b/tests/Data/Taxonomies/TermTest.php @@ -74,6 +74,7 @@ public function the_blueprint_is_blinked_when_getting_and_flushed_when_setting() $taxonomy = Mockery::mock(Taxonomy::make('tags')); $taxonomy->shouldReceive('termBlueprint')->with(null, $term)->once()->andReturn('the old blueprint'); $taxonomy->shouldReceive('termBlueprint')->with('new', $term)->once()->andReturn('the new blueprint'); + $taxonomy->shouldReceive('collection')->with(null)->andReturn($taxonomy); Taxonomy::shouldReceive('findByHandle')->with('tags')->andReturn($taxonomy); $this->assertEquals('the old blueprint', $term->blueprint()); diff --git a/tests/Stache/Stores/TaxonomiesStoreTest.php b/tests/Stache/Stores/TaxonomiesStoreTest.php index b457a7cb45..57d046eba5 100644 --- a/tests/Stache/Stores/TaxonomiesStoreTest.php +++ b/tests/Stache/Stores/TaxonomiesStoreTest.php @@ -6,6 +6,7 @@ use Illuminate\Filesystem\Filesystem; use PHPUnit\Framework\Attributes\Test; use Statamic\Contracts\Taxonomies\Taxonomy; +use Statamic\Facades\Collection; use Statamic\Facades\Path; use Statamic\Facades\Taxonomy as TaxonomyAPI; use Statamic\Stache\Stache; @@ -100,6 +101,8 @@ public function it_uses_the_filename_as_the_item_key() #[Test] public function it_saves_to_disk() { + Collection::shouldReceive('all')->andReturn(collect()); + $taxonomy = TaxonomyAPI::make('new'); $this->store->save($taxonomy);