Skip to content

Commit

Permalink
Filter datagrid extension by search engine
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreGauthier committed Nov 12, 2024
1 parent bb750b4 commit fc45d60
Show file tree
Hide file tree
Showing 11 changed files with 343 additions and 8 deletions.
7 changes: 5 additions & 2 deletions src/Decorator/ProductIndexFieldsProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@

namespace Gally\OroPlugin\Decorator;

use Gally\OroPlugin\Engine\SearchEngine;
use Oro\Bundle\ProductBundle\Search\ProductIndexAttributeProviderInterface;
use Oro\Bundle\SearchBundle\Engine\EngineParameters;

class ProductIndexFieldsProvider implements ProductIndexAttributeProviderInterface
{
public function __construct(
private ProductIndexAttributeProviderInterface $productIndexAttributeProvider,
private EngineParameters $engineParameters,
) {
}

Expand All @@ -30,7 +33,7 @@ public function addForceIndexed(string $field): void

public function isForceIndexed(string $field): bool
{
// Todo check search engine
return true || $this->productIndexAttributeProvider->isForceIndexed($field);
return SearchEngine::ENGINE_NAME === $this->engineParameters->getEngineName()
|| $this->productIndexAttributeProvider->isForceIndexed($field);
}
}
2 changes: 1 addition & 1 deletion src/Engine/ExpressionVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public function walkComparison(Comparison $comparison): ?array
}

if ('category_path' === $field) {
$this->currentCategoryId = 'node_' . basename(str_replace('_', '/', $value));
// $this->currentCategoryId = 'node_' . basename(str_replace('_', '/', $value)); // todo this is wrong, the current category should contain content node id !

return null;
}
Expand Down
8 changes: 5 additions & 3 deletions src/Engine/SearchEngine.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public function __construct(
private SearchManager $searchManager,
private GallyRequestBuilder $requestBuilder,
private SearchRegistry $registry,
private array $attributeMapping,
) {
parent::__construct($eventDispatcher, $queryPlaceholderResolver, $mappingProvider);
}
Expand All @@ -60,9 +61,10 @@ protected function doSearch(Query $query, array $context = [])
$results = [];
foreach ($response->getCollection() as $item) {
$item['id'] = (int) basename($item['id']);
$item['system_entity_id'] = $item['id']; // todo manage attributes
$item['names'] = $item['name'];
$item['descriptions'] = $item['description'] ?? '';

foreach ($this->attributeMapping as $oroAttribute => $gallyAttribute) {
$item[$oroAttribute] = $item[$gallyAttribute] ?? null;
}

$results[] = new Item(
'product', // Todo manage other entity
Expand Down
7 changes: 5 additions & 2 deletions src/Extension/GallyDataGridExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

namespace Gally\OroPlugin\Extension;

use Gally\OroPlugin\Engine\SearchEngine;
use Gally\OroPlugin\Registry\SearchRegistry;
use Gally\Sdk\Entity\Metadata;
use Gally\Sdk\Entity\SourceField;
Expand All @@ -25,13 +26,15 @@
use Oro\Bundle\DataGridBundle\Extension\AbstractExtension;
use Oro\Bundle\EntityExtendBundle\Form\Util\EnumTypeHelper;
use Oro\Bundle\ProductBundle\Entity\Product;
use Oro\Bundle\SearchBundle\Engine\EngineParameters;

/**
* Adapt data grid for result managed by Gally.
*/
class GallyDataGridExtension extends AbstractExtension
{
public function __construct(
private EngineParameters $engineParameters,
private SearchManager $searchManager,
private SearchRegistry $registry,
private EnumTypeHelper $enumTypeHelper,
Expand All @@ -40,8 +43,8 @@ public function __construct(

public function isApplicable(DatagridConfiguration $config): bool
{
// Todo it is gally search engine
return 'frontend-product-search-grid' === $config->getName();
return SearchEngine::ENGINE_NAME === $this->engineParameters->getEngineName()
&& 'frontend-product-search-grid' === $config->getName();
}

public function visitDatasource(DatagridConfiguration $config, DatasourceInterface $datasource)
Expand Down
1 change: 1 addition & 0 deletions src/Resources/config/services/indexer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ services:
decorates: oro_product.provider.index_fields
arguments:
- '@.inner'
- '@oro_website_search.engine.parameters'

Gally\OroPlugin\Indexer\Provider\CatalogProvider:
arguments:
Expand Down
1 change: 1 addition & 0 deletions src/Resources/config/services/sdk.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
services:
Gally\Sdk\Client\Configuration:
factory: ['\Gally\OroPlugin\Factory\ConfigurationFactory', 'create']
lazy: true
arguments:
- '@oro_website_search.engine.parameters'

Expand Down
2 changes: 2 additions & 0 deletions src/Resources/config/services/search.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@ services:
- '@Gally\Sdk\Service\SearchManager'
- '@Gally\OroPlugin\RequestBuilder\GallyRequestBuilder'
- '@Gally\OroPlugin\Registry\SearchRegistry'
- '%gally_config.attribute_mapping%'
calls:
- ['setMapper', ['@oro_website_search.engine.mapper']]
tags:
- { name: 'oro_website_search.engine', engine_name: 'gally' }

Gally\OroPlugin\Extension\GallyDataGridExtension:
arguments:
- '@oro_website_search.engine.parameters'
- '@Gally\Sdk\Service\SearchManager'
- '@Gally\OroPlugin\Registry\SearchRegistry'
- '@oro_entity_extend.enum_type_helper'
Expand Down
59 changes: 59 additions & 0 deletions src/Search/ContextProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php
/**
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Gally to newer versions in the future.
*
* @package Gally
* @author Gally Team <[email protected]>
* @copyright 2024-present Smile
* @license Open Software License v. 3.0 (OSL-3.0)
*/

declare(strict_types=1);

namespace Gally\OroPlugin\Search;

use Gally\OroPlugin\Indexer\Provider\CatalogProvider;
use Gally\Sdk\Entity\LocalizedCatalog;
use Oro\Bundle\CatalogBundle\Handler\RequestProductHandler;
use Oro\Bundle\LocaleBundle\Entity\Localization;
use Oro\Bundle\LocaleBundle\Helper\LocalizationHelper;
use Oro\Bundle\WebCatalogBundle\Entity\ContentNode;
use Oro\Bundle\WebCatalogBundle\Provider\RequestWebContentVariantProvider;
use Oro\Bundle\WebsiteBundle\Entity\Website;
use Oro\Bundle\WebsiteBundle\Manager\WebsiteManager;

class ContextProvider
{
public function __construct(
private WebsiteManager $websiteManager,
private LocalizationHelper $localizationHelper,
private CatalogProvider $catalogProvider,
private RequestWebContentVariantProvider $requestWebContentVariantProvider,
) {
}

public function getCurrentWebsite(): Website
{
return $this->websiteManager->getCurrentWebsite();
}

public function getCurrentLocalization(): Localization
{
return $this->localizationHelper->getCurrentLocalization();
}

public function getCurrentLocalizedCatalog(): LocalizedCatalog
{
return $this->catalogProvider->buildLocalizedCatalog(
$this->getCurrentWebsite(),
$this->getCurrentLocalization(),
);
}

public function getCurrentContentNode(): ?ContentNode
{
return $this->requestWebContentVariantProvider->getContentVariant()?->getNode();
}
}
128 changes: 128 additions & 0 deletions src/Search/ExpressionVisitor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php
/**
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Gally to newer versions in the future.
*
* @package Gally
* @author Gally Team <[email protected]>
* @copyright 2024-present Smile
* @license Open Software License v. 3.0 (OSL-3.0)
*/

declare(strict_types=1);

namespace Gally\OroPlugin\Search;

use Doctrine\Common\Collections\Expr\Comparison;
use Doctrine\Common\Collections\Expr\CompositeExpression;
use Doctrine\Common\Collections\Expr\Expression;
use Doctrine\Common\Collections\Expr\ExpressionVisitor as BaseExpressionVisitor;
use Doctrine\Common\Collections\Expr\Value;
use Gally\Sdk\GraphQl\Request;
use Oro\Bundle\SearchBundle\Query\Criteria\Criteria;

class ExpressionVisitor extends BaseExpressionVisitor
{
private ?string $searchQuery = null;
private ?string $currentCategoryId = null;

public function dispatch(Expression $expr, bool $isMainQuery = true)
{
// Use main query parameter to flatten main and expression.

switch (true) {
case $expr instanceof Comparison:
return $this->walkComparison($expr);
case $expr instanceof Value:
return $this->walkValue($expr);
case $expr instanceof CompositeExpression:
return $this->walkCompositeExpression($expr, $isMainQuery);
default:
throw new \RuntimeException('Unknown Expression ' . $expr::class);
}
}

public function walkCompositeExpression(CompositeExpression $expr, bool $isMainQuery = true): array
{
$type = '_must';
if (CompositeExpression::TYPE_AND !== $expr->getType()) {
$isMainQuery = false;
$type = '_should';
}

$filters = [];
foreach ($expr->getExpressionList() as $expression) {
$filters[] = $this->dispatch($expression, $isMainQuery);
}
$filters = array_values(array_filter($filters));

return $isMainQuery
? array_merge(...$filters)
: ['boolFilter' => [$type => $filters]];
}

public function walkComparison(Comparison $comparison): ?array
{
[$type, $field] = Criteria::explodeFieldTypeName($comparison->getField());
$value = $this->dispatch($comparison->getValue());
$operator = match ($comparison->getOperator()) {
'IN' => Request::FILTER_OPERATOR_IN,
'LIKE' => Request::FILTER_OPERATOR_MATCH,
default => Request::FILTER_OPERATOR_EQ,
// todo add EXISTS
};

if ('all_text' === $field) {
$this->searchQuery = $value;

return null;
}

if ('inv_status' === $field) {
$field = 'stock.status';
if (count($value) > 1) {
return null; // if we want in stock and out of sotck product, we do not need this filter.
}
$operator = Request::FILTER_OPERATOR_EQ;
$value = in_array(\Oro\Bundle\ProductBundle\Entity\Product::INVENTORY_STATUS_IN_STOCK, $value, true);
// return null; //todo mange specificque code for code stock
} elseif (str_starts_with($field, 'visibility_customer.')) {
[$field, $value] = explode('.', $field);
}

if ('category_path' === $field) {
// $this->currentCategoryId = 'node_' . basename(str_replace('_', '/', $value)); // todo this is wrong, the current category should contain content node id !

// return null;
}

if (str_starts_with($field, 'assigned_to')) {
return null; // Todo manage this
}
if (str_starts_with($field, 'manually_added_to')) {
return null; // Todo manage this
}

if (str_starts_with($field, 'category_path')) {
// return null;
}

return [$field => [$operator => $value]];
}

public function walkValue(Value $value): mixed
{
return $value->getValue();
}

public function getCurrentCategoryId(): ?string
{
return $this->currentCategoryId;
}

public function getSearchQuery(): ?string
{
return $this->searchQuery;
}
}
Loading

0 comments on commit fc45d60

Please sign in to comment.