Files
ltsecurityinc/app/code/Amasty/ElasticSearch/Model/Search/DataProvider.php
T

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;
}
}