get_terms
îmi dă terms dintr-o taxonomie, dar hide_empty
nu ajută foarte mult dacă vreau să afișez doar terms care au post-uri cu un anumit status.
Caz concret, am un post type jobs și taxonomie pentru categorii. Un job poate fi deschis sau nu, iar get_terms nu știe - sau cel puțin eu nu mi-am dat seama cum - să filtreze doar categoriile care au job-uri deschise (un meta_key job_is_open
cu valoarea 1).
Din fericire, terms_clauses
este destul de flexibil, prin urmare a ieșit asta:
<?php
$metaQuery = [
[
'key' => 'job_is_open',
'value' => 1,
'compare' => '=',
],
];
$categories = get_terms([
'taxonomy' => 'job-category',
'post_meta_query' => $metaQuery,
]);
add_filter('terms_clauses', function ($clauses, $tax, $args) {
if (!empty($args['post_meta_query'])) {
global $wpdb;
$clauses['fields'] .= ', p.ID, pm.* ';
if ($args['parent'] > 0) {
$join[] = " INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.parent";
} else {
$join[] = " INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = t.term_id";
}
$join[] = " INNER JOIN {$wpdb->posts} AS p ON p.ID = tr.object_id";
$join[] = " INNER JOIN {$wpdb->postmeta} AS pm on pm.post_id = p.ID";
$clauses['join'] .= implode(' ', $join);
foreach ($args['post_meta_query'] as $q) {
$clauses['where'] .= " AND pm.meta_key = '{$q['key']}' AND pm.meta_value {$q['compare']} '{$q['value']}' ";
}
$clauses['orderby'] = ' GROUP BY t.term_id ' . $clauses['orderby'];
}
return $clauses;
}, 10, 3);
Nu am apucat să testez în amănunt, dar la o primă vedere pare a merge bine. Rămâne de văzut dacă este și vreo problemă de performanță sau de compatibilitate cu alte plugin-uri.
Edit: este o problemă de caching, în sensul că schimbarea unui metafield nu va actualiza și numărul, ceea ce înseamnă că sunt șanse maxime să nu funcționeze chiar bine. Încă investighez.
Edit2: am actualizat interogările, acum pare în regulă. Nu știu cum funcționează pe DB-uri medii/mari. That’s a problem for a future me
Edit3: este o problemă la get_terms([ "parent" => xxx ])
. În stadiul actual, merge doar dacă un post are toată ierarhia de terms selectată, nu doar ultimul. Este suficient pentru ce am nevoie, posibil voi reveni asupra soluției în viitor.