<?php declare(strict_types=1);
namespace Swag\EnterpriseSearch\Boosting;
use ONGR\ElasticsearchDSL\BuilderInterface;
use ONGR\ElasticsearchDSL\Query\Compound\BoolQuery;
use ONGR\ElasticsearchDSL\Query\Compound\ConstantScoreQuery;
use ONGR\ElasticsearchDSL\Search;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition;
use Shopware\Core\Framework\DataAbstractionLayer\Exception\SearchRequestException;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Parser\QueryStringParser;
use Shopware\Elasticsearch\Framework\DataAbstractionLayer\CriteriaParser;
use Swag\EnterpriseSearch\Common\SesExtension;
/**
* Handles a given boosting struct and returns the corresponding ES query object for the `boostingRule`
*/
class BoostingQueryBuilder
{
public const FILTER = 'filter';
public const BOOSTING = 'boosting';
/**
* @var BoostingProvider
*/
private $boostingProvider;
/**
* @var CriteriaParser
*/
private $criteriaParser;
public function __construct(
BoostingProvider $boostingProvider,
CriteriaParser $criteriaParser
) {
$this->boostingProvider = $boostingProvider;
$this->criteriaParser = $criteriaParser;
}
public function addBoostingQuery(EntityDefinition $definition, Criteria $criteria, Search $search, Context $context): void
{
$boostingCombinations = $this->boostingProvider->getActiveBoostings($definition, $context);
foreach ($boostingCombinations as $boostingCombination) {
$filters = $boostingCombination[self::FILTER];
/** @var BoostingEntity $boostingEntity */
$boostingEntity = $boostingCombination[self::BOOSTING];
if (empty($filters)) {
continue;
}
if (!$boostingEntity->isActive() || !$boostingEntity->isValid()) {
continue;
}
$search->addQuery($this->getBoostingQuery($boostingEntity, $definition, $context, $filters), BoolQuery::SHOULD);
}
}
protected function getBoostingQuery(BoostingEntity $boosting, EntityDefinition $definition, Context $context, array $filters): BuilderInterface
{
$filter = QueryStringParser::fromArray($definition, $filters, new SearchRequestException());
$query = new ConstantScoreQuery($this->criteriaParser->parseFilter($filter, $definition, $definition->getEntityName(), $context));
$query->addParameter('boost', $boosting->getBoost());
if (SesExtension::isExplanation($context)) {
$boostingValue = (string) $boosting->getBoost();
$query->addParameter('_name', 'Boosting ' . $boosting->getTranslation('name') . ' ' . $boostingValue);
}
return $query;
}
}