Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
FieldsFilter.php
Go to the documentation of this file.
1 <?php
8 
12 
17 {
18  const FILTER_PARAMETER = 'fields';
19 
23  protected $_request;
24 
30  public function __construct(RestRequest $request)
31  {
32  $this->_request = $request;
33  }
34 
41  public function filter($response)
42  {
43  $filter = $this->_request->getParam(self::FILTER_PARAMETER);
44  if (!is_string($filter)) {
45  return [];
46  }
47  $filterArray = $this->parse($filter);
48  if ($filterArray === null) {
49  return [];
50  }
51  $partialResponse = $this->applyFilter($response, $filterArray);
52  return $partialResponse;
53  }
54 
86  protected function parse($filterString)
87  {
88  $length = strlen($filterString);
89  //Permissible characters in filter string: letter, number, underscore, square brackets and comma
90  if ($length == 0 || preg_match('/[^\w\[\],]+/', $filterString)) {
91  return null;
92  }
93 
94  $start = null;
95  $current = [];
96  $stack = [];
97  $parent = [];
98  $currentElement = null;
99 
100  for ($position = 0; $position < $length; $position++) {
101  //Extracting field when encountering field separators
102  if (in_array($filterString[$position], ['[', ']', ','])) {
103  if ($start !== null) {
104  $currentElement = substr($filterString, $start, $position - $start);
105  $current[$currentElement] = 1;
106  }
107  $start = null;
108  }
109  switch ($filterString[$position]) {
110  case '[':
111  $parent[] = $currentElement;
112  // push current field in stack and initialize current
113  $stack[] = $current;
114  $current = [];
115  break;
116 
117  case ']':
118  //cache current
119  $temp = $current;
120  //Initialize with previous
121  $current = array_pop($stack);
122  //Add from cache
123  $current[array_pop($parent)] = $temp;
124  break;
125 
126  //Do nothing on comma. On the next iteration field will be extracted
127  case ',':
128  break;
129 
130  default:
131  //Move position if no field separators found
132  if ($start === null) {
133  $start = $position;
134  }
135  }
136  }
137  //Check for wrongly formatted filter
138  if (!empty($stack)) {
139  return null;
140  }
141  //Check if there's any field remaining that's not added to response
142  if ($start !== null) {
143  $currentElement = substr($filterString, $start, $position - $start);
144  $current[$currentElement] = 1;
145  }
146  return $current;
147  }
148 
156  protected function applyFilter(array $responseArray, array $filter)
157  {
158  $arrayIntersect = null;
159  //Check if its a sequential array. Presence of sequential arrays mean that the filed is a collection
160  //and the filtering will be applied to all the collection items
161  if (!(bool)count(array_filter(array_keys($responseArray), 'is_string'))) {
162  foreach ($responseArray as $key => &$item) {
163  $arrayIntersect[$key] = $this->recursiveArrayIntersectKey($item, $filter);
164  }
165  } else {
166  $arrayIntersect = $this->recursiveArrayIntersectKey($responseArray, $filter);
167  }
168  return $arrayIntersect;
169  }
170 
178  protected function recursiveArrayIntersectKey(array $array1, array $array2)
179  {
180  //If the field in array2 (filter) is not present in array1 (response) it will be removed after intersect
181  $arrayIntersect = array_intersect_key($array1, $array2);
182  foreach ($arrayIntersect as $key => &$value) {
185  ) {
186  $value = $this->filterCustomAttributes(
187  $value,
189  );
190  continue;
191  }
192  if (is_array($value) && is_array($array2[$key])) {
193  $value = $this->applyFilter($value, $array2[$key]);
194  }
195  }
196  return $arrayIntersect;
197  }
198 
206  private function filterCustomAttributes(array $item, array $filter) : array
207  {
208  $fieldResult = [];
209  foreach ($item as $key => $field) {
210  $filterKeys = array_keys($filter);
211  if (in_array($field[AttributeInterface::ATTRIBUTE_CODE], $filterKeys)) {
212  $fieldResult[$key][AttributeInterface::ATTRIBUTE_CODE] = $field[AttributeInterface::ATTRIBUTE_CODE];
213  $fieldResult[$key][AttributeInterface::VALUE] = $field[AttributeInterface::VALUE];
214  } else {
215  if (isset($filter[AttributeInterface::ATTRIBUTE_CODE])) {
216  $fieldResult[$key][AttributeInterface::ATTRIBUTE_CODE] = $field[AttributeInterface::ATTRIBUTE_CODE];
217  }
218  if (isset($filter[AttributeInterface::VALUE])) {
219  $fieldResult[$key][AttributeInterface::VALUE] = $field[AttributeInterface::VALUE];
220  }
221  }
222  }
223 
224  return $fieldResult;
225  }
226 }
$response
Definition: 404.php:11
recursiveArrayIntersectKey(array $array1, array $array2)
$start
Definition: listing.phtml:18
applyFilter(array $responseArray, array $filter)
$value
Definition: gender.phtml:16