РЕДАКТИРОВАТЬ:
У меня был относительно длинный ответ, который хорошо подходит для проверки дочерних терминов, но не очень хорошо для снятия отметки, когда родитель не проверен. Я поддержал этот ответ здесь: Оригинальный ответ: 60079535 (также доступен в История изменений ).
Новый ответ:
Хорошо Я очень горжусь этим результатом на самом деле. Проведя некоторые исследования, я наткнулся на хук set_object_terms
, который запускается в конце функции wp_set_object_terms()
, расположенной в /wp-includes/taxonomy.php
.
На этом хуке он принимает 6 аргументов: $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids
. Важными здесь для "проверки детей" и" un проверки детей" являются $tt_ids
и $old_tt_ids
. Это массивы новых идентификаторов терминов и старых идентификаторов терминов, соответственно.
Это позволяет нам сравнить два массива и посмотреть, какие идентификаторы были добавлены добавлены , а какие удалены . Это важно, потому что вы можете проверить Африку, затем снять флажок с Африки и теперь проверить Азию. Вот удобная функция, которая позволит вам увидеть оба различия:
function array_diff_once($a1, $a2){
foreach($a2 as $val){
if( false !== ($pos = array_search($val, $a1)) ){
unset($a1[$pos]);
}
}
return array_values($a1);
}
Таким образом, вместо использования хука save_post
, мы можем вместо этого сравнить добавленные / удаленные термины на хуке set_object_terms
и добавить / удалить дочерние термины для каждого там. Обратите внимание, что это также может срабатывать в неподходящее время (автосохранение, если публикация не опубликована и т. Д. c, поэтому я поставил несколько условий отмены.)
add_action( 'set_object_terms', 'so_60079535_toggle_child_terms', 10, 6 );
function so_60079535_toggle_child_terms( $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids ){
// Abort if this is an autosave/backup
if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return;
// Abort if no ids are set from before or now
if( empty($tt_ids) && empty($old_tt_ids) )
return;
// Only do things if this post is published (front facing)
$post_status = get_post_status( $object_id );
if( $post_status != 'publish' )
return;
// What terms where ADDED, and which were REMOVED?
$added_terms = array_diff_once( $tt_ids, $old_tt_ids );
$removed_terms = array_diff_once( $old_tt_ids, $tt_ids );
// Any terms ADDED this time?
if( !empty($added_terms) ){
foreach( $added_terms as $added_term ){
// Do any of these added terms have children?
if( $added_child_terms = get_term_children( $added_term, $taxonomy ) ){
// Append those children
wp_set_object_terms( $object_id, $added_child_terms, $taxonomy, true );
}
}
}
// Any terms REMOVED?
if( !empty($removed_terms) ){
foreach( $removed_terms as $removed_term ){
// Do any of the removed terms have children?
if( $removed_child_terms = get_term_children( $removed_term, $taxonomy ) ){
// Remove them all
wp_remove_object_terms( $object_id, $removed_child_terms, $taxonomy, true );
}
}
}
}
Я на самом деле разместите этот код на моем тестовом сайте, и он, кажется, работает безупречно, независимо от того, насколько глубоко (термины «внучка» / «великий внук») термины и сколько добавляется или удаляется одновременно. Еще одна приятная вещь - этот хук уже передан параметру $taxonomy
, поэтому он должен работать автоматически для всех без исключения таксономий, которые когда-либо добавлялись. Если это нежелательно, вы всегда можете очень легко добавить условие прерывания для некоторых таксономий, типов записей и т. Д. c.