123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Framework\Search\Request;
- use Magento\Framework\Exception\StateException;
- use Magento\Framework\Search\Request\Aggregation\StatusInterface as AggregationStatus;
- use Magento\Framework\Phrase;
- /**
- * @api
- * @since 100.0.2
- */
- class Cleaner
- {
- /**
- * @var array
- */
- private $requestData;
- /**
- * @var array
- */
- private $mappedQueries;
- /**
- * @var array
- */
- private $mappedFilters;
- /**
- * @var AggregationStatus
- */
- private $aggregationStatus;
- /**
- * Cleaner constructor
- *
- * @param AggregationStatus $aggregationStatus
- */
- public function __construct(AggregationStatus $aggregationStatus)
- {
- $this->aggregationStatus = $aggregationStatus;
- }
- /**
- * Clean not binder queries and filters
- *
- * @param array $requestData
- * @return array
- */
- public function clean(array $requestData)
- {
- $this->clear();
- $this->requestData = $requestData;
- $this->cleanQuery($requestData['query']);
- $this->cleanAggregations();
- $requestData = $this->requestData;
- $this->clear();
- if (empty($requestData['queries']) && empty($requestData['filters'])) {
- throw new EmptyRequestDataException(
- new Phrase("The request query and filters aren't set. Verify the query and filters and try again.")
- );
- }
- return $requestData;
- }
- /**
- * Clear don't bind queries
- *
- * @param string $queryName
- * @return void
- * @throws StateException
- * @throws \Exception
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- * @SuppressWarnings(PHPMD.UnusedLocalVariable)
- */
- private function cleanQuery($queryName)
- {
- if (!isset($this->requestData['queries'][$queryName])) {
- throw new \Exception('Query ' . $queryName . ' does not exist');
- } elseif (in_array($queryName, $this->mappedQueries)) {
- throw new StateException(
- new Phrase('A cycle was found. The "%1" query is already used in the request hierarchy.', [$queryName])
- );
- }
- $this->mappedQueries[] = $queryName;
- $query = $this->requestData['queries'][$queryName];
- switch ($query['type']) {
- case QueryInterface::TYPE_BOOL:
- $queryReference = $this->processQueryReference($query['queryReference']);
- if (empty($queryReference)) {
- unset($this->requestData['queries'][$queryName]);
- } else {
- $this->requestData['queries'][$queryName]['queryReference'] = array_values($queryReference);
- }
- break;
- case QueryInterface::TYPE_MATCH:
- if (!array_key_exists('is_bind', $query)) {
- unset($this->requestData['queries'][$queryName]);
- }
- break;
- case QueryInterface::TYPE_FILTER:
- if (isset($query['queryReference'][0])) {
- $fQueryName = $query['queryReference'][0]['ref'];
- $this->cleanQuery($fQueryName);
- if (!isset($this->requestData['queries'][$fQueryName])) {
- unset($this->requestData['queries'][$queryName]);
- }
- } elseif (isset($query['filterReference'][0])) {
- $filterName = $query['filterReference'][0]['ref'];
- $this->cleanFilter($filterName);
- if (!isset($this->requestData['filters'][$filterName])) {
- unset($this->requestData['queries'][$queryName]);
- }
- } else {
- throw new \Exception('Reference is not provided');
- }
- break;
- default:
- throw new \InvalidArgumentException('Invalid query type');
- }
- }
- /**
- * Clean aggregations if we don't need to process them
- *
- * @return void
- */
- private function cleanAggregations()
- {
- if (!$this->aggregationStatus->isEnabled()) {
- $this->requestData['aggregations'] = [];
- } else {
- if (array_key_exists('aggregations', $this->requestData) && is_array($this->requestData['aggregations'])) {
- foreach ($this->requestData['aggregations'] as $aggregationName => $aggregationValue) {
- switch ($aggregationValue['type']) {
- case 'dynamicBucket':
- if (is_string($aggregationValue['method'])
- && preg_match('/^\$(.+)\$$/si', $aggregationValue['method'])
- ) {
- unset($this->requestData['aggregations'][$aggregationName]);
- }
- }
- }
- }
- }
- }
- /**
- * Clear don't bind filters
- *
- * @param string $filterName
- * @return void
- * @throws StateException
- * @throws \Exception
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- */
- private function cleanFilter($filterName)
- {
- if (!isset($this->requestData['filters'][$filterName])) {
- throw new \Exception('Filter ' . $filterName . ' does not exist');
- } elseif (in_array($filterName, $this->mappedFilters)) {
- throw new StateException(
- new Phrase(
- 'A cycle was found. The "%1" filter is already used in the request hierarchy.',
- [$filterName]
- )
- );
- }
- $this->mappedFilters[] = $filterName;
- $filter = $this->requestData['filters'][$filterName];
- switch ($filter['type']) {
- case FilterInterface::TYPE_WILDCARD:
- case FilterInterface::TYPE_TERM:
- if (!array_key_exists('is_bind', $filter)) {
- unset($this->requestData['filters'][$filterName]);
- }
- break;
- case FilterInterface::TYPE_RANGE:
- $keys = ['from', 'to'];
- foreach ($keys as $key) {
- if (isset($filter[$key]) && preg_match('/^\$(.+)\$$/si', $filter[$key])) {
- unset($this->requestData['filters'][$filterName][$key]);
- }
- }
- $filterKeys = array_keys($this->requestData['filters'][$filterName]);
- if (count(array_diff($keys, $filterKeys)) == count($keys)) {
- unset($this->requestData['filters'][$filterName]);
- }
- break;
- case FilterInterface::TYPE_BOOL:
- $filterReference = $this->processFilterReference($filter['filterReference']);
- if (empty($filterReference)) {
- unset($this->requestData['filters'][$filterName]);
- } else {
- $this->requestData['filters'][$filterName]['filterReference'] = array_values($filterReference);
- }
- break;
- default:
- throw new \InvalidArgumentException('Invalid filter type');
- }
- }
- /**
- * Aggregate Queries by clause
- *
- * @param array $queryReference
- * @return array
- */
- private function processQueryReference($queryReference)
- {
- foreach ($queryReference as $key => $value) {
- $this->cleanQuery($value['ref']);
- if (!isset($this->requestData['queries'][$value['ref']])) {
- unset($queryReference[$key]);
- }
- }
- return $queryReference;
- }
- /**
- * Aggregate Filters by clause
- *
- * @param array $filterReference
- * @return array
- */
- private function processFilterReference($filterReference)
- {
- foreach ($filterReference as $key => $value) {
- $this->cleanFilter($value['ref']);
- if (!isset($this->requestData['filters'][$value['ref']])) {
- unset($filterReference[$key]);
- }
- }
- return $filterReference;
- }
- /**
- * Clear variables to default status
- *
- * @return void
- */
- private function clear()
- {
- $this->mappedQueries = [];
- $this->mappedFilters = [];
- $this->requestData = [];
- }
- }
|