Skip to content

Commit

Permalink
category automated filters (#3672)
Browse files Browse the repository at this point in the history
  • Loading branch information
vitek-rostislav authored Jan 14, 2025
2 parents 095fcea + 6376467 commit 07aa08d
Show file tree
Hide file tree
Showing 14 changed files with 242 additions and 141 deletions.
22 changes: 7 additions & 15 deletions src/Model/Product/BatchLoad/ProductBatchLoadByEntityData.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ class ProductBatchLoadByEntityData
{
/**
* @param string $id
* @param int $entityId
* @param string $entityClass
* @param object $entity
* @param int $limit
* @param int $offset
* @param string $orderingModeId
Expand All @@ -20,8 +19,7 @@ class ProductBatchLoadByEntityData
*/
public function __construct(
protected readonly string $id,
protected readonly int $entityId,
protected readonly string $entityClass,
protected readonly object $entity,
protected readonly int $limit,
protected readonly int $offset,
protected readonly string $orderingModeId,
Expand All @@ -39,19 +37,13 @@ public function getId(): string
}

/**
* @return int
*/
public function getEntityId(): int
{
return $this->entityId;
}

/**
* @return string
* @template T of object
* @param class-string<T>|null $entityClassName
* @return T
*/
public function getEntityClass(): string
public function getEntity(string $entityClassName = null): object
{
return $this->entityClass;
return $this->entity;
}

/**
Expand Down
128 changes: 128 additions & 0 deletions src/Model/Product/BatchLoad/ProductElasticsearchBatchProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@

namespace Shopsys\FrontendApiBundle\Model\Product\BatchLoad;

use InvalidArgumentException;
use Shopsys\FrameworkBundle\Component\EntityExtension\EntityNameResolver;
use Shopsys\FrameworkBundle\Model\Category\AutomatedFilter\CategoryAutomatedFilterFacade;
use Shopsys\FrameworkBundle\Model\Category\Category;
use Shopsys\FrameworkBundle\Model\Product\Brand\Brand;
use Shopsys\FrameworkBundle\Model\Product\Flag\Flag;
use Shopsys\FrameworkBundle\Model\Product\ProductFrontendLimitProvider;
use Shopsys\FrameworkBundle\Model\Product\Search\FilterQuery;
use Shopsys\FrameworkBundle\Model\Product\Search\FilterQueryFactory;

class ProductElasticsearchBatchProvider
Expand All @@ -13,11 +20,15 @@ class ProductElasticsearchBatchProvider
* @param \Shopsys\FrameworkBundle\Model\Product\Search\FilterQueryFactory $filterQueryFactory
* @param \Shopsys\FrontendApiBundle\Model\Product\BatchLoad\ProductElasticsearchBatchRepository $productElasticsearchBatchRepository
* @param \Shopsys\FrameworkBundle\Model\Product\ProductFrontendLimitProvider $productFrontendLimitProvider
* @param \Shopsys\FrameworkBundle\Component\EntityExtension\EntityNameResolver $entityNameResolver
* @param \Shopsys\FrameworkBundle\Model\Category\AutomatedFilter\CategoryAutomatedFilterFacade $categoryAutomatedFilterFacade
*/
public function __construct(
protected readonly FilterQueryFactory $filterQueryFactory,
protected readonly ProductElasticsearchBatchRepository $productElasticsearchBatchRepository,
protected readonly ProductFrontendLimitProvider $productFrontendLimitProvider,
protected readonly EntityNameResolver $entityNameResolver,
protected readonly CategoryAutomatedFilterFacade $categoryAutomatedFilterFacade,
) {
}

Expand Down Expand Up @@ -50,4 +61,121 @@ public function getBatchedSellableByProductIds(array $productsIds): array

return $this->productElasticsearchBatchRepository->getBatchedProductsAndTotalsByFilterQueries($filterQueries);
}

/**
* @param \Shopsys\FrontendApiBundle\Model\Product\BatchLoad\ProductSellableInCategoryBatchLoadData[] $sellableInCategoryBatchLoadData
* @return array
*/
public function getBatchedSellableInCategoryByIds(array $sellableInCategoryBatchLoadData): array
{
$filterQueries = [];

foreach ($sellableInCategoryBatchLoadData as $batchLoadData) {
$filterQueries[] = $this->getSellableByProductsIdsInCategoryFilterQuery($batchLoadData->productIds, $batchLoadData->category);
}

return $this->productElasticsearchBatchRepository->getBatchedProductsAndTotalsByFilterQueries($filterQueries);
}

/**
* @param \Shopsys\FrontendApiBundle\Model\Product\BatchLoad\ProductBatchLoadByEntityData[] $productBatchLoadByEntitiesData
* @return array
*/
public function getBatchedByEntities(array $productBatchLoadByEntitiesData): array
{
$filterQueries = [];

foreach ($productBatchLoadByEntitiesData as $productBatchLoadByEntityData) {
$filterQueries[$productBatchLoadByEntityData->getId()] = $this->getFilterQuery($productBatchLoadByEntityData);
}

return $this->productElasticsearchBatchRepository->getBatchedProductsAndTotalsByFilterQueries($filterQueries);
}

/**
* @param \Shopsys\FrontendApiBundle\Model\Product\BatchLoad\ProductBatchLoadByEntityData $productBatchLoadByEntityData
* @return \Shopsys\FrameworkBundle\Model\Product\Search\FilterQuery
*/
protected function getFilterQuery(ProductBatchLoadByEntityData $productBatchLoadByEntityData): FilterQuery
{
$entity = $productBatchLoadByEntityData->getEntity();

$filterQuery = match (true) {
$entity instanceof Category => $this->getFilterQueryForCategory($productBatchLoadByEntityData),
$entity instanceof Flag => $this->getFilterQueryForFilterData($productBatchLoadByEntityData),
$entity instanceof Brand => $this->getFilterQueryForBrand($productBatchLoadByEntityData),
default => throw new InvalidArgumentException(sprintf('Entity class "%s" is not supported for creating filter query', get_class($entity))),
};

$filterQuery = $filterQuery->setFrom($productBatchLoadByEntityData->getOffset());

if ($productBatchLoadByEntityData->getSearch() !== '') {
$filterQuery = $filterQuery->search($productBatchLoadByEntityData->getSearch());
}

return $filterQuery;
}

/**
* @param \Shopsys\FrontendApiBundle\Model\Product\BatchLoad\ProductBatchLoadByEntityData $productBatchLoadByEntityData
* @return \Shopsys\FrameworkBundle\Model\Product\Search\FilterQuery
*/
protected function getFilterQueryForCategory(
ProductBatchLoadByEntityData $productBatchLoadByEntityData,
): FilterQuery {
return $this->filterQueryFactory->createListableProductsByCategory(
$productBatchLoadByEntityData->getProductFilterData(),
$productBatchLoadByEntityData->getOrderingModeId(),
1,
$productBatchLoadByEntityData->getLimit(),
$productBatchLoadByEntityData->getEntity($this->entityNameResolver->resolve(Category::class)),
);
}

/**
* @param \Shopsys\FrontendApiBundle\Model\Product\BatchLoad\ProductBatchLoadByEntityData $productBatchLoadByEntityData
* @return \Shopsys\FrameworkBundle\Model\Product\Search\FilterQuery
*/
protected function getFilterQueryForFilterData(
ProductBatchLoadByEntityData $productBatchLoadByEntityData,
): FilterQuery {
return $this->filterQueryFactory->createWithProductFilterData(
$productBatchLoadByEntityData->getProductFilterData(),
$productBatchLoadByEntityData->getOrderingModeId(),
1,
$productBatchLoadByEntityData->getLimit(),
);
}

/**
* @param \Shopsys\FrontendApiBundle\Model\Product\BatchLoad\ProductBatchLoadByEntityData $productBatchLoadByEntityData
* @return \Shopsys\FrameworkBundle\Model\Product\Search\FilterQuery
*/
protected function getFilterQueryForBrand(ProductBatchLoadByEntityData $productBatchLoadByEntityData): FilterQuery
{
return $this->filterQueryFactory->createListableProductsByBrand(
$productBatchLoadByEntityData->getProductFilterData(),
$productBatchLoadByEntityData->getOrderingModeId(),
1,
$productBatchLoadByEntityData->getLimit(),
$productBatchLoadByEntityData->getEntity($this->entityNameResolver->resolve(Brand::class)),
);
}

/**
* @param array $productIds
* @param \Shopsys\FrameworkBundle\Model\Category\Category $category
* @return \Shopsys\FrameworkBundle\Model\Product\Search\FilterQuery
*/
protected function getSellableByProductsIdsInCategoryFilterQuery(
array $productIds,
Category $category,
): FilterQuery {
$filterQuery = $this->filterQueryFactory->createSellableProductsByProductIdsFilter(
$productIds,
$this->productFrontendLimitProvider->getProductsFrontendLimit(),
);

return $this->categoryAutomatedFilterFacade->applyFiltersByCategory($filterQuery, $category);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Shopsys\FrontendApiBundle\Model\Product\BatchLoad;

use Shopsys\FrameworkBundle\Model\Category\Category;

class ProductSellableInCategoryBatchLoadData
{
/**
* @param int[] $productIds
* @param \Shopsys\FrameworkBundle\Model\Category\Category $category
*/
public function __construct(
public readonly array $productIds,
public readonly Category $category,
) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Shopsys\FrontendApiBundle\Model\Product\BatchLoad;

use Shopsys\FrameworkBundle\Model\Category\Category;

class ProductSellableInCategoryBatchLoadDataFactory
{
/**
* @param int[] $productIds
* @param \Shopsys\FrameworkBundle\Model\Category\Category $category
* @return \Shopsys\FrontendApiBundle\Model\Product\BatchLoad\ProductSellableInCategoryBatchLoadData
*/
public function create(array $productIds, Category $category): ProductSellableInCategoryBatchLoadData
{
return new ProductSellableInCategoryBatchLoadData($productIds, $category);
}
}
36 changes: 36 additions & 0 deletions src/Model/Product/BatchLoad/ProductsBatchLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,24 @@ public function loadSellableCountByIds(array $productsIds): Promise
return $this->promiseAdapter->all($this->productElasticsearchBatchProvider->getBatchedSellableByProductIds($productsIds)[ProductElasticsearchBatchRepository::TOTALS_KEY]);
}

/**
* @param \Shopsys\FrontendApiBundle\Model\Product\BatchLoad\ProductSellableInCategoryBatchLoadData[] $sellableInCategoryBatchLoadData
* @return \GraphQL\Executor\Promise\Promise
*/
public function loadSellableInCategoryByIds(array $sellableInCategoryBatchLoadData): Promise
{
return $this->promiseAdapter->all($this->productElasticsearchBatchProvider->getBatchedSellableInCategoryByIds($sellableInCategoryBatchLoadData)[ProductElasticsearchBatchRepository::PRODUCTS_KEY]);
}

/**
* @param \Shopsys\FrontendApiBundle\Model\Product\BatchLoad\ProductSellableInCategoryBatchLoadData[] $sellableInCategoryBatchLoadData
* @return \GraphQL\Executor\Promise\Promise
*/
public function loadSellableCountInCategoryByIds(array $sellableInCategoryBatchLoadData): Promise
{
return $this->promiseAdapter->all($this->productElasticsearchBatchProvider->getBatchedSellableInCategoryByIds($sellableInCategoryBatchLoadData)[ProductElasticsearchBatchRepository::TOTALS_KEY]);
}

/**
* @param string $batchLoadDataId
* @return int
Expand All @@ -85,6 +103,24 @@ public static function getTotalByBatchLoadDataId(string $batchLoadDataId): int
return self::$totalsIndexedByBatchLoadDataId[$batchLoadDataId] ?? 0;
}

/**
* @param \Shopsys\FrontendApiBundle\Model\Product\BatchLoad\ProductBatchLoadByEntityData[] $productBatchLoadByEntitiesData
* @return \GraphQL\Executor\Promise\Promise
*/
public function loadByEntities(array $productBatchLoadByEntitiesData): Promise
{
$batchedByEntities = $this->productElasticsearchBatchProvider->getBatchedByEntities($productBatchLoadByEntitiesData);
self::$totalsIndexedByBatchLoadDataId = $batchedByEntities[ProductElasticsearchBatchRepository::TOTALS_KEY];

$result = [];

foreach ($productBatchLoadByEntitiesData as $productBatchLoadByEntityData) {
$result[] = $batchedByEntities[ProductElasticsearchBatchRepository::PRODUCTS_KEY][$productBatchLoadByEntityData->getId()];
}

return $this->promiseAdapter->all($result);
}

/**
* @param array $arrayForSorting
* @param array $originalArray
Expand Down
4 changes: 1 addition & 3 deletions src/Model/Product/Filter/ProductFilterOptionsFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ public function createProductFilterOptionsForAll(
if ($searchText !== '') {
$productFilterCountData = $this->productOnCurrentDomainElasticFacade->getProductFilterCountDataForSearch(
$searchText,
$productFilterConfig,
$productFilterData,
);
} else {
Expand Down Expand Up @@ -205,8 +204,7 @@ public function createProductFilterOptionsForCategory(
}

$productFilterCountData = $this->productOnCurrentDomainElasticFacade->getProductFilterCountDataInCategory(
$category->getId(),
$productFilterConfig,
$category,
$productFilterData,
);

Expand Down
Loading

0 comments on commit 07aa08d

Please sign in to comment.