Sistema de Votação com Estrelas (exibição automática)
Objetivo: Fornecer um MU-Plugin completo que substitui wp-postratings e similares, com exibição automática das estrelas no final de cada post, sem necessidade de inserir shortcode manualmente. O sistema registra votos por IP, evita múltiplos votos e atualiza a média e total de votos.
Código do MU-Plugin: neodoor-ratings.php
Crie o arquivo dentro de wp-content/mu-plugins/neodoor-ratings/neodoor-ratings.php (ou direto na pasta mu-plugins se preferir).
<?php
/**
* Plugin Name: Neodoor Ratings (Unificado)
* Description: Sistema de votação com estrelas (1 a 5), exibido automaticamente ao final de cada post. Substitui wp-postratings.
* Version: 2.0
* Author: Reinaldo (Neodoor.neo)
*/
if ( ! defined( 'ABSPATH' ) ) exit;
class Neodoor_Ratings_Unified {
private static $instance = null;
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
add_action( 'init', [ $this, 'handle_vote' ] );
add_filter( 'the_content', [ $this, 'append_ratings_to_content' ], 20 );
add_action( 'wp_head', [ $this, 'inline_css' ] );
}
/**
* Adiciona o sistema de votação automaticamente após o conteúdo de cada post.
*/
public function append_ratings_to_content( $content ) {
if ( is_singular( 'post' ) && in_the_loop() && is_main_query() ) {
$content .= $this->render_ratings();
}
return $content;
}
/**
* Renderiza o HTML das estrelas e informações de voto.
*/
private function render_ratings() {
$post_id = get_the_ID();
$avg = get_post_meta( $post_id, '_rating_average', true ) ?: 0;
$count = get_post_meta( $post_id, '_rating_count', true ) ?: 0;
// Mensagem de feedback (vindo da URL após voto)
$msg = '';
if ( isset( $_GET['vote_status'] ) && $_GET['vote_status'] == 'success' && isset( $_GET['rated_post'] ) && $_GET['rated_post'] == $post_id ) {
$msg = '<p style="color:green; margin:0 0 10px 0;">✅ Voto computado! Obrigado.</p>';
} elseif ( isset( $_GET['vote_status'] ) && $_GET['vote_status'] == 'already_voted' && isset( $_GET['rated_post'] ) && $_GET['rated_post'] == $post_id ) {
$msg = '<p style="color:orange; margin:0 0 10px 0;">⚠️ Você já votou neste conteúdo.</p>';
}
// Gera links para votar (1 a 5 estrelas)
$vote_links = '';
for ( $i = 1; $i <= 5; $i++ ) {
$url = add_query_arg( [ 'rate_post' => $post_id, 'rating' => $i ], get_permalink() );
$star_class = ( $i <= round( $avg ) ) ? 'star-filled' : 'star-empty';
$vote_links .= '<a href="' . esc_url( $url ) . '" class="neodoor-star ' . $star_class . '" data-rating="' . $i . '">★</a>';
}
return '
<div class="neodoor-ratings-wrapper">
' . $msg . '
<div class="neodoor-stars-container">' . $vote_links . '</div>
<div class="neodoor-rating-stats">Média: ' . number_format( $avg, 1 ) . ' (' . $count . ' voto' . ( $count != 1 ? 's' : '' ) . ')</div>
</div>';
}
/**
* Processa o voto quando os parâmetros rate_post e rating são enviados via GET.
*/
public function handle_vote() {
if ( ! isset( $_GET['rate_post'], $_GET['rating'] ) ) return;
$post_id = intval( $_GET['rate_post'] );
$rating = intval( $_GET['rating'] );
if ( $rating < 1 || $rating > 5 ) return;
// Verifica voto por IP (evita múltiplos votos)
$ip = $_SERVER['REMOTE_ADDR'];
$voted_ips = get_post_meta( $post_id, '_rating_voted_ips', true );
if ( ! is_array( $voted_ips ) ) $voted_ips = [];
if ( in_array( $ip, $voted_ips ) ) {
$redirect_url = add_query_arg( [ 'vote_status' => 'already_voted', 'rated_post' => $post_id ], get_permalink( $post_id ) );
wp_redirect( $redirect_url );
exit;
}
// Atualiza métricas
$total = get_post_meta( $post_id, '_rating_total', true ) ?: 0;
$count = get_post_meta( $post_id, '_rating_count', true ) ?: 0;
$total += $rating;
$count++;
$new_avg = $total / $count;
update_post_meta( $post_id, '_rating_average', $new_avg );
update_post_meta( $post_id, '_rating_count', $count );
update_post_meta( $post_id, '_rating_total', $total );
// Registra IP
$voted_ips[] = $ip;
update_post_meta( $post_id, '_rating_voted_ips', $voted_ips );
// Redireciona com sucesso
$redirect_url = add_query_arg( [ 'vote_status' => 'success', 'rated_post' => $post_id ], get_permalink( $post_id ) );
wp_redirect( $redirect_url );
exit;
}
/**
* Estilos CSS básicos para as estrelas e layout.
*/
public function inline_css() {
if ( ! is_singular( 'post' ) ) return;
echo '<style>
.neodoor-ratings-wrapper {
margin: 30px 0 20px;
padding: 15px 0;
border-top: 1px solid #eee;
text-align: center;
}
.neodoor-stars-container {
display: inline-block;
font-size: 32px;
letter-spacing: 5px;
}
.neodoor-star {
text-decoration: none;
color: #ccc;
transition: color 0.2s;
}
.neodoor-star.star-filled {
color: #ffc107;
}
.neodoor-star:hover {
color: #ffb300;
}
.neodoor-rating-stats {
font-size: 14px;
color: #666;
margin-top: 8px;
}
</style>';
}
}
Neodoor_Ratings_Unified::get_instance();
Instalação e uso
- Crie o arquivo conforme o caminho indicado.
- Não é necessário inserir shortcode – o sistema aparecerá automaticamente ao final de cada post.
- Para desativar em posts específicos, você pode usar uma condicional (ex: excluir categorias).
- Os votos são registrados por IP. O cookie não é necessário, pois o redirecionamento mantém o estado.
Personalizações comuns
- Alterar posição das estrelas: no método
append_ratings_to_content, troque$content .= ...por$content = ... . $content(para aparecer antes do conteúdo). - Restringir a apenas algumas categorias: adicione uma condição como
if ( in_category( 'noticias' ) )dentro do filtro. - Mudar cores ou tamanhos: edite o CSS no método
inline_css.
Registro no caderno
Data:
Funcionalidade: Votação com estrelas (1 a 5) exibida automaticamente em todos os posts.
Plugins substituídos: wp-postratings e similares.
Testado: ✅ Votos registrados, média atualizada, prevenção de múltiplos votos por IP, exibição automática.