woocommerce_wpml = $woocommerce_wpml; $this->sitepress = $sitepress; $this->post_translations = $post_translations; $this->wpdb = $wpdb; } public function add_hooks() { add_action( 'wp_insert_comment', [ $this, 'add_comment_rating' ] ); add_action( 'woocommerce_review_before_comment_meta', [ $this, 'add_comment_flag' ], 9 ); add_action( 'woocommerce_review_before_comment_text', [ $this, 'open_lang_div' ] ); add_action( 'woocommerce_review_after_comment_text', [ $this, 'close_lang_div' ] ); add_action( 'added_comment_meta', [ $this, 'maybe_duplicate_comment_rating' ], 10, 4 ); add_filter( 'get_post_metadata', [ $this, 'filter_average_rating' ], 10, 4 ); add_filter( 'comments_clauses', [ $this, 'comments_clauses' ], 10, 2 ); add_action( 'comment_form_before', [ $this, 'comments_link' ] ); add_filter( 'wpml_is_comment_query_filtered', [ $this, 'is_comment_query_filtered' ], 10, 3 ); add_action( 'trashed_comment', [ $this, 'recalculate_average_rating_on_comment_hook' ], 10, 2 ); add_action( 'deleted_comment', [ $this, 'recalculate_average_rating_on_comment_hook' ], 10, 2 ); add_action( 'untrashed_comment', [ $this, 'recalculate_average_rating_on_comment_hook' ], 10, 2 ); // before WCML_Synchronize_Product_Data::sync_product_translations_visibility hook. add_action( 'woocommerce_product_set_visibility', Fns::withoutRecursion( Fns::noop(), [ $this, 'recalculate_comment_rating' ] ), 9 ); if ( ! defined( 'WPSEO_VERSION' ) && 'all' === WPML\FP\Obj::prop( 'clang', $_GET ) && ! $this->is_reviews_in_all_languages_by_default_selected() ) { add_action( 'wp_head', [ $this, 'no_index_all_reviews_page' ], 10 ); } add_filter( 'woocommerce_top_rated_products_widget_args', [ $this, 'top_rated_products_widget_args' ] ); add_filter( 'woocommerce_rating_filter_count', [ $this, 'woocommerce_rating_filter_count' ], 10, 3 ); add_filter( 'the_comments', [ $this, 'translate_product_ids' ] ); } /** * Add comment rating * * @param int $comment_id */ public function add_comment_rating( $comment_id ) { if ( isset( $_POST['comment_post_ID'] ) ) { $product_id = sanitize_text_field( $_POST['comment_post_ID'] ); if ( 'product' === get_post_type( $product_id ) ) { $this->recalculate_comment_rating( $product_id ); } } } /** * Calculate rating field for comments based on reviews in all languages. * * @param int $product_id */ public function recalculate_comment_rating( $product_id ) { $translations = $this->post_translations->get_element_translations( $product_id ); $average_ratings_sum = 0; $average_ratings_count = 0; $reviews_count = 0; $ratings_count = []; foreach ( $translations as $translation ) { $product = wc_get_product( $translation ); if ( ! $product ) { continue; } $ratings = WC_Comments::get_rating_counts_for_product( $product ); $review_count = WC_Comments::get_review_count_for_product( $product ); if ( is_array( $ratings ) ) { foreach ( $ratings as $rating => $count ) { $average_ratings_sum += $rating * $count; $average_ratings_count += $count; if ( isset( $ratings_count[ $rating ] ) ) { $ratings_count[ $rating ] += $count; } else { $ratings_count[ $rating ] = $count; } } } if ( $review_count ) { $reviews_count += $review_count; } else { update_post_meta( $translation, self::WCML_AVERAGE_RATING_KEY, null ); update_post_meta( $translation, self::WCML_REVIEW_COUNT_KEY, null ); update_post_meta( $translation, self::WCML_RATING_COUNT_KEY, null ); } } if ( $average_ratings_sum ) { $average_rating = number_format( $average_ratings_sum / $average_ratings_count, 2, '.', '' ); foreach ( $translations as $translation ) { update_post_meta( $translation, self::WCML_AVERAGE_RATING_KEY, $average_rating ); update_post_meta( $translation, self::WCML_REVIEW_COUNT_KEY, $reviews_count ); update_post_meta( $translation, self::WCML_RATING_COUNT_KEY, $ratings_count ); WC_Comments::clear_transients( $translation ); } } } /** * Filter WC reviews meta. * * @param null|array|string $value get_metadata() should return a single value or array of values. * @param int $object_id Post ID. * @param string $meta_key Meta key. * @param bool $single * * @return array|null|string Filtered metadata value, array of values, or null. */ public function filter_average_rating( $value, $object_id, $meta_key, $single ) { $filtered_value = $value; if ( in_array( $meta_key, [ self::WC_AVERAGE_RATING_KEY, self::WC_REVIEW_COUNT_KEY, self::WC_RATING_COUNT_KEY ], true ) && 'product' === get_post_type( $object_id ) ) { if ( ! metadata_exists( 'post', $object_id, self::WCML_RATING_COUNT_KEY ) ) { $this->recalculate_comment_rating( $object_id ); } switch ( $meta_key ) { case self::WC_AVERAGE_RATING_KEY: $filtered_value = get_post_meta( $object_id, self::WCML_AVERAGE_RATING_KEY, $single ); if ( empty( $filtered_value ) ) { $filtered_value = 0; } break; case self::WC_REVIEW_COUNT_KEY: if ( $this->is_reviews_in_all_languages( $object_id ) ) { $filtered_value = get_post_meta( $object_id, self::WCML_REVIEW_COUNT_KEY, $single ); } break; case self::WC_RATING_COUNT_KEY: $filtered_value = get_post_meta( $object_id, self::WCML_RATING_COUNT_KEY, $single ); if ( $single ) { $filtered_value = [ $filtered_value ]; } break; } } return ! empty( $filtered_value ) || $filtered_value === 0 ? $filtered_value : $value; } /** * Filters comment queries to display in all languages if needed * * @param string[] $clauses * @param WP_Comment_Query $obj * * @return string[] */ public function comments_clauses( $clauses, $obj ) { if ( $this->is_reviews_in_all_languages( $obj->query_vars['post_id'] ) ) { $ids = $this->get_translations_ids( $obj->query_vars['post_id'] ); $clauses['where'] = str_replace( 'comment_post_ID = ' . $obj->query_vars['post_id'], 'comment_post_ID IN (' . DB::prepareIn( $ids, '%d' ) . ')', $clauses['where'] ); } return $clauses; } /** * Get list of translated ids for product * * @param int $product_id * * @return array */ private function get_translations_ids( $product_id ) { $translations = $this->post_translations->get_element_translations( $product_id ); return array_filter( $translations ); } /** * Display link to show rating in all/current language */ public function comments_link() { if ( is_product() ) { if ( $this->is_reviews_in_all_languages( get_the_ID() ) ) { $this->show_link_to_current_language_reviews(); } else { $this->show_link_to_all_reviews(); } } } /** * @return bool */ private function is_reviews_in_all_languages_by_default_selected() { return (bool) $this->woocommerce_wpml->get_setting( 'reviews_in_all_languages', false ); } /** * Echoes link to product page with all reviews. */ private function show_link_to_all_reviews() { $comments_link = add_query_arg( [ 'clang' => 'all' ] ); $all_languages_reviews_count = $this->get_reviews_count( 'all' ); $current_language_reviews_count = $this->get_reviews_count(); if ( $all_languages_reviews_count > $current_language_reviews_count ) { /* translators: %s is the number of reviews */ $comments_link_text = sprintf( __( 'Show reviews in all languages (%s)', 'woocommerce-multilingual' ), $all_languages_reviews_count ); echo '
'; } } /** * Echoes link to product page with reviews in current language. */ private function show_link_to_current_language_reviews() { $current_language_reviews_count = $this->get_reviews_count(); $current_language = $this->sitepress->get_current_language(); $comments_link = add_query_arg( [ 'clang' => $current_language ] ); $language_details = $this->sitepress->get_language_details( $current_language ); /* translators: %1$s is a language name and %2$s is the number of reviews */ $comments_link_text = sprintf( __( 'Show only reviews in %1$s (%2$s)', 'woocommerce-multilingual' ), $language_details['display_name'], $current_language_reviews_count ); echo ''; } /** * Checks if comments needs filtering by language. * * @param bool $filtered * @param int $post_id * @param WP_Comment_Query $comment_query * @return bool */ public function is_comment_query_filtered( $filtered, $post_id, $comment_query = null ) { if ( $this->is_reviews_in_all_languages( $post_id, $comment_query ) ) { $filtered = false; } return $filtered; } /** * Add flag to comment description * * @param WP_Comment $comment */ public function add_comment_flag( $comment ) { $comment_language = $this->get_comment_language_on_all_languages_reviews( $comment ); if ( $comment_language ) { printf( '