diff --git a/config/services/controller.xml b/config/services/controller.xml
index ea545f6b..f05371e4 100644
--- a/config/services/controller.xml
+++ b/config/services/controller.xml
@@ -23,6 +23,17 @@
%bitbag_es_shop_product_price_property_prefix%
+
+
+
+
+
+ %bitbag_es_shop_product_sold_units%
+ %bitbag_es_shop_product_created_at%
+ %bitbag_es_shop_product_price_property_prefix%
+ %bitbag_es_shop_taxon_position_property_prefix%
+
+
@@ -30,7 +41,7 @@
-
+
diff --git a/config/twig/bitbag_twig_hooks.yml b/config/twig/bitbag_twig_hooks.yml
index 364337e7..c26d17c1 100644
--- a/config/twig/bitbag_twig_hooks.yml
+++ b/config/twig/bitbag_twig_hooks.yml
@@ -167,6 +167,13 @@ sylius_twig_hooks:
template: '@SyliusShop/product/index/content/body/main/filters/controls/sorting/menu.html.twig'
priority: 0
'bitbag.sylius_elasticsearch_plugin.taxon_products_search.index.content.body.main.filters.controls.sorting.menu':
+ position:
+ template: '@BitBagSyliusElasticsearchPlugin/Shop/TaxonProductsSearch/content/body/main/sorting/item.html.twig'
+ configuration:
+ title: 'bitbag_sylius_elasticsearch_plugin.ui.position'
+ order_by: 'taxon_position'
+ sort: 'asc'
+ priority: 700
bestsellers:
template: '@BitBagSyliusElasticsearchPlugin/Shop/TaxonProductsSearch/content/body/main/sorting/item.html.twig'
configuration:
diff --git a/spec/Controller/RequestDataHandler/TaxonProductsSortDataHandlerSpec.php b/spec/Controller/RequestDataHandler/TaxonProductsSortDataHandlerSpec.php
new file mode 100644
index 00000000..5e3d079a
--- /dev/null
+++ b/spec/Controller/RequestDataHandler/TaxonProductsSortDataHandlerSpec.php
@@ -0,0 +1,127 @@
+beConstructedWith(
+ $channelPricingNameResolver,
+ $channelContext,
+ $taxonContext,
+ $taxonPositionNameResolver,
+ 'sold_units',
+ 'created_at',
+ 'price',
+ 'taxon_position'
+ );
+ }
+
+ function it_is_initializable(): void
+ {
+ $this->shouldHaveType(TaxonProductsSortDataHandler::class);
+ }
+
+ function it_is_a_shop_products_sort_data_handler(): void
+ {
+ $this->shouldHaveType(ShopProductsSortDataHandler::class);
+ }
+
+ function it_implements_sort_data_handler_interface(): void
+ {
+ $this->shouldHaveType(SortDataHandlerInterface::class);
+ }
+
+ function it_sorts_by_taxon_position_ascending_by_default(
+ TaxonContextInterface $taxonContext,
+ TaxonInterface $taxon,
+ ConcatedNameResolverInterface $taxonPositionNameResolver,
+ ): void {
+ $taxonContext->getTaxon()->willReturn($taxon);
+ $taxon->getCode()->willReturn('t_shirts');
+ $taxonPositionNameResolver->resolvePropertyName('t_shirts')->willReturn('taxon_position_t_shirts');
+
+ $this->retrieveData([])->shouldBeEqualTo([
+ 'sort' => [
+ 'taxon_position_t_shirts' => [
+ 'order' => SortDataHandlerInterface::SORT_ASC_INDEX,
+ 'unmapped_type' => 'keyword',
+ ],
+ ],
+ ]);
+ }
+
+ function it_resolves_the_taxon_position_field_for_the_current_taxon(
+ TaxonContextInterface $taxonContext,
+ TaxonInterface $taxon,
+ ConcatedNameResolverInterface $taxonPositionNameResolver,
+ ): void {
+ $taxonContext->getTaxon()->willReturn($taxon);
+ $taxon->getCode()->willReturn('mugs');
+ $taxonPositionNameResolver->resolvePropertyName('mugs')->willReturn('taxon_position_mugs');
+
+ $this->retrieveData([
+ 'order_by' => 'taxon_position',
+ 'sort' => 'desc',
+ ])->shouldBeEqualTo([
+ 'sort' => [
+ 'taxon_position_mugs' => [
+ 'order' => SortDataHandlerInterface::SORT_DESC_INDEX,
+ 'unmapped_type' => 'keyword',
+ ],
+ ],
+ ]);
+ }
+
+ function it_still_resolves_the_price_field_per_channel(
+ ChannelContextInterface $channelContext,
+ ChannelInterface $channel,
+ ConcatedNameResolverInterface $channelPricingNameResolver,
+ ): void {
+ $channelContext->getChannel()->willReturn($channel);
+ $channel->getCode()->willReturn('WEB');
+ $channelPricingNameResolver->resolvePropertyName('WEB')->willReturn('price_WEB');
+
+ $this->retrieveData([
+ 'order_by' => 'price',
+ 'sort' => 'asc',
+ ])->shouldBeEqualTo([
+ 'sort' => [
+ 'price_WEB' => [
+ 'order' => SortDataHandlerInterface::SORT_ASC_INDEX,
+ 'unmapped_type' => 'keyword',
+ ],
+ ],
+ ]);
+ }
+
+ function it_throws_an_exception_for_an_unsupported_sorter(): void
+ {
+ $this->shouldThrow(\UnexpectedValueException::class)->during('retrieveData', [
+ ['order_by' => 'unsupported'],
+ ]);
+ }
+}
diff --git a/src/Controller/RequestDataHandler/ShopProductsSortDataHandler.php b/src/Controller/RequestDataHandler/ShopProductsSortDataHandler.php
index 87378153..fdc4d105 100644
--- a/src/Controller/RequestDataHandler/ShopProductsSortDataHandler.php
+++ b/src/Controller/RequestDataHandler/ShopProductsSortDataHandler.php
@@ -16,14 +16,14 @@
use Sylius\Component\Channel\Context\ChannelContextInterface;
use UnexpectedValueException;
-final class ShopProductsSortDataHandler implements SortDataHandlerInterface
+class ShopProductsSortDataHandler implements SortDataHandlerInterface
{
public function __construct(
- private ConcatedNameResolverInterface $channelPricingNameResolver,
- private ChannelContextInterface $channelContext,
- private string $soldUnitsProperty,
- private string $createdAtProperty,
- private string $pricePropertyPrefix
+ protected ConcatedNameResolverInterface $channelPricingNameResolver,
+ protected ChannelContextInterface $channelContext,
+ protected string $soldUnitsProperty,
+ protected string $createdAtProperty,
+ protected string $pricePropertyPrefix
) {
}
@@ -31,24 +31,43 @@ public function retrieveData(array $requestData): array
{
$data = [];
- $orderBy = $requestData[self::ORDER_BY_INDEX] ?? $this->createdAtProperty;
+ $orderBy = $requestData[self::ORDER_BY_INDEX] ?? $this->getDefaultOrderBy();
$sort = $requestData[self::SORT_INDEX] ?? self::SORT_ASC_INDEX;
- $availableSorters = [$this->soldUnitsProperty, $this->createdAtProperty, $this->pricePropertyPrefix];
$availableSorting = [self::SORT_ASC_INDEX, self::SORT_DESC_INDEX];
- if (!in_array($orderBy, $availableSorters, true) || !in_array($sort, $availableSorting, true)) {
+ if (!in_array($orderBy, $this->getAvailableSorters(), true) || !in_array($sort, $availableSorting, true)) {
throw new UnexpectedValueException();
}
+ $orderBy = $this->resolveOrderByProperty($orderBy);
+
+ $data['sort'] = [$orderBy => ['order' => strtolower($sort), 'unmapped_type' => 'keyword']];
+
+ return $data;
+ }
+
+ protected function getDefaultOrderBy(): string
+ {
+ return $this->createdAtProperty;
+ }
+
+ /**
+ * @return string[]
+ */
+ protected function getAvailableSorters(): array
+ {
+ return [$this->soldUnitsProperty, $this->createdAtProperty, $this->pricePropertyPrefix];
+ }
+
+ protected function resolveOrderByProperty(string $orderBy): string
+ {
if ($this->pricePropertyPrefix === $orderBy) {
/** @var string $channelCode */
$channelCode = $this->channelContext->getChannel()->getCode();
$orderBy = $this->channelPricingNameResolver->resolvePropertyName($channelCode);
}
- $data['sort'] = [$orderBy => ['order' => strtolower($sort), 'unmapped_type' => 'keyword']];
-
- return $data;
+ return $orderBy;
}
}
diff --git a/src/Controller/RequestDataHandler/TaxonProductsSortDataHandler.php b/src/Controller/RequestDataHandler/TaxonProductsSortDataHandler.php
new file mode 100644
index 00000000..71350480
--- /dev/null
+++ b/src/Controller/RequestDataHandler/TaxonProductsSortDataHandler.php
@@ -0,0 +1,61 @@
+taxonPositionPropertyPrefix;
+ }
+
+ protected function getAvailableSorters(): array
+ {
+ return array_merge(parent::getAvailableSorters(), [$this->taxonPositionPropertyPrefix]);
+ }
+
+ protected function resolveOrderByProperty(string $orderBy): string
+ {
+ if ($this->taxonPositionPropertyPrefix === $orderBy) {
+ /** @var string $taxonCode */
+ $taxonCode = $this->taxonContext->getTaxon()->getCode();
+
+ return $this->taxonPositionNameResolver->resolvePropertyName($taxonCode);
+ }
+
+ return parent::resolveOrderByProperty($orderBy);
+ }
+}
diff --git a/templates/Shop/TaxonProductsSearch/content/body/main/sorting.html.twig b/templates/Shop/TaxonProductsSearch/content/body/main/sorting.html.twig
index b7e3eee9..9460ae4f 100644
--- a/templates/Shop/TaxonProductsSearch/content/body/main/sorting.html.twig
+++ b/templates/Shop/TaxonProductsSearch/content/body/main/sorting.html.twig
@@ -4,7 +4,9 @@
{% set route_parameters = app.request.query.all|unset_elements(['order_by', 'sort', 'page']) %}
{% if app.request.query.all()['order_by'] is not defined or app.request.query.all()['order_by'] is empty %}
- {% set current_sorting_label = 'bitbag_sylius_elasticsearch_plugin.ui.newest'|trans|lower %}
+ {% set current_sorting_label = 'bitbag_sylius_elasticsearch_plugin.ui.position'|trans|lower %}
+ {% elseif app.request.query.all()['order_by'] == 'taxon_position' %}
+ {% set current_sorting_label = 'bitbag_sylius_elasticsearch_plugin.ui.position'|trans|lower %}
{% elseif app.request.query.all()['order_by'] == 'sold_units'%}
{% set current_sorting_label = 'bitbag_sylius_elasticsearch_plugin.ui.bestsellers'|trans|lower %}
{% elseif app.request.query.all()['order_by'] == 'product_created_at' and app.request.query.all()['sort'] == 'desc'%}
diff --git a/translations/messages.en.yml b/translations/messages.en.yml
index efe67b72..081b4aca 100644
--- a/translations/messages.en.yml
+++ b/translations/messages.en.yml
@@ -5,6 +5,7 @@ bitbag_sylius_elasticsearch_plugin:
filter_results: Filter results
filter: Filter
sort: Sort by
+ position: Position
bestsellers: Bestsellers
newest: Newest
oldest: Oldest