Skip to content
Snippets Groups Projects

Resolve #3366032 "Problem with filter"

1 file
+ 123
27
Compare changes
  • Side-by-side
  • Inline
@@ -31,6 +31,13 @@ class ViewsJsonQuery extends QueryPluginBase {
*/
protected $contextualFilter;
/**
* To store the Filter groups info.
*
* @var array
*/
protected array $filterGroups = [];
/**
* The config.
*
@@ -351,35 +358,13 @@ class ViewsJsonQuery extends QueryPluginBase {
// Get rows.
$ret = $this->apath($this->options['row_apath'], $ret) ?? [];
// Get group operator.
$filter_group = $view->display_handler->getOption('filter_groups');
$group_conditional_operator = $filter_group['groups'][1] ?? "AND";
// Prepare filter group.
$this->setFilterGroups($view);
// Filter.
foreach ($ret as $k => $row) {
$check = TRUE;
foreach ($view->build_info['query'] as $filter) {
// Filter only when value is present.
if (!empty($filter[0])) {
$l = $row[$filter[0]];
$check = $this->ops($filter[1], $l, $filter[2]);
if ($group_conditional_operator === "AND") {
// With AND condition.
if (!$check) {
break;
}
}
elseif ($group_conditional_operator === "OR") {
// With OR conditions.
if ($check) {
break;
}
}
}
}
if (!$check) {
unset($ret[$k]);
}
if (!empty($this->filterGroups) && !empty($ret)) {
// If view has filters set, then process by group to select the records.
$this->filterRecords($ret);
}
try {
@@ -650,4 +635,115 @@ class ViewsJsonQuery extends QueryPluginBase {
return $filter;
}
/**
* Sets filter groups data array from the view.
*
* @param \Drupal\views\ViewExecutable $view
* The view executable.
*
* @return void
* Sets the property filterGroups if there's at least one filter.
*/
private function setFilterGroups(ViewExecutable $view) :void {
$filter_handlers = $view->getHandlers('filter');
if (empty($filter_handlers)) {
// Check the filter handlers, empty means no filter has been configured.
// We discard the filter groups information, is not needed anymore.
return;
}
// Filter groups option always comes with information.
$filterGroups = $view->display_handler->getOption('filter_groups');
$this->filterGroups['operator'] = $filterGroups['operator'];
foreach ($filterGroups['groups'] as $groupId => $groupOperator) {
$this->filterGroups['group'][$groupId]['group_operator'] = $groupOperator;
}
// Finally add the data of filters per each group.
foreach ($filter_handlers as $k => $dataFilter) {
$this->filterGroups['group'][$dataFilter['group']]['filter'][$dataFilter['id']]['key'] = $dataFilter['key'];
$this->filterGroups['group'][$dataFilter['group']]['filter'][$dataFilter['id']]['operator'] = $dataFilter['operator'];
$this->filterGroups['group'][$dataFilter['group']]['filter'][$dataFilter['id']]['value'] = $dataFilter['value'];
}
}
/**
* Filters the records processing them per group.
*
* @param array $records
* Array with the records of the JSON that must be filtered.
*
* @return void
* Array of the filtered records from json that must be presented.
*/
private function filterRecords(array &$records) :void {
foreach ($records as $k => $row) {
$check = TRUE;
$groupCheck = [];
// Process each group per record.
foreach ($this->filterGroups['group'] as $group_key => $group_data) {
$groupCheck[$group_key]['result'] = $this->processAllFiltersInGroup($row, $group_data);
}
// Validate overall result of the record.
foreach ($groupCheck as $groupResult) {
if ($this->filterGroups['operator'] === "AND") {
// With AND condition.
if ($groupResult['result'] === FALSE) {
$check = FALSE;
}
}
elseif ($this->filterGroups['operator'] === "OR") {
// With OR conditions.
if ($groupResult['result']) {
$check = FALSE;
}
}
if (!$check) {
unset($records[$k]);
}
}
}
}
/**
* Processes all filters of a group.
*
* @param array $inputData
* Array containing the value to inspect.
* @param array $groupData
* Data of the filter group.
*
* @return bool
* The result of the filtering of the group.
*/
private function processAllFiltersInGroup(array $inputData, array $groupData) :bool {
$resultProcess = FALSE;
// If no data to process, bail out.
if (is_null($inputData) || empty($groupData)) {
return $resultProcess;
}
foreach ($groupData['filter'] as $filter) {
// Get the value to be processed.
$field = $inputData[$filter['key']];
// Filter only when value is present.
$resultProcess = $this->ops($filter['operator'], $field, $filter['value']);
if ($groupData['group_operator'] === "AND") {
// With AND condition.
if (!$resultProcess) {
break;
}
}
elseif ($groupData['group_operator'] === "OR") {
// With OR conditions.
if ($resultProcess) {
break;
}
}
}
return $resultProcess;
}
}
Loading