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 = []; } }