diff --git a/src/Decorator/ProductIndexFieldsProvider.php b/src/Decorator/ProductIndexFieldsProvider.php index 361957f..41ce8ee 100644 --- a/src/Decorator/ProductIndexFieldsProvider.php +++ b/src/Decorator/ProductIndexFieldsProvider.php @@ -14,7 +14,7 @@ namespace Gally\OroPlugin\Decorator; -use Gally\OroPlugin\Engine\SearchEngine; +use Gally\OroPlugin\Search\SearchEngine; use Oro\Bundle\ProductBundle\Search\ProductIndexAttributeProviderInterface; use Oro\Bundle\SearchBundle\Engine\EngineParameters; diff --git a/src/EventListener/WebsiteSearchChildDataIndexerListener.php b/src/Indexer/EventListener/WebsiteSearchChildDataIndexerListener.php similarity index 96% rename from src/EventListener/WebsiteSearchChildDataIndexerListener.php rename to src/Indexer/EventListener/WebsiteSearchChildDataIndexerListener.php index 6a43af4..38d511a 100644 --- a/src/EventListener/WebsiteSearchChildDataIndexerListener.php +++ b/src/Indexer/EventListener/WebsiteSearchChildDataIndexerListener.php @@ -12,11 +12,11 @@ declare(strict_types=1); -namespace Gally\OroPlugin\EventListener; +namespace Gally\OroPlugin\Indexer\EventListener; use Doctrine\ORM\EntityManagerInterface; use Doctrine\Persistence\ManagerRegistry; -use Gally\OroPlugin\Engine\Indexer; +use Gally\OroPlugin\Indexer\Indexer; use Oro\Bundle\ElasticSearchBundle\Engine\ElasticSearch; use Oro\Bundle\LocaleBundle\Entity\Localization; use Oro\Bundle\ProductBundle\Entity\Product; diff --git a/src/EventListener/WebsiteSearchInventoryLevelIndexerListener.php b/src/Indexer/EventListener/WebsiteSearchInventoryLevelIndexerListener.php similarity index 98% rename from src/EventListener/WebsiteSearchInventoryLevelIndexerListener.php rename to src/Indexer/EventListener/WebsiteSearchInventoryLevelIndexerListener.php index 995e080..a144b9b 100644 --- a/src/EventListener/WebsiteSearchInventoryLevelIndexerListener.php +++ b/src/Indexer/EventListener/WebsiteSearchInventoryLevelIndexerListener.php @@ -12,7 +12,7 @@ declare(strict_types=1); -namespace Gally\OroPlugin\EventListener; +namespace Gally\OroPlugin\Indexer\EventListener; use Doctrine\Persistence\ManagerRegistry; use Oro\Bundle\ElasticSearchBundle\Engine\ElasticSearch; diff --git a/src/EventListener/WebsiteSearchWebCatalogIndexerListener.php b/src/Indexer/EventListener/WebsiteSearchWebCatalogIndexerListener.php similarity index 97% rename from src/EventListener/WebsiteSearchWebCatalogIndexerListener.php rename to src/Indexer/EventListener/WebsiteSearchWebCatalogIndexerListener.php index c267690..2c140f6 100644 --- a/src/EventListener/WebsiteSearchWebCatalogIndexerListener.php +++ b/src/Indexer/EventListener/WebsiteSearchWebCatalogIndexerListener.php @@ -12,10 +12,10 @@ declare(strict_types=1); -namespace Gally\OroPlugin\EventListener; +namespace Gally\OroPlugin\Indexer\EventListener; use Doctrine\Persistence\ManagerRegistry; -use Gally\OroPlugin\Engine\Indexer; +use Gally\OroPlugin\Indexer\Indexer; use Oro\Bundle\ElasticSearchBundle\Engine\ElasticSearch; use Oro\Bundle\LocaleBundle\Entity\Localization; use Oro\Bundle\LocaleBundle\Helper\LocalizationHelper; diff --git a/src/Indexer/IndexDataProvider.php b/src/Indexer/IndexDataProvider.php index 5c57455..48c4b6b 100644 --- a/src/Indexer/IndexDataProvider.php +++ b/src/Indexer/IndexDataProvider.php @@ -15,7 +15,6 @@ namespace Gally\OroPlugin\Indexer; use Doctrine\ORM\EntityManagerInterface; -use Gally\OroPlugin\Engine\Indexer; use Gally\OroPlugin\Indexer\Normalizer\AbstractNormalizer; use Oro\Bundle\ConfigBundle\Config\ConfigManager; use Oro\Bundle\EntityBundle\ORM\DoctrineHelper; diff --git a/src/Engine/Indexer.php b/src/Indexer/Indexer.php similarity index 99% rename from src/Engine/Indexer.php rename to src/Indexer/Indexer.php index d345e33..53de608 100644 --- a/src/Engine/Indexer.php +++ b/src/Indexer/Indexer.php @@ -12,7 +12,7 @@ declare(strict_types=1); -namespace Gally\OroPlugin\Engine; +namespace Gally\OroPlugin\Indexer; use Gally\OroPlugin\Indexer\Provider\CatalogProvider; use Gally\OroPlugin\Indexer\Provider\SourceFieldProvider; diff --git a/src/Resources/config/services/indexer.yml b/src/Resources/config/services/indexer.yml index b1e1130..65a67f8 100644 --- a/src/Resources/config/services/indexer.yml +++ b/src/Resources/config/services/indexer.yml @@ -46,7 +46,7 @@ services: tags: - { name: console.command } - Gally\OroPlugin\EventListener\WebsiteSearchWebCatalogIndexerListener: + Gally\OroPlugin\Indexer\EventListener\WebsiteSearchWebCatalogIndexerListener: arguments: - '@oro_website_search.manager.website_context_manager' - '@doctrine' @@ -56,7 +56,7 @@ services: tags: - { name: kernel.event_listener, event: oro_website_search.event.index_entity.contentnode, method: onWebsiteSearchIndex, priority: -255 } - Gally\OroPlugin\EventListener\WebsiteSearchInventoryLevelIndexerListener: + Gally\OroPlugin\Indexer\EventListener\WebsiteSearchInventoryLevelIndexerListener: arguments: - '@doctrine' - '@oro_website_search.engine.parameters' @@ -64,7 +64,7 @@ services: tags: - { name: kernel.event_listener, event: oro_website_search.event.index_entity.product, method: onWebsiteSearchIndex, priority: -255 } - Gally\OroPlugin\EventListener\WebsiteSearchChildDataIndexerListener: + Gally\OroPlugin\Indexer\EventListener\WebsiteSearchChildDataIndexerListener: arguments: - '@doctrine' - '@oro_website_search.engine.parameters' @@ -128,7 +128,7 @@ services: - '%gally_config.attribute_mapping%' - !tagged_iterator { tag: 'gally.indexer_normalizer' } - Gally\OroPlugin\Engine\Indexer: + Gally\OroPlugin\Indexer\Indexer: arguments: - '@oro_entity.doctrine_helper' - '@oro_website_search.provider.search_mapping' diff --git a/src/Resources/config/services/search.yml b/src/Resources/config/services/search.yml index 509feb9..13ae121 100644 --- a/src/Resources/config/services/search.yml +++ b/src/Resources/config/services/search.yml @@ -1,5 +1,5 @@ services: - Gally\OroPlugin\Registry\SearchRegistry: ~ + Gally\OroPlugin\Search\SearchRegistry: ~ Gally\OroPlugin\Search\ContextProvider: arguments: @@ -30,7 +30,7 @@ services: tags: - { name: form.type, alias: gally_search_type_select_filter } - Gally\OroPlugin\Engine\SearchEngine: + Gally\OroPlugin\Search\SearchEngine: arguments: - '@event_dispatcher' - '@Gally\OroPlugin\Resolver\QueryPlaceholderResolver' @@ -39,7 +39,7 @@ services: # - '@oro_website_elastic_search.request_builder.registry' - '@Gally\Sdk\Service\SearchManager' - '@Gally\OroPlugin\Search\GallyRequestBuilder' - - '@Gally\OroPlugin\Registry\SearchRegistry' + - '@Gally\OroPlugin\Search\SearchRegistry' - '%gally_config.attribute_mapping%' calls: - ['setMapper', ['@oro_website_search.engine.mapper']] @@ -50,7 +50,6 @@ services: arguments: - '@oro_website_search.engine.parameters' - '@Gally\Sdk\Service\SearchManager' - - '@Gally\OroPlugin\Registry\SearchRegistry' - - '@oro_entity_extend.enum_type_helper' + - '@Gally\OroPlugin\Search\SearchRegistry' tags: - { name: oro_datagrid.extension } diff --git a/src/Search/ExpressionVisitor.php b/src/Search/ExpressionVisitor.php index 1b31850..b509800 100644 --- a/src/Search/ExpressionVisitor.php +++ b/src/Search/ExpressionVisitor.php @@ -22,6 +22,7 @@ use Gally\Sdk\GraphQl\Request; use Oro\Bundle\ProductBundle\Entity\Product; use Oro\Bundle\SearchBundle\Query\Criteria\Criteria; +use Oro\Bundle\SearchBundle\Query\Query; use Oro\Bundle\VisibilityBundle\Entity\VisibilityResolved\BaseVisibilityResolved; class ExpressionVisitor extends BaseExpressionVisitor @@ -58,26 +59,38 @@ public function walkCompositeExpression(CompositeExpression $expr, bool $isMainQ $filters = []; foreach ($expr->getExpressionList() as $expression) { - $filters[] = $this->dispatch($expression, $isMainQuery); + $filter = $this->dispatch($expression, $isMainQuery); + if ($filter) { + if ($isMainQuery) { + foreach ($filter as $field => $data) { + if (!\array_key_exists($field, $filters)) { + $filters[$field] = $data; + } else { + $filters['boolFilter'] = [ + $type => [ + [$field => $filters[$field]], + [$field => $data], + ], + ]; + } + } + } else { + $filters[] = $filter; + } + } } - $filters = array_values(array_filter($filters)); + $filters = array_filter($filters); return $isMainQuery - ? array_merge(...$filters) + ? $filters : ['boolFilter' => [$type => $filters]]; } public function walkComparison(Comparison $comparison): ?array { - [$type, $field] = Criteria::explodeFieldTypeName($comparison->getField()); - $field = $this->attributeMapping[$field] ?? $field; + [$type, $field] = $this->explodeFieldTypeName($comparison->getField()); $value = $this->dispatch($comparison->getValue()); - $operator = match ($comparison->getOperator()) { - 'IN', 'NOT IN' => Request::FILTER_OPERATOR_IN, - 'LIKE', 'NOT LIKE' => Request::FILTER_OPERATOR_MATCH, - 'EXISTS', 'NOT EXISTS' => Request::FILTER_OPERATOR_EXISTS, - default => Request::FILTER_OPERATOR_EQ, - }; + $operator = $this->getGallyOperator($comparison->getOperator()); $hasNegation = str_starts_with($comparison->getOperator(), 'NOT'); if ('all_text' === $field) { @@ -88,13 +101,13 @@ public function walkComparison(Comparison $comparison): ?array if ('id' === $field) { $type = 'text'; - } elseif ('inv_status' === $field) { - $field = 'stock.status'; + } elseif ('inv_status' === $field || 'stock__status' === $field) { if (\count($value) > 1) { - return null; // if we want in stock and out of sotck product, we do not need this filter. + return null; // if we want in stock and out of stock product, we do not need this filter. } - $operator = Request::FILTER_OPERATOR_EQ; - $value = \in_array(Product::INVENTORY_STATUS_IN_STOCK, $value, true); + $type = 'bool'; + $field = 'stock__status'; + $value = \in_array(Product::INVENTORY_STATUS_IN_STOCK, $value, true) || \in_array(true, $value, true); } elseif (str_starts_with($field, 'assigned_to.') || str_starts_with($field, 'manually_added_to.')) { [$field, $variantId] = explode('.', $field); [$_, $value] = explode('_', $variantId); @@ -102,6 +115,14 @@ public function walkComparison(Comparison $comparison): ?array [$field, $value] = explode('.', $field); $type = 'text'; $operator = Request::FILTER_OPERATOR_IN; + } elseif ('category__id' === $field && Request::FILTER_OPERATOR_IN === $operator) { + // Category filter do not support in operator + $value = array_map( + fn ($value) => [$field => [Request::FILTER_OPERATOR_EQ => $value]], + $value + ); + $field = 'boolFilter'; + $operator = '_should'; } elseif (str_starts_with($field, 'visibility_customer.')) { [$field, $customerId] = explode('.', $field); $type = 'text'; @@ -120,6 +141,16 @@ public function walkComparison(Comparison $comparison): ?array } } + if ('bool' === $type) { + if (\is_array($value) && \count($value) > 1) { + $operator = Request::FILTER_OPERATOR_EXISTS; + $value = true; + } else { + $operator = Request::FILTER_OPERATOR_EQ; + $value = \is_array($value) ? reset($value) : $value; + } + } + $rule = [$field => [$operator => $this->enforceValueType($type, $value)]]; return $hasNegation @@ -137,6 +168,36 @@ public function getSearchQuery(): ?string return $this->searchQuery; } + /** + * @return array [string, string] + */ + private function explodeFieldTypeName(string $field): array + { + [$type, $field] = Criteria::explodeFieldTypeName($field); + if (str_contains($field, '.')) { + $parts = explode('.', $field, 2); + if ('bool' === $parts[0]) { + [$type, $field] = $parts; + } + } + + return [$type, $this->attributeMapping[$field] ?? $field]; + } + + private function getGallyOperator(string $operator): string + { + return match ($operator) { + 'IN', 'NOT IN' => Request::FILTER_OPERATOR_IN, + 'LIKE', 'NOT LIKE' => Request::FILTER_OPERATOR_MATCH, + 'EXISTS', 'NOT EXISTS' => Request::FILTER_OPERATOR_EXISTS, + '>' => Request::FILTER_OPERATOR_GT, + '>=' => Request::FILTER_OPERATOR_GTE, + '<' => Request::FILTER_OPERATOR_LT, + '<=' => Request::FILTER_OPERATOR_LTE, + default => Request::FILTER_OPERATOR_EQ, + }; + } + private function enforceValueType(string $type, mixed $value): mixed { if (\is_array($value)) { diff --git a/src/Search/Extension/GallyDataGridExtension.php b/src/Search/Extension/GallyDataGridExtension.php index 22b953c..71b9e93 100644 --- a/src/Search/Extension/GallyDataGridExtension.php +++ b/src/Search/Extension/GallyDataGridExtension.php @@ -14,8 +14,8 @@ namespace Gally\OroPlugin\Search\Extension; -use Gally\OroPlugin\Engine\SearchEngine; -use Gally\OroPlugin\Registry\SearchRegistry; +use Gally\OroPlugin\Search\SearchEngine; +use Gally\OroPlugin\Search\SearchRegistry; use Gally\Sdk\Entity\Metadata; use Gally\Sdk\Entity\SourceField; use Gally\Sdk\GraphQl\Request; @@ -26,8 +26,6 @@ use Oro\Bundle\DataGridBundle\Datasource\DatasourceInterface; use Oro\Bundle\DataGridBundle\Extension\AbstractExtension; use Oro\Bundle\DataGridBundle\Extension\Sorter\Configuration; -use Oro\Bundle\EntityExtendBundle\Form\Util\EnumTypeHelper; -use Oro\Bundle\ProductBundle\Entity\Product; use Oro\Bundle\SearchBundle\Engine\EngineParameters; /** @@ -39,7 +37,6 @@ public function __construct( private EngineParameters $engineParameters, private SearchManager $searchManager, private SearchRegistry $registry, - private EnumTypeHelper $enumTypeHelper, ) { } @@ -58,7 +55,7 @@ public function visitDatasource(DatagridConfiguration $config, DatasourceInterfa public function visitMetadata(DatagridConfiguration $config, MetadataObject $object): void { - $this->addFiltersFromGallyResult($config, $object); + $this->addFiltersFromGallyResult($config); $this->setAppliedSortingFromGallyResult($config); } @@ -69,7 +66,7 @@ public function getPriority(): int private function addFilterFieldsFromGallyConfiguration(DatagridConfiguration $config): void { - $filterableSourceField = $this->searchManager->getFilterableSourceField(new Metadata('product')); // todo get entity from context & cache this ! + $filterableSourceField = $this->searchManager->getFilterableSourceField(new Metadata('product')); $filters = $config->offsetGetByPath('[filters][columns]'); $proceed = []; @@ -80,35 +77,46 @@ private function addFilterFieldsFromGallyConfiguration(DatagridConfiguration $co foreach ($filterableSourceField as $sourceField) { if (!\in_array($sourceField->getCode(), $proceed, true)) { + $fieldName = $sourceField->getCode(); + $type = null; $filter = [ - 'data_name' => $sourceField->getCode(), 'label' => $sourceField->getDefaultLabel(), + 'type' => 'gally-select', 'visible' => false, 'disabled' => false, 'renderable' => true, - // 'multiple' => false, - // 'expanded' => false, - // 'choices' => [], ]; // @see \Gally\Search\Decoration\GraphQl\AddAggregationsData::formatAggregation - $filter['type'] = match ($sourceField->getType()) { - SourceField::TYPE_PRICE => 'frontend-product-price', - // SourceField::TYPE_FLOAT, SourceField::TYPE_INT => self::AGGREGATION_TYPE_SLIDER, - // SourceField::TYPE_CATEGORY => self::AGGREGATION_TYPE_CATEGORY, - // SourceField::TYPE_STOCK, SourceField::TYPE_BOOLEAN => self::AGGREGATION_TYPE_BOOLEAN, - // SourceField::TYPE_DATE => self::AGGREGATION_TYPE_DATE_HISTOGRAM, - // SourceField::TYPE_LOCATION => self::AGGREGATION_TYPE_HISTOGRAM, - default => 'gally-select', - }; - - if (SourceField::TYPE_SELECT === $sourceField->getType()) { - $filter['data_name'] .= '__value'; - $enumCode = $this->enumTypeHelper->getEnumCode(Product::class, $sourceField->getCode()); - // $filter['enum_code'] = $enumCode; + switch ($sourceField->getType()) { + case SourceField::TYPE_CATEGORY: + $fieldName .= '__id'; + $filter['type'] = 'gally-select'; + break; + case SourceField::TYPE_PRICE: + $fieldName .= '__price'; + $filter['type'] = 'frontend-product-price'; + break; + case SourceField::TYPE_SELECT: + $fieldName .= '__value'; + $filter['type'] = 'gally-select'; + break; + case SourceField::TYPE_STOCK: + $fieldName .= '__status'; + $filter['type'] = 'boolean'; + break; + case SourceField::TYPE_FLOAT: + case SourceField::TYPE_INT: + $filter['type'] = 'number-range'; + break; + case SourceField::TYPE_BOOLEAN: + $type = 'bool'; + $filter['type'] = 'boolean'; + break; } - $filters[$filter['data_name']] = $filter; + $filter['data_name'] = $type ? "$type.$fieldName" : $fieldName; + $filters[$fieldName] = $filter; } } @@ -165,23 +173,18 @@ private function addSortFieldsFromGallyConfiguration(DatagridConfiguration $conf $config->offsetSetByPath(Configuration::DISABLE_DEFAULT_SORTING_PATH, false); } - private function addFiltersFromGallyResult(DatagridConfiguration $config, MetadataObject $object): void + private function addFiltersFromGallyResult(DatagridConfiguration $config): void { $gallyFilters = $this->registry->getResponse()->getAggregations(); $currentFilters = $config->offsetGetByPath('[filters][columns]') ?? []; $filters = []; - // current : all_text, sku, names, brand, minimal_price, - - foreach ($currentFilters as $filter) { - $name = $filter['data_name']; - // Todo check if we should keep these default filters - if (\in_array($name, ['all_text_LOCALIZATION_ID', 'sku', 'names'], true)) { - $filters[] = $filter; + foreach ($currentFilters as $code => $filter) { + if (\in_array($code, ['sku', 'names'], true)) { + $filters[$code] = $filter; } } - // Todo Iterate over current filter to get base array ! foreach ($gallyFilters as $gallyFilter) { $filter = [ 'data_name' => $gallyFilter['field'], @@ -189,159 +192,22 @@ private function addFiltersFromGallyResult(DatagridConfiguration $config, Metada 'visible' => true, 'disabled' => false, 'renderable' => true, - // 'multiple' => true, - // 'expanded' => true, ]; - if (Response::FILTER_TYPE_CHECKBOX === $gallyFilter['type']) { + + if (Response::FILTER_TYPE_SLIDER === $gallyFilter['type']) { + $filter['type'] = 'price__price' === $gallyFilter['field'] ? 'frontend-product-price' : 'number-range'; + $filters[$gallyFilter['field']] = $filter; + } elseif (Response::FILTER_TYPE_BOOLEAN === $gallyFilter['type']) { + $filter['type'] = 'boolean'; + $filters[$gallyFilter['field']] = $filter; + } else { $filter['choices'] = $gallyFilter['options']; $filter['options']['gally_options'] = $gallyFilter['options']; $filter['type'] = 'gally-select'; $filters[$gallyFilter['field']] = $filter; - // "field_options": { - // "type": "ref-one" - // }, - // "type": "multichoice", - // "force_like": true, - // "translatable": true, - // "case_insensitive": true, - // "min_length": 0, - // "max_length": 9223372036854775807, - // "order": 4, - // "lazy": false, - // "populateDefault": false, - // "cacheId": null - } elseif (Response::FILTER_TYPE_SLIDER === $gallyFilter['type']) { - $filter['type'] = 'frontend-product-price'; - $filters[$gallyFilter['field']] = $filter; - // "choices": [ - // { - // "label": "between", - // "value": "7", - // "data": 7, - // "attr": [], - // "labelTranslationParameters": [] - // }, - // { - // "label": "equals", - // "value": "3", - // "data": 3, - // "attr": [], - // "labelTranslationParameters": [] - // }, - // { - // "label": "more than", - // "value": "2", - // "data": 2, - // "attr": [], - // "labelTranslationParameters": [] - // }, - // { - // "label": "less than", - // "value": "6", - // "data": 6, - // "attr": [], - // "labelTranslationParameters": [] - // }, - // { - // "label": "equals or more than", - // "value": "1", - // "data": 1, - // "attr": [], - // "labelTranslationParameters": [] - // }, - // { - // "label": "equals or less than", - // "value": "5", - // "data": 5, - // "attr": [], - // "labelTranslationParameters": [] - // } - // ], - // "type": "frontend-product-price", - // "translatable": true, - // "force_like": false, - // "case_insensitive": true, - // "min_length": 0, - // "max_length": 9223372036854775807, - // "order": 5, - // "lazy": false, - // "formatterOptions": { - // "grouping": true, - // "orderSeparator": ",", - // "decimalSeparator": "." - // }, - // "arraySeparator": ",", - // "arrayOperators": [ - // 9, - // 10 - // ], - // "dataType": "data_decimal", - // "unitChoices": [ - // { - // "data": "each", - // "value": "each", - // "label": "each", - // "shortLabel": "ea" - // }, - // { - // "data": "hour", - // "value": "hour", - // "label": "hour", - // "shortLabel": "hr" - // }, - // { - // "data": "item", - // "value": "item", - // "label": "item", - // "shortLabel": "item" - // }, - // { - // "data": "kg", - // "value": "kg", - // "label": "kilogram", - // "shortLabel": "kg" - // }, - // { - // "data": "piece", - // "value": "piece", - // "label": "piece", - // "shortLabel": "pc" - // }, - // { - // "data": "set", - // "value": "set", - // "label": "set", - // "shortLabel": "set" - // } - // ], - // "cacheId": null - } else { - // Todo boolean - $toto = 'blop'; } } - // $choices = $object->offsetGetByPath('[filters][0][choices]'); - // $object->offsetAddToArrayByPath( - // '[filters]', - // [ - // [ - // 'name' => 'test_color', - // 'label' => 'Cumtom filter', - // 'choices' => $choices, - // 'type' => 'string', - // 'max_length' => 255, - // 'translatable' => true, - // 'force_like' => false, - // 'case_insensitive' => true, - // 'min_length' => 0, - // 'order' => 1, - // 'lazy' => false, - // 'cacheId' => null, - // ] - // ] - // ); - $config->offsetSetByPath('[filters][columns]', $filters); } diff --git a/src/Search/Filter/Form/CategoryFilter.php b/src/Search/Filter/Form/CategoryFilter.php new file mode 100644 index 0000000..d2ac693 --- /dev/null +++ b/src/Search/Filter/Form/CategoryFilter.php @@ -0,0 +1,81 @@ + + * @copyright 2024-present Smile + * @license Open Software License v. 3.0 (OSL-3.0) + */ + +declare(strict_types=1); + +namespace Gally\OroPlugin\Search\Filter\Form; + +use Oro\Bundle\FilterBundle\Datasource\FilterDatasourceAdapterInterface; +use Oro\Bundle\FilterBundle\Filter\BaseMultiChoiceFilter; +use Oro\Bundle\FilterBundle\Filter\FilterUtility; +use Oro\Bundle\SearchBundle\Datagrid\Filter\Adapter\SearchFilterDatasourceAdapter; +use Oro\Bundle\SearchBundle\Query\Criteria\Criteria; +use Oro\Component\Exception\UnexpectedTypeException; + +/** + * The filter by a multi-enum entity for a datasource based on a search index. + */ +class CategoryFilter extends BaseMultiChoiceFilter +{ + /** + * {@inheritDoc} + */ + public function init($name, array $params) + { + parent::init($name, $params); + + $this->params[FilterUtility::FRONTEND_TYPE_KEY] = 'multiselect'; + } + + /** + * {@inheritDoc} + */ + public function apply(FilterDatasourceAdapterInterface $ds, $data) + { + if (!$ds instanceof SearchFilterDatasourceAdapter) { + throw new UnexpectedTypeException($ds, SearchFilterDatasourceAdapter::class); + } + + return $this->applyRestrictions($ds, $data); + } + + /** + * {@inheritDoc} + */ + public function prepareData(array $data): array + { + throw new \BadMethodCallException('Not implemented'); + } + + /** + * {@inheritDoc} + */ + protected function applyRestrictions(FilterDatasourceAdapterInterface $ds, array $data): bool + { + $fieldName = $this->get(FilterUtility::DATA_NAME_KEY); + $criteria = Criteria::create(); + $builder = Criteria::expr(); + + $criteria->where($builder->in($fieldName, $data['value'])); + $ds->addRestriction($criteria->getWhereExpression(), FilterUtility::CONDITION_AND); + + return true; + } + + /** + * {@inheritDoc} + */ + protected function getFormType(): string + { + return SelectFormFilter::class; + } +} diff --git a/src/Engine/SearchEngine.php b/src/Search/SearchEngine.php similarity index 95% rename from src/Engine/SearchEngine.php rename to src/Search/SearchEngine.php index 677280b..20bc89a 100644 --- a/src/Engine/SearchEngine.php +++ b/src/Search/SearchEngine.php @@ -12,10 +12,8 @@ declare(strict_types=1); -namespace Gally\OroPlugin\Engine; +namespace Gally\OroPlugin\Search; -use Gally\OroPlugin\Registry\SearchRegistry; -use Gally\OroPlugin\Search\GallyRequestBuilder; use Gally\Sdk\Service\SearchManager; use Oro\Bundle\SearchBundle\Provider\AbstractSearchMappingProvider; use Oro\Bundle\SearchBundle\Query\Query; diff --git a/src/Registry/SearchRegistry.php b/src/Search/SearchRegistry.php similarity index 94% rename from src/Registry/SearchRegistry.php rename to src/Search/SearchRegistry.php index 5b12bab..74e3e1b 100644 --- a/src/Registry/SearchRegistry.php +++ b/src/Search/SearchRegistry.php @@ -12,7 +12,7 @@ declare(strict_types=1); -namespace Gally\OroPlugin\Registry; +namespace Gally\OroPlugin\Search; use Gally\Sdk\GraphQl\Response; diff --git a/src/Voter/ElasticSearchEngineFeatureVoter.php b/src/Voter/ElasticSearchEngineFeatureVoter.php index 61f1bfd..84a7dd5 100644 --- a/src/Voter/ElasticSearchEngineFeatureVoter.php +++ b/src/Voter/ElasticSearchEngineFeatureVoter.php @@ -14,7 +14,7 @@ namespace Gally\OroPlugin\Voter; -use Gally\OroPlugin\Engine\SearchEngine; +use Gally\OroPlugin\Search\SearchEngine; use Oro\Bundle\FeatureToggleBundle\Checker\Voter\VoterInterface; use Oro\Bundle\SearchBundle\Engine\EngineParameters;