Добавляем рейтинг записей к родной системе комментирования WordPress

Рейтинг в виде звездочек – самый быстрый и простой способ получить обратную связь от ваших пользователей, потому он и стал таким популярным во всем мире. Сегодня мы расширим комментарии WordPress путем добавления к ним рейтинговой системы.

Основной файл плагина

Давайте создадим основной файл, который будет содержать код нашего плагина. С помощью FTP-клиента перейдите в /wp-content/plugins/ в вашей установке WordPress и создайте папку под названием ci-comment-rating (или любую другую на ваше усмотрение). Затем войдите в папку и создайте в ней файл ci-comment-rating.php (тоже можете назвать на свое усмотрение).

Вставьте в файл следующий код:

<?php
/*
Plugin Name: CI Comment Rating
Description: Adds a star rating system to WordPress comments
Version: 1.0.0
Author: The CSSIgniter Team
Author URI: https://cssigniter.com/
*/

Создание интерфейса для рейтинга

Нам нужно создать интерфейс, который будет использовать посетитель для выставления рейтинга к нашей записи. Чтобы сделать это, используйте код:

//Create the rating interface.
add_action( 'comment_form_logged_in_after', 'ci_comment_rating_rating_field' );
add_action( 'comment_form_after_fields', 'ci_comment_rating_rating_field' );
function ci_comment_rating_rating_field () {
	?>
	<label for="rating">Rating<span class="required">*</span></label>
	
<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 ); ?>"><?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
}

Код выше поможет нам поместить систему рейтинга в форму комментариев – как для зарегистрированных пользователей, так и для незарегистрированных. Вот как рейтинг будет выглядеть после добавления кода:

Пока не очень красиво.

 Добавляем стилизацию

Нам нужны звездочки, поскольку наша система рейтинга использует их для оценки постов. Вставим иконки в наш интерфейс. Также нам нужно будет создать папку с ресурсами (назовем ее assets) в главной папке с плагином и внутри нее создать файл style.css. Отредактируем style.css и вставим код:

.comments-rating {
	border: none;
	padding: 0;
	margin-left: 0;
}

.comments-rating label {
	display: inline-block;
}

.rating-container {
	/* remove inline-block whitespace */
	font-size: 0;
	/* flip the order so we can use the + and ~ combinators */
	unicode-bidi: bidi-override;
	direction: rtl;
}

.rating-container * {
	font-size: 1.4rem;
}

.rating-container > input {
	display: none;
}

.rating-container > input + label {
	/* only enough room for the star */
	font-family: 'dashicons';
	display: inline-block;
	overflow: hidden;
	text-indent: 9999px;
	width: 1em;
	white-space: nowrap;
	cursor: pointer;
	margin: 0;
}

.rating-container > input + label:before {
	display: inline-block;
	text-indent: -9999px;
	content: "\f154";
	color: #888;
}

.rating-container > input:checked ~ label:before,
.rating-container > input + label:hover ~ label:before,
.rating-container > input + label:hover:before {
	content: "\f155";
	color: #e52;
	text-shadow: 0 0 1px #333;
}

.rating-container > .star-cb-clear + label {
	text-indent: -9999px;
	width: .5em;
	margin-left: -.5em;
}

.rating-container > .star-cb-clear + label:before {
	width: .5em;
}

.rating-container:hover > input + label:before {
	content: "\f154";
	color: #888;
	text-shadow: none;
}

.rating-container:hover > input + label:hover ~ label:before,
.rating-container:hover > input + label:hover:before {
	content: "\f155";
	color: #e52;
	text-shadow: 0 0 1px #333;
}

Идем обратно к ci-comment-rating.php и добавляем:

//Enqueue the plugin's styles.
add_action( 'wp_enqueue_scripts', 'ci_comment_rating_styles' );
function ci_comment_rating_styles() {

	wp_register_style( 'ci-comment-rating-styles', plugins_url(/,__FILE__) . 'assets/style.css' );

	wp_enqueue_style( 'dashicons' );
	wp_enqueue_style( 'ci-comment-rating-styles' );
}

Сначала мы регистрируем файл style.css, созданный ранее, после чего ставим в очередь иконки и таблицу стилей. Сохраняем код и обновляем страницу.

Гораздо лучше.

Сохраняем пользовательский ввод

Интерфейс готов. Теперь нам надо убедиться, что пользовательский рейтинг сохраняется в базу данных. Для этого мы будем использовать add_comment_meta, чтобы создать произвольное поле, которое будет хранить наши данные рейтинга. Вставьте код в главный файл плагина:

//Save the rating submitted by the user.
add_action( 'comment_post', 'ci_comment_rating_save_comment_rating' );
function ci_comment_rating_save_comment_rating( $comment_id ) {
	if ( ( isset( $_POST['rating'] ) ) && ( '' !== $_POST['rating'] ) )
	$rating = intval( $_POST['rating'] );
	add_comment_meta( $comment_id, 'rating', $rating );
}

В коде выше мы сцепляемся с хуком comment_post, который запускается в момент отправки комментария. Мы проверяем, добавил ли пользователь рейтинг, чистим его, после чего сохраняем в базу данных.

Делаем рейтинг обязательным (опциональный шаг)

Если вы хотите, чтобы пользователи всегда передавали рейтинг вместе с комментариями, то в таком случае добавьте следующий код в главный файл плагина:

//Make the rating required.
add_filter( 'preprocess_comment', 'ci_comment_rating_require_rating' );
function ci_comment_rating_require_rating( $commentdata ) {
	if ( ! isset( $_POST['rating'] ) || 0 === intval( $_POST['rating'] ) )
	wp_die( __( 'Error: You did not add a rating. Hit the Back button on your Web browser and resubmit your comment with a rating.' ) );
	return $commentdata;
}

Здесь мы проверяем, имеется ли рейтинг в отправленном комментарии, и если нет, то выводим ошибку, предлагающую пользователю вернуться назад и повторно отправить комментарий вместе с рейтингом. Это, конечно же, опциональный шаг.

Совет: если вы не хотите, чтобы рейтинг был обязательным, удалите фрагмент:

<span class="required">*</span>

В итоге визуальный сигнал о том, что рейтинг обязателен, будет удален.

Вывод рейтинга в отправленном комментарии

Как только пользователь оценил ваш пост, нам нужно вывести рейтинг вместе с комментарием. Для этого вставьте следующий код в главный файл плагина:

//Display the rating on a submitted comment.
add_filter( 'comment_text', 'ci_comment_rating_display_rating');
function ci_comment_rating_display_rating( $comment_text ){

	if ( $rating = get_comment_meta( get_comment_ID(), 'rating', true ) ) {
		$stars = '

';
		for ( $i = 1; $i <= $rating; $i++ ) {
			$stars .= '<span class="dashicons dashicons-star-filled"></span>';
		}
		$stars .= '

';
		$comment_text = $comment_text . $stars;
		return $comment_text;
	} else {
		return $comment_text;
	}
}

Что мы делаем тут: мы сцепляемся с comment_text, проверяем, есть ли фактический рейтинг, и если да, то генерируем разметку для вывода рейтинга. Если рейтинга нет, то просто возвращаем текст комментария.

Готово!

Мы создали простой плагин, который позволяет добавить систему рейтинга в виде звезд к комментариям WordPress.

Расширяем плагин

Теперь, когда у вас есть данные, вы можете использовать их любым образом путем расширения плагина. К примеру, давайте получим средний рейтинг поста и покажем его над контентом.

Вставьте следующий код в файл плагина:

//Get the average rating of a post.
function ci_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;
	}
}

Функция получит ID поста, пройдет по всем одобренным комментариям, просуммирует рейтинги, после чего вернет средний показатель с округлением до первого десятичного знака. Если у тестируемого поста нет рейтингов, то в таком случае функция вернет false.

Чтобы отобразить средний рейтинг комментариев над контентом записи, используйте код:

//Display the average rating above the content.
add_filter( 'the_content', 'ci_comment_rating_display_average_rating' );
function ci_comment_rating_display_average_rating( $content ) {

	global $post;

	if ( false === ci_comment_rating_get_average_ratings( $post->ID ) ) {
		return $content;
	}
	
	$stars   = '';
	$average = ci_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  = '

This post\'s average rating is: ' . $average .' ' . $stars .'

';
	$custom_content .= $content;
	return $custom_content;
}

Приведенный выше код получит средний рейтинг, используя функцию, созданную нами на предыдущем шаге. Если среднего рейтинга нет, то в таком случае функция просто вернет контент, в противном случае появится абзац над контентом, где будет выведен средний рейтинг.

Урок подошел к концу. Мы надеемся, что вы придумаете интересные идеи по расширению плагина.

Для вашего удобства ниже приведен весь код плагина из файла ci-comment-rating.php:

<?php /* Plugin Name: CI Comment Rating Description: Adds a star rating system to WordPress comments Version: 1.0.0 Author: The CSSIgniter Team Author URI: https://cssigniter.com/ */ //Enqueue the plugin's styles. add_action( 'wp_enqueue_scripts', 'ci_comment_rating_styles' ); function ci_comment_rating_styles() { wp_register_style( 'ci-comment-rating-styles', plugins_url(/,__FILE__) . 'assets/style.css' ); wp_enqueue_style( 'dashicons' ); wp_enqueue_style( 'ci-comment-rating-styles' ); } //Create the rating interface. add_action( 'comment_form_logged_in_after', 'ci_comment_rating_rating_field' ); add_action( 'comment_form_after_fields', 'ci_comment_rating_rating_field' ); function ci_comment_rating_rating_field () { ?>
	<label for="rating">Rating<span class="required">*</span></label>
	
<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 ); ?>"><?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', 'ci_comment_rating_save_comment_rating' );
function ci_comment_rating_save_comment_rating( $comment_id ) {
	if ( ( isset( $_POST['rating'] ) ) && ( '' !== $_POST['rating'] ) )
	$rating = intval( $_POST['rating'] );
	add_comment_meta( $comment_id, 'rating', $rating );
}

//Make the rating required.
add_filter( 'preprocess_comment', 'ci_comment_rating_require_rating' );
function ci_comment_rating_require_rating( $commentdata ) {
	if ( ! isset( $_POST['rating'] ) || 0 === intval( $_POST['rating'] ) )
	wp_die( __( 'Error: You did not add a rating. Hit the Back button on your Web browser and resubmit your comment with a rating.' ) );
	return $commentdata;
}

//Display the rating on a submitted comment.
add_filter( 'comment_text', 'ci_comment_rating_display_rating');
function ci_comment_rating_display_rating( $comment_text ){

	if ( $rating = get_comment_meta( get_comment_ID(), 'rating', true ) ) {
		$stars = '

';
		for ( $i = 1; $i <= $rating; $i++ ) {
			$stars .= '<span class="dashicons dashicons-star-filled"></span>';
		}
		$stars .= '

';
		$comment_text = $comment_text . $stars;
		return $comment_text;
	} else {
		return $comment_text;
	}
}

//Get the average rating of a post.
function ci_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_filter( 'the_content', 'ci_comment_rating_display_average_rating' );
function ci_comment_rating_display_average_rating( $content ) {

	global $post;

	if ( false === ci_comment_rating_get_average_ratings( $post->ID ) ) {
		return $content;
	}
	
	$stars   = '';
	$average = ci_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  = '

This post\'s average rating is: ' . $average .' ' . $stars .'

';
	$custom_content .= $content;
	return $custom_content;
}

Источник: https://www.cssigniter.com

Блог про WordPress
Комментарии: 5
  1. Дмитрий

    Здравствуйте, Дмитрий!
    Нужна ваша помощь по доработке комментариев с рейтингом.
    Мой контактный email для связи указан к данному комментарию.
    Подробности отправлю на ваш email.

    1. Дмитрий (автор)

      Здравствуйте, мы не оказываем услуг по разработке.

  2. Дмитрий

    Дмитрий, тогда, если это возможно, в рамках информационного развития данной статьи, сможете помочь разобраться начинающему пользователю WP с рядом вопросов, чтобы выполнить эти задачи самостоятельно:

    1. Как разместить рейтинг, например, сразу после имени или даты. Сейчас рейтинг выводится с использованием функции ‘comment_text’, т.е. после текста комментария. Я пробовал поставить функцию ‘comment_autor’, но рейтинг после этого пропадал совсем.
    2. Как обернуть в отдельный блок ‘div’ запись с общим рейтингом поста. Например: ‘This post’s average rating is: 5 *****’.
    3. Как в форму комментариев добавить произвольное поле, например, попросить посетителя указать дополнительно номер телефона для связи. Как сделать это поле открытым или закрытым, как, например, email, который виден только администратору сайта. И, так же, как сделать поле обязательным или необязательным для заполнения.
    4. Как добавить к комментарию фотографию или серию фотографий, которые будут выводиться вместе с комментарием под текстовой записью. Как вывести эти фотографии миниатюрами, открывающимися в полном размере в модальном окне.

    Убежден, тот кто самостоятельно делает свой блог или сайт для коммерческих целей, рано или поздно задумывается о тех же вопросах. И если постараться развернуть эту тему, она окажется полезной для многих читателей. Вы можете подсказать мне в комментарии где ковырять и какой код куда установить. А я по окончании работ подготовлю краткий, пошаговый отчет для читателей вашего блога, чтобы вам не тратить время на подготовку данного материала.

    Заранее благодарен за такую возможность.

    1. Дмитрий (автор)

      Эта статья — перевод материала. Разбираться детально в чужом коде — неблагодарный труд. Потому в данном случае могу только порекомендовать обратиться за детальными консультациями к Роману https://vk.com/kustyrt. Но не факт, что у него есть свободное время, и он захочет тратить свое свободное время на то, чтобы разбираться в коде. Попытка не пытка.

  3. Олег

    Здравствуйте, Дмитрий. А как можно вывести рейтинг для каждого комментария?
    Вывожу комментарии через цикл.

    Код:
    10,
    ‘orderby’ => ‘comment_date’,
    ‘order’ => ‘DESC’,
    ‘status’ => ‘approve’,
    ‘type’ => ‘comment’, // только комментарии, без пингов и т.д…
    );
    if( $comments = get_comments( $args ) ){
    global $post;
    foreach( $comments as $comment ){
    $comm_short_txt = mb_substr( strip_tags( $comment->comment_content ), 0, 450 ) .’…’; ?>
    <div class="reviews-item" id="post-ID; ?>»>

    ID, ‘full’, array(‘class’ => ‘reviews-item-img’)); ?>

    comment_author; ?>
    ID); ?>

Добавить комментарий

Получать новые комментарии по электронной почте.