Удаляем комментарии ветками
Предлагаю вниманию хук для удаления всех дочерних комментариев при удалении комментария, т.е. мы удаляем комментарий и вместе с ним удаляются все его дочерние комментарии, и дочерние дочерних, и так далее. Другими словами, при удалении комментария удалится вся ветка ответов на него.
Чтобы "удаление ветками" начало работать вставляем код в файл темы functions.php.
/** * Удаление всех дочерних комментариев (всего дерева) при удалении комментария */ add_action( 'delete_comment', 'del_child_comments_on_del_comment' ); function del_child_comments_on_del_comment( $comment_id ) { global $wpdb; $child_comments = $wpdb->get_col( "SELECT comment_ID FROM $wpdb->comments WHERE comment_parent='$comment_id'" ); // если нет детей, возвращаем if( ! $child_comments ){ 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; // если нет детей, возвращаем $child_comments = $wpdb->get_col( "SELECT comment_ID FROM $wpdb->comments WHERE comment_parent='$comment_id'" ); if( ! $child_comments ){ 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; // если нет детей, возвращаем $child_comments = $wpdb->get_col( "SELECT comment_ID FROM $wpdb->comments WHERE comment_parent='$comment_id'" ); if( ! $child_comments ){ 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; // если нет детей, возвращаем $child_comments = $wpdb->get_col( "SELECT comment_ID FROM $wpdb->comments WHERE comment_parent='$comment_id'" ); if( ! $child_comments ){ return; } foreach( $child_comments as $val ){ // получим wp_trash_comment или wp_untrash_comment $use_function = 'wp_' . current_filter(); $use_function( $val ); } }