fix(admin): replicate reference advanced-filter settings page 1:1

- Rewrite post_list/filter schema (PHP + JS) with the reference theme's
  field set, order, defaults and dependencies; topics fields excluded
  (no topics taxonomy), AKSRT private filter_* toggles dropped
- Support dynamic checkbox options in AksField (options as formData key)
  so cat_custom_filter.custom_filters lists the custom_filter dimensions
- Map PostDisplay filter settings to the new keys without legacy fallback;
  cat_custom_filter now carries lists/dropdown fieldsets and array filters
- Wire the archive chain to reference semantics: cat_custom_filter
  overrides per-category filter projects, custom_filter_show gates the
  default display, dimension chip groups render on category/tag archives
- Filter archive queries (main query + AJAX endpoint) by _aksrt_cf_{key}
  meta with exact-quoted LIKE matching
- Add advanced-filter settings reference contract test
This commit is contained in:
2026-09-24 15:39:25 +08:00
parent 4d6b2c6045
commit a8060fa71d
16 changed files with 635 additions and 154 deletions
+68
View File
@@ -262,3 +262,71 @@ if (!function_exists('aksrt_archive_render_filter_bar')) :
<?php
}
endif;
if (!function_exists('aksrt_archive_build_custom_filter_groups')) :
/**
* Build custom advanced-filter dimension groups.
*
* Reference: zib_get_option_custom_filter_but — one labeled chip group per
* dimension; when a value is active an extra "all" chip prepends to clear it.
*
* @param array<int,array<string,mixed>> $dimensions Dimension definitions (custom_filter settings).
* @param mixed $keys 'all' or list of enabled dimension keys.
* @param bool $ajax Attach AJAX attributes.
* @return array<int,array<string,mixed>>
*/
function aksrt_archive_build_custom_filter_groups(array $dimensions, $keys, bool $ajax): array {
$groups = [];
foreach ($dimensions as $dimension) {
$dim_key = sanitize_key((string) ($dimension['key'] ?? ''));
$dim_name = sanitize_text_field((string) ($dimension['name'] ?? $dim_key));
$vals = is_array($dimension['vals'] ?? null) ? $dimension['vals'] : [];
if ($dim_key === '' || $vals === []) {
continue;
}
if ($keys !== 'all' && !in_array($dim_key, (array) $keys, true)) {
continue;
}
$current = isset($_GET[$dim_key]) ? sanitize_key(wp_unslash((string) $_GET[$dim_key])) : '';
$chips = [];
$has_focus = false;
foreach ($vals as $val) {
$value_key = sanitize_key((string) ($val['key'] ?? ''));
$value_name = sanitize_text_field((string) ($val['name'] ?? $value_key));
if ($value_key === '') {
continue;
}
$is_active = $current === $value_key;
$chips[] = [
'label' => $value_name,
'url' => $is_active
? remove_query_arg([$dim_key, 'paged'])
: add_query_arg([$dim_key => $value_key], remove_query_arg('paged')),
'active' => $is_active,
'attrs' => $ajax ? ' data-filter-dim="' . esc_attr($dim_key) . '" data-filter-dim-value="' . esc_attr($value_key) . '"' : '',
];
if ($is_active) {
$has_focus = true;
}
}
if ($chips === []) {
continue;
}
if ($has_focus) {
array_unshift($chips, [
'label' => __('全部', 'aksrt'),
'url' => remove_query_arg([$dim_key, 'paged']),
'active' => false,
'attrs' => $ajax ? ' data-filter-dim="' . esc_attr($dim_key) . '" data-filter-dim-value=""' : '',
]);
}
$groups[] = [
'label' => $dim_name,
'chips' => $chips,
];
}
return $groups;
}
endif;