Skip to content

Commit

Permalink
Fix filtering taxonomy terms by collection (#3870)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonvarga authored Jun 17, 2021
1 parent b3e27f4 commit e70f518
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/Stache/Indexes/Terms/Associations.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public function getItems()
'value' => $value,
'slug' => Str::slug($value),
'entry' => $entry->id(),
'collection' => $entry->collectionHandle(),
'site' => $entry->locale(),
];
});
Expand Down
16 changes: 16 additions & 0 deletions src/Stache/Query/TermQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ protected function getFilteredKeys()
? Facades\Taxonomy::handles()
: $this->taxonomies;

if ($this->collections) {
$this->filterUsagesWithinCollections($taxonomies);
}

$keys = empty($this->wheres)
? $this->getKeysFromTaxonomies($taxonomies)
: $this->getKeysFromTaxonomiesWithWheres($taxonomies, $this->wheres);
Expand Down Expand Up @@ -143,4 +147,16 @@ public function get($columns = ['*'])

return $items;
}

private function filterUsagesWithinCollections($taxonomies)
{
$this->whereIn('id', collect($taxonomies)->flatMap(function ($taxonomy) {
return $this->store->store($taxonomy)
->index('associations')
->items()->whereIn('collection', $this->collections)
->map(function ($item) use ($taxonomy) {
return $taxonomy.'::'.$item['slug'];
});
})->all());
}
}
1 change: 1 addition & 0 deletions src/Stache/Stores/TaxonomyTermsStore.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ public function sync($entry, $terms)
'value' => $value,
'slug' => $slug,
'entry' => $entry->id(),
'collection' => $entry->collectionHandle(),
'site' => $entry->locale(),
]);
}
Expand Down
137 changes: 137 additions & 0 deletions tests/Data/Taxonomies/TermQueryBuilderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<?php

namespace Tests\Data\Taxonomies;

use Facades\Tests\Factories\EntryFactory;
use Statamic\Facades\Collection;
use Statamic\Facades\Taxonomy;
use Statamic\Facades\Term;
use Statamic\Taxonomies\LocalizedTerm;
use Statamic\Taxonomies\TermCollection;
use Tests\PreventSavingStacheItemsToDisk;
use Tests\TestCase;

class TermQueryBuilderTest extends TestCase
{
use PreventSavingStacheItemsToDisk;

/** @test */
public function it_gets_terms()
{
Taxonomy::make('tags')->save();
Term::make('a')->taxonomy('tags')->data([])->save();
Term::make('b')->taxonomy('tags')->data([])->save();
Term::make('c')->taxonomy('tags')->data([])->save();

$terms = Term::query()->get();
$this->assertInstanceOf(TermCollection::class, $terms);
$this->assertEveryItemIsInstanceOf(LocalizedTerm::class, $terms);
}

/** @test */
public function it_filters_using_wheres()
{
Taxonomy::make('tags')->save();
Term::make('a')->taxonomy('tags')->data(['test' => 'foo'])->save();
Term::make('b')->taxonomy('tags')->data(['test' => 'bar'])->save();
Term::make('c')->taxonomy('tags')->data(['test' => 'foo'])->save();

$terms = Term::query()->where('test', 'foo')->get();
$this->assertEquals(['a', 'c'], $terms->map->slug()->sort()->values()->all());
}

/** @test */
public function it_filters_by_taxonomy()
{
Taxonomy::make('tags')->save();
Taxonomy::make('categories')->save();
Taxonomy::make('colors')->save();
Term::make('a')->taxonomy('tags')->data([])->save();
Term::make('b')->taxonomy('categories')->data([])->save();
Term::make('c')->taxonomy('colors')->data([])->save();
Term::make('d')->taxonomy('tags')->data([])->save();

$terms = Term::query()->where('taxonomy', 'tags')->get();
$this->assertEquals(['a', 'd'], $terms->map->slug()->sort()->values()->all());

$terms = Term::query()->whereIn('taxonomy', ['tags', 'categories'])->get();
$this->assertEquals(['a', 'b', 'd'], $terms->map->slug()->sort()->values()->all());
}

/** @test */
public function it_sorts()
{
Taxonomy::make('tags')->save();
Term::make('a')->taxonomy('tags')->data(['test' => 4])->save();
Term::make('b')->taxonomy('tags')->data(['test' => 2])->save();
Term::make('c')->taxonomy('tags')->data(['test' => 1])->save();
Term::make('d')->taxonomy('tags')->data(['test' => 5])->save();
Term::make('e')->taxonomy('tags')->data(['test' => 3])->save();

$terms = Term::query()->orderBy('test')->get();
$this->assertEquals(['c', 'b', 'e', 'a', 'd'], $terms->map->slug()->all());
}

/** @test */
public function it_filters_usage_in_collections()
{
Taxonomy::make('tags')->save();
Taxonomy::make('cats')->save();

Collection::make('blog')->taxonomies(['tags', 'cats'])->save();
Collection::make('news')->taxonomies(['tags', 'cats'])->save();

EntryFactory::collection('blog')->data(['tags' => ['a'], 'cats' => ['f']])->create();
EntryFactory::collection('blog')->data(['tags' => ['c'], 'cats' => ['g']])->create();
EntryFactory::collection('news')->data(['tags' => ['a'], 'cats' => ['f']])->create();
EntryFactory::collection('news')->data(['tags' => ['b'], 'cats' => ['h']])->create();

Term::make('a')->taxonomy('tags')->data([])->save();
Term::make('b')->taxonomy('tags')->data([])->save();
Term::make('c')->taxonomy('tags')->data([])->save();
Term::make('d')->taxonomy('tags')->data([])->save();
Term::make('e')->taxonomy('cats')->data([])->save();
Term::make('f')->taxonomy('cats')->data([])->save();
Term::make('g')->taxonomy('cats')->data([])->save();
Term::make('h')->taxonomy('cats')->data([])->save();

$this->assertEquals(['cats::f', 'cats::g', 'tags::a', 'tags::c'],
Term::query()
->where('collection', 'blog')
->get()->map->id()->sort()->values()->all()
);

$this->assertEquals(['tags::a', 'tags::c'],
Term::query()
->where('collection', 'blog')
->where('taxonomy', 'tags')
->get()->map->id()->sort()->values()->all()
);

$this->assertEquals(['cats::f', 'cats::h', 'tags::a', 'tags::b'],
Term::query()
->where('collection', 'news')
->get()->map->id()->sort()->values()->all()
);

$this->assertEquals(['tags::a', 'tags::b'],
Term::query()
->where('collection', 'news')
->where('taxonomy', 'tags')
->get()->map->id()->sort()->values()->all()
);

$this->assertEquals(['cats::f', 'cats::g', 'cats::h', 'tags::a', 'tags::b', 'tags::c'],
Term::query()
->whereIn('collection', ['blog', 'news'])
->get()->map->id()->sort()->values()->all()
);

$this->assertEquals(['tags::a', 'tags::b', 'tags::c'],
Term::query()
->whereIn('collection', ['blog', 'news'])
->where('taxonomy', 'tags')
->get()->map->id()->sort()->values()->all()
);
}
}

0 comments on commit e70f518

Please sign in to comment.