'', 'values' => [], 'from' => '', 'to' => '', 'errors' => $control['errors'] ?? []]; foreach (native_parameter_suffixes($control) as $suffix) { $key = $parameters[$id][$suffix] ?? ''; $legacy_key = $generated[$id][$suffix] ?? ''; $raw = $key !== '' ? (array_key_exists($key, $request) ? $request[$key] : ($request[$legacy_key] ?? '')) : ''; if ($kind === 'choice') { $values = is_array($raw) ? $raw : [$raw]; if (count($values) > MAX_VALUES_PER_FILTER) $state['errors'][] = 'too-many-values'; foreach (array_slice($values, 0, MAX_VALUES_PER_FILTER) as $value) { if (!is_scalar($value)) { $state['errors'][] = 'invalid-value'; continue; } $value = trim((string) $value); if ($value === '') continue; if (!in_array($value, array_column($control['choices'], 'value'), true)) { $state['errors'][] = 'invalid-choice'; continue; } $state['values'][] = $value; } $state['values'] = array_values(array_unique($state['values'])); if (!$control['settings']['multiple'] && count($state['values']) > 1) $state['errors'][] = 'multiple-not-allowed'; $state['value'] = $state['values'][0] ?? ''; continue; } } $result[$id] = $state; } return ['nativeControls' => $result]; } namespace Fqbpro\Plugin\Query\Compiler; use Fqbpro\Plugin\Blocks\FilterHeader; function compile($query, $configuration, $state, $sources) { if (!empty($configuration['errors'])) { $query['post__in'] = [0]; return $query; } foreach ($configuration['nativeControls'] ?? [] as $control) { $current = $state['nativeControls'][$control['controlId']] ?? []; if (!empty($control['errors']) || !empty($current['errors'])) { $query['post__in'] = [0]; return $query; } if (!in_array($control['kind'], ['choice', 'apply', 'reset'], true)) { $query['post__in'] = [0]; return $query; } $settings = $control['settings']; if ($control['kind'] === 'choice' && !empty($current['values'])) { $source = $sources[$control['sourceId']] ?? []; if (($source['type'] ?? '') !== 'taxonomy' || array_diff($current['values'], array_column($control['choices'], 'value'))) { $query['post__in'] = [0]; return $query; } $clause = ['taxonomy' => $source['source'], 'field' => 'slug', 'terms' => $current['values'], 'operator' => $settings['operator'], 'include_children' => $settings['includeChildren']]; if ($settings['operator'] === 'AND' && $settings['includeChildren']) { $group = ['relation' => 'AND']; foreach ($current['values'] as $value) $group[] = array_merge($clause, ['terms' => [$value], 'operator' => 'IN']); $clause = $group; } // Native WP_Query composes the visitor taxonomy constraint with the saved query. // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query $query['tax_query'] = merge_fixed_group($query['tax_query'] ?? [], $clause); } } return $query; } function merge_fixed_group($existing, $clause) { return $existing ? ['relation' => 'AND', $existing, $clause] : [$clause]; }