Как объединить рейтинг поста в мультиязычном сайте (Polylang)?
Привет!
Может кто-то сталкивался проблемой и решил её...
Делаю мультиязычный сайт на WordPress с помощью плагина Polylang. Мне нужно было объединить комментарии переводов страницы. Я использовал плагин Polylang Comments Merger. Он со свой задачей справился. Содержимое плагина:
// Safety check add_action( 'admin_init', 'rbnet_test_polylang_installation' ); function rbnet_test_polylang_installation() { if ( is_admin() && current_user_can( 'activate_plugins' ) && !is_plugin_active( 'polylang-pro/polylang.php' ) ) { add_action( 'admin_notices', 'rbnet_plugin_notice' ); deactivate_plugins( plugin_basename( __FILE__ ) ); if ( isset( $_GET['activate'] ) ) { unset( $_GET['activate'] ); } } } function rbnet_plugin_notice() { $class = 'notice notice-error'; $message = __( '<strong>Polylang Comments Merger</strong> requires <strong>Polylang</strong> plugin to be installed and active.', 'rbnet-pcmerger' ); printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), esc_html( $message ) ); } // Define constants if ( !defined( 'RBNETPM_BASE' ) ) { define( 'RBNETPM_BASE', plugin_basename( __FILE__ ) ); } // Load plugin textdomain if ( !function_exists( 'rbnet_load_textdomain' ) ) { function rbnet_load_textdomain() { $path = dirname( plugin_basename( __FILE__ ) ) . '/languages/'; load_plugin_textdomain( 'rbnet-pcmerger', false, $path ); } add_action( 'init', 'rbnet_load_textdomain' ); } // Sort merged comments function sort_merged_comments($a, $b) { return $a->comment_ID - $b->comment_ID; } // Merge comments on frontend function merge_comments($comments, $post_ID) { global $polylang; $translationIds = PLL()->model->post->get_translations($post_ID); foreach ( $translationIds as $key=>$translationID ){ if( $translationID != $post_ID ) { $translatedPostComments = get_comments( array('post_id' => $translationID, 'status' => 'approve', 'order' => 'ASC') ); if ( $translatedPostComments ) { $comments = array_merge($comments, $translatedPostComments); } } } // re-sort merged comment array if ( count($translationIds) >1 ) { usort($comments, 'sort_merged_comments'); } return $comments; } add_filter('comments_array', 'merge_comments', 100, 2); // Count merged comments - In AdminCP leaves comments per translations function merge_comment_count($count, $post_ID) { if ( !is_admin() ){ global $polylang; $translationIds = PLL()->model->post->get_translations($post_ID); foreach ( $translationIds as $key=>$translationID ){ if( $translationID != $post_ID ) { $translatedPost = get_post($translationID); if ( $translatedPost ) { $count = $count + $translatedPost->comment_count; } } } } return $count; } add_filter('get_comments_number', 'merge_comment_count', 100, 2); // Stop Polylang filtering comments function polylang_remove_comments_filter() { global $polylang; remove_filter('comments_clauses', array(&$polylang->filters, 'comments_clauses')); } add_action('wp','polylang_remove_comments_filter'); // Add custom meta link on plugin list page if ( !function_exists( 'rbnet_meta_links' ) ) { function rbnet_meta_links( $links, $file ) { if ( $file == RBNETPM_BASE ) { $links[] = '<a href="https://www.paypal.me/RobertoBolli/2" target="_blank" title="' . __( 'Donate', 'rbnet-pcmerger' ) . '"><strong>' . __( 'Donate', 'rbnet-pcmerger' ) . '</strong></a>'; } return $links; } add_filter( 'plugin_row_meta', 'rbnet_meta_links', 10, 2 ); } |
// Safety check add_action( 'admin_init', 'rbnet_test_polylang_installation' ); function rbnet_test_polylang_installation() { if ( is_admin() && current_user_can( 'activate_plugins' ) && !is_plugin_active( 'polylang-pro/polylang.php' ) ) { add_action( 'admin_notices', 'rbnet_plugin_notice' ); deactivate_plugins( plugin_basename( __FILE__ ) ); if ( isset( $_GET['activate'] ) ) { unset( $_GET['activate'] ); } } } function rbnet_plugin_notice() { $class = 'notice notice-error'; $message = __( '<strong>Polylang Comments Merger</strong> requires <strong>Polylang</strong> plugin to be installed and active.', 'rbnet-pcmerger' ); printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), esc_html( $message ) ); } // Define constants if ( !defined( 'RBNETPM_BASE' ) ) { define( 'RBNETPM_BASE', plugin_basename( __FILE__ ) ); } // Load plugin textdomain if ( !function_exists( 'rbnet_load_textdomain' ) ) { function rbnet_load_textdomain() { $path = dirname( plugin_basename( __FILE__ ) ) . '/languages/'; load_plugin_textdomain( 'rbnet-pcmerger', false, $path ); } add_action( 'init', 'rbnet_load_textdomain' ); } // Sort merged comments function sort_merged_comments($a, $b) { return $a->comment_ID - $b->comment_ID; } // Merge comments on frontend function merge_comments($comments, $post_ID) { global $polylang; $translationIds = PLL()->model->post->get_translations($post_ID); foreach ( $translationIds as $key=>$translationID ){ if( $translationID != $post_ID ) { $translatedPostComments = get_comments( array('post_id' => $translationID, 'status' => 'approve', 'order' => 'ASC') ); if ( $translatedPostComments ) { $comments = array_merge($comments, $translatedPostComments); } } } // re-sort merged comment array if ( count($translationIds) >1 ) { usort($comments, 'sort_merged_comments'); } return $comments; } add_filter('comments_array', 'merge_comments', 100, 2); // Count merged comments - In AdminCP leaves comments per translations function merge_comment_count($count, $post_ID) { if ( !is_admin() ){ global $polylang; $translationIds = PLL()->model->post->get_translations($post_ID); foreach ( $translationIds as $key=>$translationID ){ if( $translationID != $post_ID ) { $translatedPost = get_post($translationID); if ( $translatedPost ) { $count = $count + $translatedPost->comment_count; } } } } return $count; } add_filter('get_comments_number', 'merge_comment_count', 100, 2); // Stop Polylang filtering comments function polylang_remove_comments_filter() { global $polylang; remove_filter('comments_clauses', array(&$polylang->filters, 'comments_clauses')); } add_action('wp','polylang_remove_comments_filter'); // Add custom meta link on plugin list page if ( !function_exists( 'rbnet_meta_links' ) ) { function rbnet_meta_links( $links, $file ) { if ( $file == RBNETPM_BASE ) { $links[] = '<a href="https://www.paypal.me/RobertoBolli/2" target="_blank" title="' . __( 'Donate', 'rbnet-pcmerger' ) . '"><strong>' . __( 'Donate', 'rbnet-pcmerger' ) . '</strong></a>'; } return $links; } add_filter( 'plugin_row_meta', 'rbnet_meta_links', 10, 2 ); }
Для оценки поста перед формой комментариев используется данный плагин:
//Enqueue the plugin's styles. add_action( 'wp_enqueue_scripts', 'wpp_comment_rating_styles' ); function wpp_comment_rating_styles() { wp_register_style( 'wpp-comment-rating-styles', plugins_url( '/', __FILE__ ) . 'assets/style.css' ); wp_enqueue_style( 'dashicons' ); } //Create the rating interface. add_action( 'comment_form_logged_in_after', 'wpp_comment_rating_rating_field' ); add_action( 'comment_form_before_fields', 'wpp_comment_rating_rating_field' ); function wpp_comment_rating_rating_field () { ?> <p><?php pll_e('Rate this excursion'); ?></p> <fieldset class="comments-rating"> <span class="rating-container"> <?php for ($i = 5;$i >= 1;$i--): ?> <input type="radio" id="rating-<?php echo esc_attr($i); ?>" name="rating" value="<?php echo esc_attr($i); ?>"> <label for="rating-<?php echo esc_attr($i); ?>" id="rating-<?php echo esc_attr($i); ?>"><?php echo esc_html($i); ?></label> <?php endfor; ?> <input type="radio" id="rating-0" class="star-cb-clear" name="rating" value="0" /><label for="rating-0">0</label> </span> </fieldset> <?php } //Save the rating submitted by the user. add_action('comment_post', 'wpp_comment_rating_save_comment_rating'); function wpp_comment_rating_save_comment_rating($comment_id) { if ((isset($_POST['rating'])) && ('' !== $_POST['rating'])) $rating = intval($_POST['rating']); add_comment_meta($comment_id, 'rating', $rating); } //Display the rating on a submitted comment. add_filter('comment_text', 'wpp_comment_rating_display_rating'); function wpp_comment_rating_display_rating($comment_text) { if ($rating = get_comment_meta(get_comment_ID() , 'rating', true)) { $stars = '<div class="stars">'; for ($i = 1;$i <= $rating;$i++) { $stars .= '<span class="dashicons dashicons-star-filled yellow" style="color:#ffbc00"></span>'; } if ($rating < 5) { for ($i = $rating;$i < 5;$i++) { $stars .= '<span class="dashicons dashicons-star-filled grey" style="color:#ddd"></span>'; } } $stars .= '</div>'; $comment_text = $stars . $comment_text; return $comment_text; } else { return $comment_text; } } //Get the average rating of a post. function wpp_comment_rating_get_average_ratings( $id ) { $comments = get_approved_comments( $id ); if ( $comments ) { $i = 0; $total = 0; foreach( $comments as $comment ){ $rate = get_comment_meta( $comment->comment_ID, 'rating', true ); if( isset( $rate ) && '' !== $rate ) { $i++; $total += $rate;} } if ( 0 === $i ) { return false; } else { return round( $total / $i, 1 ); } } else { return false; } } //Display the average rating above the content. add_shortcode( 'comment_displaying_average_rating', 'wpp_comment_rating_display_average_rating' ); function wpp_comment_rating_display_average_rating( $content ) { global $post; if ( false === wpp_comment_rating_get_average_ratings( $post->ID ) ) { return $content; } $stars = ''; $average = wpp_comment_rating_get_average_ratings( $post->ID ); for ( $i = 1; $i <= $average + 1; $i++ ) { $width = intval( $i - $average > 0 ? 20 - ( ( $i - $average ) * 20 ) : 20 ); if ( 0 === $width ) {continue;} $stars .= '<span style="overflow:hidden; width:' . $width . 'px" class="dashicons dashicons-star-filled"></span>'; if ( $i - $average > 0 ) { $stars .= '<span style="overflow:hidden; position:relative; left:-' . $width .'px;" class="dashicons dashicons-star-empty"></span>'; } } $custom_content = '<span class="average-rating">'. $stars .' <strong>'.$average .'</strong></span>'; $custom_content .= $content; return $custom_content; } |
//Enqueue the plugin's styles. add_action( 'wp_enqueue_scripts', 'wpp_comment_rating_styles' ); function wpp_comment_rating_styles() { wp_register_style( 'wpp-comment-rating-styles', plugins_url( '/', __FILE__ ) . 'assets/style.css' ); wp_enqueue_style( 'dashicons' ); } //Create the rating interface. add_action( 'comment_form_logged_in_after', 'wpp_comment_rating_rating_field' ); add_action( 'comment_form_before_fields', 'wpp_comment_rating_rating_field' ); function wpp_comment_rating_rating_field () { ?> <p><?php pll_e('Rate this excursion'); ?></p> <fieldset class="comments-rating"> <span class="rating-container"> <?php for ($i = 5;$i >= 1;$i--): ?> <input type="radio" id="rating-<?php echo esc_attr($i); ?>" name="rating" value="<?php echo esc_attr($i); ?>"> <label for="rating-<?php echo esc_attr($i); ?>" id="rating-<?php echo esc_attr($i); ?>"><?php echo esc_html($i); ?></label> <?php endfor; ?> <input type="radio" id="rating-0" class="star-cb-clear" name="rating" value="0" /><label for="rating-0">0</label> </span> </fieldset> <?php } //Save the rating submitted by the user. add_action('comment_post', 'wpp_comment_rating_save_comment_rating'); function wpp_comment_rating_save_comment_rating($comment_id) { if ((isset($_POST['rating'])) && ('' !== $_POST['rating'])) $rating = intval($_POST['rating']); add_comment_meta($comment_id, 'rating', $rating); } //Display the rating on a submitted comment. add_filter('comment_text', 'wpp_comment_rating_display_rating'); function wpp_comment_rating_display_rating($comment_text) { if ($rating = get_comment_meta(get_comment_ID() , 'rating', true)) { $stars = '<div class="stars">'; for ($i = 1;$i <= $rating;$i++) { $stars .= '<span class="dashicons dashicons-star-filled yellow" style="color:#ffbc00"></span>'; } if ($rating < 5) { for ($i = $rating;$i < 5;$i++) { $stars .= '<span class="dashicons dashicons-star-filled grey" style="color:#ddd"></span>'; } } $stars .= '</div>'; $comment_text = $stars . $comment_text; return $comment_text; } else { return $comment_text; } } //Get the average rating of a post. function wpp_comment_rating_get_average_ratings( $id ) { $comments = get_approved_comments( $id ); if ( $comments ) { $i = 0; $total = 0; foreach( $comments as $comment ){ $rate = get_comment_meta( $comment->comment_ID, 'rating', true ); if( isset( $rate ) && '' !== $rate ) { $i++; $total += $rate;} } if ( 0 === $i ) { return false; } else { return round( $total / $i, 1 ); } } else { return false; } } //Display the average rating above the content. add_shortcode( 'comment_displaying_average_rating', 'wpp_comment_rating_display_average_rating' ); function wpp_comment_rating_display_average_rating( $content ) { global $post; if ( false === wpp_comment_rating_get_average_ratings( $post->ID ) ) { return $content; } $stars = ''; $average = wpp_comment_rating_get_average_ratings( $post->ID ); for ( $i = 1; $i <= $average + 1; $i++ ) { $width = intval( $i - $average > 0 ? 20 - ( ( $i - $average ) * 20 ) : 20 ); if ( 0 === $width ) {continue;} $stars .= '<span style="overflow:hidden; width:' . $width . 'px" class="dashicons dashicons-star-filled"></span>'; if ( $i - $average > 0 ) { $stars .= '<span style="overflow:hidden; position:relative; left:-' . $width .'px;" class="dashicons dashicons-star-empty"></span>'; } } $custom_content = '<span class="average-rating">'. $stars .' <strong>'.$average .'</strong></span>'; $custom_content .= $content; return $custom_content; }
В чем заключается проблема?
Шорткод вывода оценки работает только на той странице перевода, где была сделана оценка. На других страницах перевода пусто. Я полагая, что страницы имеют разные ID. Как можно это пофиксить?
Заранее благодарю!
Дополнительно:
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Если Polylang объединяет комментарии переводов, рейтинг поста всё равно может считаться отдельно, потому что многие рейтинговые плагины хранят оценки в post meta конкретного post ID. Комментарии можно объединить выводом, но meta вроде
ratings_averageиratings_usersостанется у каждого перевода своя.Есть два подхода.
Первый — показывать рейтинг главного языка для всех переводов. Получаете translation group, выбираете базовый post ID и выводите рейтинг от него. Это проще, но все оценки физически пишутся в один пост.
Второй — пересчитывать общий рейтинг по всем переводам. Нужно получить ID переводов через Polylang:
$translations = function_exists('pll_get_post_translations') ? pll_get_post_translations(get_the_ID()) : []; $post_ids = array_map('absint', array_values($translations));
Дальше зависит от плагина рейтинга. Если рейтинг хранится в комментариях как meta
rating, можно собрать отзывы по всем post ID и посчитать среднее. Если рейтинг хранится в собственной таблице или post meta, нужно читать именно эти данные.Для WooCommerce reviews общий рейтинг можно считать по комментариям:
$comments = get_comments([ 'post__in' => $post_ids, 'status' => 'approve', 'type' => 'review', ]); $sum = 0; $count = 0; foreach ($comments as $comment) { $rating = (int) get_comment_meta($comment->comment_ID, 'rating', true); if ($rating > 0) { $sum += $rating; $count++; } } $average = $count ? $sum / $count : 0;
Итог: универсального “объединить рейтинг Polylang” нет, потому что рейтинг зависит от конкретного плагина. Сначала выясните, где хранятся оценки, затем либо выводите рейтинг базового перевода, либо пересчитывайте общий рейтинг по всем ID переводов.