diff --git a/src/Api/Resolver/FacetsResolver.php b/src/Api/Resolver/FacetsResolver.php index abb87c69..dd836f13 100644 --- a/src/Api/Resolver/FacetsResolver.php +++ b/src/Api/Resolver/FacetsResolver.php @@ -33,6 +33,7 @@ public function resolve(array $data): array { $this->autoDiscoverRegistry->autoRegister(); + /** @var Query\BoolQuery $boolQuery */ $boolQuery = $this->queryBuilder->buildQuery($data); $query = new Query($boolQuery); $query->setSize(0); @@ -41,6 +42,15 @@ public function resolve(array $data): array $query->addAggregation($facet->getAggregation()->setName($facetId)); } + foreach ($data['facets'] ?? [] as $facetId => $selectedBuckets) { + if (!$selectedBuckets) { + continue; + } + + $facet = $this->facetRegistry->getFacetById($facetId); + $boolQuery->addFilter($facet->getQuery($selectedBuckets)); + } + $facets = $this->finder->findPaginated($query); $adapter = $facets->getAdapter(); if (!$adapter instanceof FantaPaginatorAdapter) { diff --git a/tests/PHPUnit/Integration/Api/DataFixtures/ORM/test_it_updates_facets.yaml b/tests/PHPUnit/Integration/Api/DataFixtures/ORM/test_it_updates_facets.yaml new file mode 100644 index 00000000..f614a10d --- /dev/null +++ b/tests/PHPUnit/Integration/Api/DataFixtures/ORM/test_it_updates_facets.yaml @@ -0,0 +1,121 @@ +Sylius\Component\Core\Model\Channel: + channel_web: + code: 'WEB' + name: 'Web Channel' + hostname: 'localhost' + description: 'Lorem ipsum' + baseCurrency: '@currency_usd' + defaultLocale: '@locale_en' + locales: ['@locale_en'] + color: 'black' + enabled: true + taxCalculationStrategy: 'order_items_based' + +Sylius\Component\Currency\Model\Currency: + currency_usd: + code: 'USD' + +Sylius\Component\Locale\Model\Locale: + locale_en: + code: 'en_US' + +Sylius\Component\Core\Model\Product: + product_mug: + code: 'MUG' + channels: ['@channel_web'] + currentLocale: 'en_US' + translations: + en_US: '@product_translation_mug' + product_mug2: + code: 'MUG2' + channels: ['@channel_web'] + currentLocale: 'en_US' + translations: + en_US: '@product_translation_mug2' + product_mug3: + code: 'MUG3' + channels: ['@channel_web'] + currentLocale: 'en_US' + translations: + en_US: '@product_translation_mug3' + +Sylius\Component\Core\Model\ProductTranslation: + product_translation_mug: + slug: 'mug' + locale: 'en_US' + name: 'Mug' + description: '' + translatable: '@product_mug' + product_translation_mug2: + slug: 'mug-2' + locale: 'en_US' + name: 'Mug 2' + description: '' + translatable: '@product_mug2' + product_translation_mug3: + slug: 'mug-3' + locale: 'en_US' + name: 'Mug 3' + description: '' + translatable: '@product_mug3' + +Sylius\Component\Product\Model\ProductAttributeTranslation: + attributeTranslation1: + locale: en_US + name: "Product color" + translatable: "@product_attribute_color" + attributeTranslation2: + locale: en_US + name: "Product material" + translatable: "@product_attribute_material" + +Sylius\Component\Product\Model\ProductAttribute: + product_attribute_color: + code: 'color' + type: 'text' + storage_type: 'text' + position: 1 + translatable: 1 + product_attribute_material: + code: 'material' + type: 'text' + storage_type: 'text' + position: 1 + translatable: 1 + +Sylius\Component\Product\Model\ProductAttributeValue: + product_attribute_value_color_1: + product: '@product_mug' + attribute: '@product_attribute_color' + localeCode: 'en_US' + value: 'red' + product_attribute_value_color_2: + product: '@product_mug2' + attribute: '@product_attribute_color' + localeCode: 'en_US' + value: 'blue' + product_attribute_value_color_3: + product: '@product_mug3' + attribute: '@product_attribute_color' + localeCode: 'en_US' + value: 'white' + product_attribute_value_material_1: + product: '@product_mug' + attribute: '@product_attribute_material' + localeCode: 'en_US' + value: 'ceramic' + product_attribute_value_material_2: + product: '@product_mug2' + attribute: '@product_attribute_material' + localeCode: 'en_US' + value: 'ceramic' + +Sylius\Component\Core\Model\Taxon: + mugs: + code: "mugs" + +Sylius\Component\Core\Model\ProductTaxon: + productTaxon1: + product: "@product_mug" + taxon: "@mugs" + position: 0 diff --git a/tests/PHPUnit/Integration/Api/ProductListingTest.php b/tests/PHPUnit/Integration/Api/ProductListingTest.php index 77ecebf0..c096287e 100644 --- a/tests/PHPUnit/Integration/Api/ProductListingTest.php +++ b/tests/PHPUnit/Integration/Api/ProductListingTest.php @@ -71,6 +71,20 @@ public function test_it_finds_products_by_name_and_multiple_facets(): void $this->assertResponse($response, 'test_it_finds_products_by_name_and_multiple_facets', Response::HTTP_OK); } + public function test_it_updates_facets(): void + { + $this->loadFixturesFromFiles(['test_it_updates_facets.yaml']); + $this->populateElasticsearch(); + + $this->client->request( + 'GET', + '/api/v2/shop/products/search?query=mug&facets[color][]=red&facets[material][]=ceramic' + ); + + $response = $this->client->getResponse(); + $this->assertResponse($response, 'test_it_updates_facets', Response::HTTP_OK); + } + private function populateElasticsearch(): void { $process = new Process(['tests/Application/bin/console', 'fos:elastica:populate']); diff --git a/tests/PHPUnit/Integration/Api/Responses/Expected/test_it_updates_facets.json b/tests/PHPUnit/Integration/Api/Responses/Expected/test_it_updates_facets.json new file mode 100644 index 00000000..771e4598 --- /dev/null +++ b/tests/PHPUnit/Integration/Api/Responses/Expected/test_it_updates_facets.json @@ -0,0 +1,64 @@ +{ + "items": [ + { + "productTaxons": [ + "/api/v2/shop/product-taxons/@string@" + ], + "mainTaxon": null, + "averageRating": 0, + "images": [], + "id": "@integer@", + "code": "MUG", + "variants": [], + "options": [], + "associations": [], + "createdAt": "@string@", + "updatedAt": "@string@", + "shortDescription": null, + "reviews": [], + "name": "Mug", + "description": "@string@", + "slug": "mug" + } + ], + "facets": { + "material": { + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + "buckets": [ + { + "key": "ceramic", + "doc_count": 1 + } + ] + }, + "color": { + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + "buckets": [ + { + "key": "red", + "doc_count": 1 + } + ] + }, + "taxon": { + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + "buckets": [ + { + "key": "mugs", + "doc_count": 1 + } + ] + } + }, + "pagination": { + "current_page": 1, + "has_previous_page": false, + "has_next_page": false, + "per_page": 9, + "total_items": 1, + "total_pages": 1 + } +}