Удаляем комментарии ветками
Предлагаю вниманию хук для удаления всех дочерних комментариев при удалении комментария, т.е. мы удаляем комментарий и вместе с ним удаляются все его дочерние комментарии, и дочерние дочерних, и так далее. Другими словами, при удалении комментария удалится вся ветка ответов на него.
Чтобы "удаление ветками" начало работать вставляем код в файл темы functions.php.
/* Удаление всех дочерних комментариев (всего дерева) при удалении комментария ---------------------------------------------------------------------------------- */ add_action('delete_comment', 'del_child_comments_on_del_comment'); function del_child_comments_on_del_comment($comment_id){ global $wpdb; // если нет детей, возвращаем if( !$child_comments = $wpdb->get_col("SELECT comment_ID FROM $wpdb->comments WHERE comment_parent='$comment_id'") ) return; foreach( $child_comments as $val ) wp_delete_comment($val); }
Ключевые моменты хука: фильтр - delete_comment
и функция - wp_delete_comment()
:
Над кодом я просидел прилично, потому что тут используется рекурсия, а она часто вредная и я с ней не очень...
В программировании рекурсия — вызов функции из неё же самой (простая рекурсия) или через другие функции (сложная или косвенная рекурсия). Например, функция A вызывает функцию B, а функция B — функцию A. Количество вложенных вызовов функции или процедуры называется глубиной рекурсии.
Сидел сначала и пробовал натурально использовать рекурсию (написал функцию, повесил её на хук и вызывал её из нее же самой) — что надо не выходило, а код только рос. В один момент, как только я пошел налить себе чайку, пришла её величество Эврика и я все понял: замыкание будет происходить при срабатывании хука delete_comment
в момент очередных вызовов функции wp_delete_comment()
и не надо вызывать функцию из функции в чистом виде, т.е. будет косвенная рекурсия.
Честно говоря, плохо могу себе представить реальную ситуацию, на обычном блоге, где бы такое удаление комментариев было особо нужно. Однако, оно логично и может кому-то понадобится. На этом блоге я сделал именно так, потому что, если удалить комментарий у которого есть дочерние комментарии, то смысл дочерних комментариев чаще всего будет просто потерян: будут комментарии не понятно о чем. Приводя аллегорию — это комментарии к посту, без самого поста. Думаю, мне такое тут не надо.
Перемещение в корзину
После того, как задача с удалением была решена, по проторенной дороге, я написал такое же перемещение комментариев ветками в корзину и извлечение их ветками из корзины.
Принцип тот же самый, только используются теперь фильтры: trash_comment
, untrash_comment
и функции: wp_trash_comment()
, wp_untrash_comment()
:
/* Перемещение в корзину всех дочерних комментариев (вся глубина дерева), при удалении комментария ---------------------------------------------------------------------------------------------------- */ add_action('trash_comment', 'trash_child_comments_on_trash_comment'); function trash_child_comments_on_trash_comment($comment_id){ global $wpdb; // если нет детей, возвращаем if( !$child_comments = $wpdb->get_col("SELECT comment_ID FROM $wpdb->comments WHERE comment_parent='$comment_id'") ) return; foreach( $child_comments as $val ) wp_trash_comment($val); } add_action('untrash_comment', 'untrash_child_comments_on_untrash_comment'); function untrash_child_comments_on_untrash_comment($comment_id){ global $wpdb; // если нет детей, возвращаем if( !$child_comments = $wpdb->get_col("SELECT comment_ID FROM $wpdb->comments WHERE comment_parent='$comment_id'") ) return; foreach( $child_comments as $val ) wp_untrash_comment($val); }
Упрощенная запись перемещения в корзину
Вот весьма интересный код, для тек кто разбирается в php: упрощенная версия записи для кода выше (для корзины). Здесь интересно посмотреть как можно использовать функцию current_filter() и необычный вызов функции PHP, динамичный, с использованием переменной ($use_function($val)
). В общем, смотрите сами:
/* Перемещение в корзину всех дочерних комментариев (вся глубина дереса), при удалении комментария ---------------------------------------------------------------------------------------------------- */ add_action('trash_comment', 'trash_untrash_child_comments_with_parent'); add_action('untrash_comment', 'trash_untrash_child_comments_with_parent'); function trash_untrash_child_comments_with_parent($comment_id){ global $wpdb; // если нет детей, возвращаем if( !$child_comments = $wpdb->get_col("SELECT comment_ID FROM $wpdb->comments WHERE comment_parent='$comment_id'") ) return; foreach( $child_comments as $val ){ // получим wp_trash_comment или wp_untrash_comment $use_function = 'wp_'. current_filter(); $use_function($val); } }