287 lines
8.2 KiB
PHP
Executable File
287 lines
8.2 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* @author Amasty Team
|
|
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
|
* @package Elastic Search Base for Magento 2
|
|
*/
|
|
|
|
namespace Amasty\ElasticSearch\Model\Search;
|
|
|
|
use Amasty\ElasticSearch\Model\Client\ClientRepositoryInterface;
|
|
use Magento\CatalogSearch\Model\Indexer\Fulltext;
|
|
use Magento\Framework\Search\Dynamic\EntityStorage;
|
|
|
|
class DataProvider implements \Magento\Framework\Search\Dynamic\DataProviderInterface
|
|
{
|
|
private const DEFAULT_AGGREGATION_FIELD = 'price';
|
|
|
|
/**
|
|
* @var \Magento\Catalog\Model\Layer\Filter\Price\Range
|
|
*/
|
|
private $range;
|
|
|
|
/**
|
|
* @var \Magento\Framework\Search\Dynamic\IntervalFactory
|
|
*/
|
|
private $intervalFactory;
|
|
|
|
/**
|
|
* @var \Magento\Framework\App\ScopeResolverInterface
|
|
*/
|
|
private $scopeResolver;
|
|
|
|
/**
|
|
* @var ClientRepositoryInterface
|
|
*/
|
|
private $clientRepository;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
private $indexerId;
|
|
|
|
/**
|
|
* @var \Amasty\ElasticSearch\Model\Config
|
|
*/
|
|
private $config;
|
|
|
|
/**
|
|
* @var \Magento\Store\Model\StoreManagerInterface
|
|
*/
|
|
private $storeManager;
|
|
|
|
/**
|
|
* @var GetRequestQuery\GetAggregations\FieldMapper
|
|
*/
|
|
private $fieldMapper;
|
|
|
|
/**
|
|
* @var \Magento\Customer\Model\Session
|
|
*/
|
|
private $customerSession;
|
|
|
|
/**
|
|
* @var \Magento\Framework\Registry
|
|
*/
|
|
private $registry;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
private $aggregationFieldName;
|
|
|
|
public function __construct(
|
|
ClientRepositoryInterface $clientRepository,
|
|
\Magento\Catalog\Model\Layer\Filter\Price\Range $range,
|
|
\Magento\Framework\Search\Dynamic\IntervalFactory $intervalFactory,
|
|
\Magento\Framework\App\ScopeResolverInterface $scopeResolver,
|
|
\Amasty\ElasticSearch\Model\Config $config,
|
|
\Magento\Store\Model\StoreManagerInterface $storeManager,
|
|
\Amasty\ElasticSearch\Model\Search\GetRequestQuery\GetAggregations\FieldMapper $fieldMapper,
|
|
\Magento\Customer\Model\Session $customerSession,
|
|
\Magento\Framework\Registry $registry,
|
|
$indexerId = Fulltext::INDEXER_ID,
|
|
$aggregationFieldName = self::DEFAULT_AGGREGATION_FIELD
|
|
) {
|
|
$this->range = $range;
|
|
$this->intervalFactory = $intervalFactory;
|
|
$this->scopeResolver = $scopeResolver;
|
|
$this->clientRepository = $clientRepository;
|
|
$this->config = $config;
|
|
$this->storeManager = $storeManager;
|
|
$this->fieldMapper = $fieldMapper;
|
|
$this->customerSession = $customerSession;
|
|
$this->registry = $registry;
|
|
$this->indexerId = $indexerId;
|
|
$this->aggregationFieldName = $aggregationFieldName;
|
|
}
|
|
|
|
/**
|
|
* @return array|int
|
|
*/
|
|
public function getRange()
|
|
{
|
|
return $this->range->getPriceRange();
|
|
}
|
|
|
|
/**
|
|
* @param EntityStorage $entityStorage
|
|
* @return array
|
|
*/
|
|
public function getAggregations(EntityStorage $entityStorage)
|
|
{
|
|
$query = $this->generateAggregationsQuery($entityStorage);
|
|
$queryResult = $this->clientRepository->get()->search($query);
|
|
|
|
$result['std'] = !empty($queryResult['aggregations']['prices']['std_deviation'])
|
|
? $queryResult['aggregations']['prices']['std_deviation'] : 0;
|
|
foreach (['count', 'max', 'min'] as $aggregator) {
|
|
$result[$aggregator] = !empty($queryResult['aggregations']['prices'][$aggregator])
|
|
? $queryResult['aggregations']['prices'][$aggregator] : 0;
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* @param EntityStorage $entityStorage
|
|
* @return array
|
|
*/
|
|
private function generateAggregationsQuery(EntityStorage $entityStorage)
|
|
{
|
|
$query = $this->generateGeneralQuery($entityStorage);
|
|
|
|
$query['body']['aggregations'] = [
|
|
'prices' => [
|
|
'extended_stats' => [
|
|
'field' => $this->fieldMapper->mapFieldName($this->aggregationFieldName),
|
|
],
|
|
],
|
|
];
|
|
|
|
return $query;
|
|
}
|
|
|
|
/**
|
|
* @param EntityStorage $entityStorage
|
|
* @param $fieldName
|
|
* @param $range
|
|
* @param array $dimensions
|
|
* @return array
|
|
*/
|
|
private function generateAggregationQuery(EntityStorage $entityStorage, $fieldName, $range, $dimensions = [])
|
|
{
|
|
$query = $this->generateGeneralQuery($entityStorage, $dimensions);
|
|
|
|
$query['body']['aggregations'] = [
|
|
'prices' => [
|
|
'histogram' => [
|
|
'field' => $fieldName,
|
|
'interval' => $range,
|
|
],
|
|
],
|
|
];
|
|
|
|
return $query;
|
|
}
|
|
|
|
/**
|
|
* @param EntityStorage $entityStorage
|
|
* @param array $dimensions
|
|
* @return array
|
|
*/
|
|
private function generateGeneralQuery(EntityStorage $entityStorage, array $dimensions = [])
|
|
{
|
|
$dimension = current($dimensions);
|
|
$storeId = false !== $dimension
|
|
? $this->scopeResolver->getScope($dimension->getValue())->getId()
|
|
: $this->storeManager->getStore()->getId();
|
|
|
|
$requestQuery = [
|
|
'index' => $this->config->getIndexName($this->indexerId, $storeId),
|
|
'type' => $this->config->getEntityType(),
|
|
'body' => [
|
|
'stored_fields' => [
|
|
'_id',
|
|
'_score',
|
|
]
|
|
]
|
|
];
|
|
|
|
$query = $this->registry->registry(Adapter::REQUEST_QUERY);
|
|
if (!$query) {
|
|
$entityIds = $entityStorage->getSource();
|
|
$query = [
|
|
'bool' => [
|
|
'must' => [
|
|
['terms' => ['_id' => $entityIds]]
|
|
]
|
|
]
|
|
];
|
|
}
|
|
|
|
$requestQuery['body']['query'] = $query;
|
|
|
|
return $requestQuery;
|
|
}
|
|
|
|
/**
|
|
* @param \Magento\Framework\Search\Request\BucketInterface $bucket
|
|
* @param array $dimensions
|
|
* @param EntityStorage $entityStorage
|
|
* @return \Magento\Framework\Search\Dynamic\IntervalInterface
|
|
*/
|
|
public function getInterval(
|
|
\Magento\Framework\Search\Request\BucketInterface $bucket,
|
|
array $dimensions,
|
|
EntityStorage $entityStorage
|
|
) {
|
|
$dimension = current($dimensions);
|
|
$storeId = $this->scopeResolver->getScope($dimension->getValue())->getId();
|
|
|
|
return $this->intervalFactory->create(
|
|
[
|
|
'entityIds' => $entityStorage->getSource(),
|
|
'storeId' => $storeId,
|
|
'fieldName' => 'price_' . $this->customerSession->getCustomerGroupId(),
|
|
]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param \Magento\Framework\Search\Request\BucketInterface $bucket
|
|
* @param array $dimensions
|
|
* @param int $range
|
|
* @param EntityStorage $entityStorage
|
|
* @return array
|
|
*/
|
|
public function getAggregation(
|
|
\Magento\Framework\Search\Request\BucketInterface $bucket,
|
|
array $dimensions,
|
|
$range,
|
|
EntityStorage $entityStorage
|
|
) {
|
|
$result = [];
|
|
|
|
$fieldName = $this->fieldMapper->mapFieldName($bucket->getField());
|
|
|
|
$query = $this->generateAggregationQuery($entityStorage, $fieldName, $range, $dimensions);
|
|
|
|
$queryResult = $this->clientRepository->get()->search($query);
|
|
foreach ($queryResult['aggregations']['prices']['buckets'] as $bucket) {
|
|
$key = (int)($bucket['key'] / $range + 1);
|
|
if ($bucket['doc_count']) {
|
|
$result[$key] = $bucket['doc_count'];
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* @param int $range
|
|
* @param array $ranges
|
|
* @return array
|
|
*/
|
|
public function prepareData($range, array $ranges)
|
|
{
|
|
$result = [];
|
|
if (!empty($ranges)) {
|
|
$lastIndex = array_keys($ranges);
|
|
$lastIndex = $lastIndex[count($lastIndex) - 1];
|
|
foreach ($ranges as $index => $count) {
|
|
$fromPrice = $index == 1 ? '' : ($index - 1) * $range;
|
|
$toPrice = $index * $range;
|
|
|
|
$result[] = [
|
|
'from' => $fromPrice,
|
|
'to' => $toPrice,
|
|
'count' => $count,
|
|
];
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
}
|