/vendor/magento/framework/Search/Request/Cleaner.php

https://gitlab.com/yousafsyed/easternglamor · PHP · 241 lines · 159 code · 14 blank · 68 comment · 27 complexity · 2830e041d31e8187a6063631c87c8cb0 MD5 · raw file

  1. <?php
  2. /**
  3. * Copyright © 2016 Magento. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Search\Request;
  7. use Magento\Framework\Exception\StateException;
  8. use Magento\Framework\Search\Request\Aggregation\StatusInterface as AggregationStatus;
  9. use Magento\Framework\Phrase;
  10. class Cleaner
  11. {
  12. /**
  13. * @var array
  14. */
  15. private $requestData;
  16. /**
  17. * @var array
  18. */
  19. private $mappedQueries;
  20. /**
  21. * @var array
  22. */
  23. private $mappedFilters;
  24. /**
  25. * @var AggregationStatus
  26. */
  27. private $aggregationStatus;
  28. /**
  29. * Cleaner constructor
  30. *
  31. * @param AggregationStatus $aggregationStatus
  32. */
  33. public function __construct(AggregationStatus $aggregationStatus)
  34. {
  35. $this->aggregationStatus = $aggregationStatus;
  36. }
  37. /**
  38. * Clean not binder queries and filters
  39. *
  40. * @param array $requestData
  41. * @return array
  42. */
  43. public function clean(array $requestData)
  44. {
  45. $this->clear();
  46. $this->requestData = $requestData;
  47. $this->cleanQuery($requestData['query']);
  48. $this->cleanAggregations();
  49. $requestData = $this->requestData;
  50. $this->clear();
  51. return $requestData;
  52. }
  53. /**
  54. * Clear don't bind queries
  55. *
  56. * @param string $queryName
  57. * @return void
  58. * @throws StateException
  59. * @throws \Exception
  60. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  61. * @SuppressWarnings(PHPMD.UnusedLocalVariable)
  62. */
  63. private function cleanQuery($queryName)
  64. {
  65. if (!isset($this->requestData['queries'][$queryName])) {
  66. throw new \Exception('Query ' . $queryName . ' does not exist');
  67. } elseif (in_array($queryName, $this->mappedQueries)) {
  68. throw new StateException(
  69. new Phrase('Cycle found. Query %1 already used in request hierarchy', [$queryName])
  70. );
  71. }
  72. $this->mappedQueries[] = $queryName;
  73. $query = $this->requestData['queries'][$queryName];
  74. switch ($query['type']) {
  75. case QueryInterface::TYPE_BOOL:
  76. $queryReference = $this->processQueryReference($query['queryReference']);
  77. if (empty($queryReference)) {
  78. unset($this->requestData['queries'][$queryName]);
  79. } else {
  80. $this->requestData['queries'][$queryName]['queryReference'] = array_values($queryReference);
  81. }
  82. break;
  83. case QueryInterface::TYPE_MATCH:
  84. if (!array_key_exists('is_bind', $query)) {
  85. unset($this->requestData['queries'][$queryName]);
  86. }
  87. break;
  88. case QueryInterface::TYPE_FILTER:
  89. if (isset($query['queryReference'][0])) {
  90. $fQueryName = $query['queryReference'][0]['ref'];
  91. $this->cleanQuery($fQueryName);
  92. if (!isset($this->requestData['queries'][$fQueryName])) {
  93. unset($this->requestData['queries'][$queryName]);
  94. }
  95. } elseif (isset($query['filterReference'][0])) {
  96. $filterName = $query['filterReference'][0]['ref'];
  97. $this->cleanFilter($filterName);
  98. if (!isset($this->requestData['filters'][$filterName])) {
  99. unset($this->requestData['queries'][$queryName]);
  100. }
  101. } else {
  102. throw new \Exception('Reference is not provided');
  103. }
  104. break;
  105. default:
  106. throw new \InvalidArgumentException('Invalid query type');
  107. }
  108. }
  109. /**
  110. * Clean aggregations if we don't need to process them
  111. *
  112. * @return void
  113. */
  114. private function cleanAggregations()
  115. {
  116. if (!$this->aggregationStatus->isEnabled()) {
  117. $this->requestData['aggregations'] = [];
  118. } else {
  119. if (array_key_exists('aggregations', $this->requestData) && is_array($this->requestData['aggregations'])) {
  120. foreach ($this->requestData['aggregations'] as $aggregationName => $aggregationValue) {
  121. switch ($aggregationValue['type']) {
  122. case 'dynamicBucket':
  123. if (is_string($aggregationValue['method'])
  124. && preg_match('/^\$(.+)\$$/si', $aggregationValue['method'])
  125. ) {
  126. unset($this->requestData['aggregations'][$aggregationName]);
  127. }
  128. }
  129. }
  130. }
  131. }
  132. }
  133. /**
  134. * Clear don't bind filters
  135. *
  136. * @param string $filterName
  137. * @return void
  138. * @throws StateException
  139. * @throws \Exception
  140. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  141. */
  142. private function cleanFilter($filterName)
  143. {
  144. if (!isset($this->requestData['filters'][$filterName])) {
  145. throw new \Exception('Filter ' . $filterName . ' does not exist');
  146. } elseif (in_array($filterName, $this->mappedFilters)) {
  147. throw new StateException(
  148. new Phrase('Cycle found. Filter %1 already used in request hierarchy', [$filterName])
  149. );
  150. }
  151. $this->mappedFilters[] = $filterName;
  152. $filter = $this->requestData['filters'][$filterName];
  153. switch ($filter['type']) {
  154. case FilterInterface::TYPE_WILDCARD:
  155. case FilterInterface::TYPE_TERM:
  156. if (!array_key_exists('is_bind', $filter)) {
  157. unset($this->requestData['filters'][$filterName]);
  158. }
  159. break;
  160. case FilterInterface::TYPE_RANGE:
  161. $keys = ['from', 'to'];
  162. foreach ($keys as $key) {
  163. if (isset($filter[$key]) && preg_match('/^\$(.+)\$$/si', $filter[$key])) {
  164. unset($this->requestData['filters'][$filterName][$key]);
  165. }
  166. }
  167. $filterKeys = array_keys($this->requestData['filters'][$filterName]);
  168. if (count(array_diff($keys, $filterKeys)) == count($keys)) {
  169. unset($this->requestData['filters'][$filterName]);
  170. }
  171. break;
  172. case FilterInterface::TYPE_BOOL:
  173. $filterReference = $this->processFilterReference($filter['filterReference']);
  174. if (empty($filterReference)) {
  175. unset($this->requestData['filters'][$filterName]);
  176. } else {
  177. $this->requestData['filters'][$filterName]['filterReference'] = array_values($filterReference);
  178. }
  179. break;
  180. default:
  181. throw new \InvalidArgumentException('Invalid filter type');
  182. }
  183. }
  184. /**
  185. * Aggregate Queries by clause
  186. *
  187. * @param array $queryReference
  188. * @return array
  189. */
  190. private function processQueryReference($queryReference)
  191. {
  192. foreach ($queryReference as $key => $value) {
  193. $this->cleanQuery($value['ref']);
  194. if (!isset($this->requestData['queries'][$value['ref']])) {
  195. unset($queryReference[$key]);
  196. }
  197. }
  198. return $queryReference;
  199. }
  200. /**
  201. * Aggregate Filters by clause
  202. *
  203. * @param array $filterReference
  204. * @return array
  205. */
  206. private function processFilterReference($filterReference)
  207. {
  208. foreach ($filterReference as $key => $value) {
  209. $this->cleanFilter($value['ref']);
  210. if (!isset($this->requestData['filters'][$value['ref']])) {
  211. unset($filterReference[$key]);
  212. }
  213. }
  214. return $filterReference;
  215. }
  216. /**
  217. * Clear variables to default status
  218. *
  219. * @return void
  220. */
  221. private function clear()
  222. {
  223. $this->mappedQueries = [];
  224. $this->mappedFilters = [];
  225. $this->requestData = [];
  226. }
  227. }