Já pensou qual seria a melhor forma de fazer um ranking dos autores do seu blogue WordPress? E se você deixar os seus leitores fazerem esse ranking? Neste tutorial vamos criar um plugin para WordPress que resolve este problema, criando um sistema de pontuação para os autores que vai somando de acordo com o número de estrelas (de 1 a 5) que cada leitor atribui a cada artigo.

INTRODUÇÃO

Enquanto pensava como criar tal plugin, pensei em várias maneiras de criar o algoritmo de pontuação, passando por vários tipos de sistema de pontuação flutuado (como o algoritmo da Amazon) ou com um algoritmo mais complexo onde este faria uma média ponderada ou uma regressão linear para despistar possíveis atribuições de pontuação “maléficas”. Tudo isto é possível, mas será democrático? Desta maneira mantive um algoritmo bastante simples: à pontuação anterior do autor vamos sempre somar o número (de um a 5) de estrelas que o leitor atribui, prolongando-se com esta medida, no limite, para o infinito, no entanto, para a escala de blogues como o da Escola WordPress este algoritmo é mais desejado.

Neste plugin iremos usar o plugin “Raty” para jQuery. Ele irá servir para mostrar as estrelas para o leitor poder pontuar e irá enviar por Ajax essa pontuação. Esta é a parte mais básica do plugin. Iremos também ter em consideração mostrar a pontuação total por cada autor na administração, deste modo iremos adicionar uma coluna de pontos que será também sorteável.

pontuação

CRIAR O FICHEIRO DO PLUGIN

Como noutros artigos, vamos criar uma subdirectoria na directoria “plugins” que irá albergar os ficheiros do nosso plugin. Vamos criar a subdirectoria “ewp-pontos-autores” e o ficheiro “ewp-pontos-autores.php” dentro dela. Agora registamos o cabeçalho do nosso plugin:

<?php

/*
Plugin Name: Pontos do Autor
Plugin URI: http://www.escolawp.com/
Version: 0.1
Description: Adiciona ao WordPress um sistema de pontuação para o autor
Author: lightningspirit
Author URI: http://profiles.wordpress.org/lightningspirit
Tags: plugin, 
License: GPLv2 - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/

Voltando ao wp-admin activamos o nosso plugin. Agora é só começar a programar o nosso plugin. Se você não entendeu o porquê do cabeçalho em cima ou teve alguma dificuldade neste processo, veja um dos nossos artigos anteriores em como criar um plugin para WordPress. Vamos então?

REGISTANDO AS ACÇÕES HOOKS NO PLUGIN

Primeiro que tudo vamos criar as action hook necessárias para trabalhar com o nosso plugin, assim vamos colocar a seguinte função dentro do nosso plugin:

/** 
 * Inicia o plugin
 *
 * Esta função é chamada sempre que os plugins do WordPress estiverem a ser carregados
 * pelo sistema. Desta maneira vamos colocar dentro desta função todas as action hooks
 * que precisamos para colocar este plugin a funcionar.
 * 
 * @since 0.1
 * @return void
 */
function ewp_pontos_autor_init() {
	// Aqui vamos adicionar as action hooks
}

add_action( 'plugins_loaded', 'ewp_pontos_autor_init' );

Dentro desta função iremos adicionar cada uma das action hooks que irão ser necessárias.

O CÓDIGO JQUERY

Primeiro que tudo vamos adicionar o arquivo JS que contém o nosso plugin jQuery Raty e o código jQuery. Não me irei debruçar muito no código jQuery uma vez que tudo o que está ali expresso são propriedades do plugin que você poderá ver na página de documentação do plugin. Este é o código jQuery que iremos precisar:

/*!
 * jQuery Ajax Request Queuer
 * 
 * Licensed under GPLv2 License
 * 
 * @version 	1.0
 * @author	Vitor Carvalho <email@vcarvalho.com>
 * 
 */
(function(a){var b=a({});a.ajaxQueue=function(c){var d=c.complete;b.queue(function(b){c.complete=function(){if(d)d.apply(this,arguments);b()};a.ajax(c)})}})(jQuery);
// Este plugin irá ser-nos útil por duas razões:
// 1) previne que o mesmo leitor faça submissão mais que uma vez;
// 2) coloca a chamada ajax em "fila de espera" assim não irá haver problemas de corte de ligação, por exemplo.

(function($){
	$(document).ready(function(){
		$(".ewp-rating-stars").raty({
	        number: 5,
	        start: 0,
	        path: ewp_pontos_autor.plugin_path,
	        hintList: ["Fraco", "Moderado", "Suficiente", "Bom", "Excelente"],
	        click: function (b, c) {
	        	$(this).raty('readOnly', true);
	            $.ajaxQueue({
	                url: ewp_pontos_autor.ajaxurl,
	                type: "POST",
	                data: {
	                    action: "ewp_count_autor_receive_points",
	                    post_id: $(".ewp-pontos-autor-rating input.ewp_post_id").val(),
	                    user_id: $(".ewp-pontos-autor-rating input.ewp_user_id").val(),
	                    field: $(this).attr("id"),
	                    rate: b
	                },
	                success: function (a) {
	                    return false
	                },
	                dataType: "json"
	            });
	            return false
	        }
	    });
	})
})(jQuery);

Agora que temos este código jQuery dentro de um ficheiro .js (javascript) só temos que o chamar colocando uma hook que irá apontar para uma função que irá incluir este ficheiro sempre que necessário:

// Adiciona o javascript necessário para o leitor fazer o rating ao artigo
add_action( 'wp_enqueue_scripts', 'ewp_pontos_autor_wp_enqueue_scripts' );

A chamada acima será colocada dentro da função ewp_pontos_autor_init. Agora vamos colocar a nossa função dentro do ficheiro PHP:

// Esta função irá chamar o ficheiro .js
function ewp_pontos_autor_wp_enqueue_scripts() {
	// Como só iremos ter a pontuação dentro dos posts/artigos
	// vamos só chamar o javascript nesse caso.
	if ( is_single() ) {
		wp_enqueue_script( 'ewp-pontos-autor', plugin_dir_url( __FILE__ ) . 'ewp-pontos-autor.js', array( 'jquery' ), '0.1' );
		wp_localize_script( 'ewp-pontos-autor', 'ewp_pontos_autor', array(
			'plugin_path' => plugin_dir_url( __FILE__ ),
			'ajaxurl' => admin_url( 'admin-ajax.php' ),
			)
		);

	}

}

Agora o nosso código jQuery já se encontra devidamente preparado e localizado para ser chamado quando um Post for visualizado.

ADICIONAR AS “ESTRELAS” DO RATING NO FIM DO POST

Agora falta-nos adicionar as estrelas de rating no fim do post para que qualquer leitor possa dar uma pontuação facilmente. Poderiamos fazer isto de várias maneira, por exemplo, com uma dropdown que atribuísse em vez de números palavras (“Bom”, ‘Muito bom”, etc), mas acho que não há dúvidas que o que melhor pretende traduzir uma pontuação é o uso de estrelas.

O plugin jQuery Raty já trás duas imagens de estrelas que iremos usar, assim não serbaá necessário estarmos a criar as nossas ou a baixar da internet alguns ícones de estrelas que sejam gratuitos.

Posto isto, vamos então colocar a nossa pontuação no final de cada post através da action filter the_content que permite filtrar o conteúdo mesmo antes de este ser baixado. Vamos então adicionar a seguinte chamada à função init:

// Adiciona o rating no fim do artigo
add_filter( 'the_content', 'ewp_pontos_autor_the_content' );

e iremos igualmente incluir a função ewp_pontos_autor_the_content que irá colocar o código HTML necessário para as estrelas aparecerem no fim do post:

// Esta função irá incluir o código HTML para mostrar a pontuação
function ewp_pontos_autor_the_content( $the_content ) {
	// Só irá serincluída em posts
	if ( is_single() ) {
		return sprintf( apply_filters( 'ewp_pontos_autor', '%s <div class="ewp-pontos-autor-rating">Avalie o autor: %s</div>' ),
			$the_content, ewp_pontos_autor_stars() 		
		);

	}

}
// Esta é uma função de ajuda e serve para mostrar campos input
// para serem enviados via Ajax
function ewp_pontos_autor_stars() {
	global $post;
	ob_start();
	?> 
	<span class="ewp-rating-stars star" style="cursor: pointer; width: 100px; "></span>
	<input class="ewp_post_id" type="hidden" name="ewp_post_id" value="<?php echo $post->ID; ?>">
	<input class="ewp_user_id" type="hidden" name="ewp_user_id" value="<?php echo $post->post_author; ?>">
	<?php 

	return ob_get_clean();

}

Se você for agora ver um post do seu blog tudo estará direitinho como estava previsto. Vamos agora entrar na parte em que o plugin jQuery Raty submete por ajax as pontuações.

PROCESSAR AJAX COM WORDPRESS

Já falámos aqui na escola em como processar o ajax no WordPress. Existem duas frameworks no WordPress que podem ser bastante úteis dependendo dos casos. A primeira é a WP_Ajax_Response que facilita todo o trabalho de captura e apresentação de resultados ao usuário, porém ela usa XML e por vezes para algo tão pequeno como o que estamos aqui a fazer acaba por ser dispendioso de tempo. A segunda framework, e que é a que vamos usar, é a admin-ajax.php. Basicamente ela recebe todas as chamadas ajax apontadas para esse ficheiro e coloca-as numa acção que será depois invocada pelas funções PHP que forem criadas.

Assim, a primeira coisa a criar é a chamada a essas acções Ajax, incluindo o seguinte código na função init:

// Processa o pedido JSON para fazer a contagem dos pontos
add_action( 'wp_ajax_nopriv_ewp_count_autor_receive_points', 'ewp_pontos_autor_ajax_receive_points' );
add_action( 'wp_ajax_ewp_count_autor_receive_points', 'ewp_pontos_autor_ajax_receive_points' );

Têm de ser duas action hooks pois a primeira serve para visitantes que não estão logados no sistema e a segunda para usuários mesmo. Desta forma, distinguindo os dois, esta framework do ajax no WordPress apresenta uma robustez bastante grande pois garante que determinadas chamadas só são efetuadas por usuários do sistema (usando apenas a segunda action hook), ou só por visitantes (usando apenas a primeira action hook) ou pelos dois (usando as duas em suimultâneo).

Agora só temos que incluir a nossa função ewp_pontos_autor_ajax_receive_points para processarmos o ajax:

// Esta função irá processar as chamadas Ajax
function ewp_pontos_autor_ajax_receive_points() {
	// Vamos recolher as variáveis do POST
	// e saneá-las
	$points  = (int) $_POST['rate'];
	$post_id = (int) $_POST['post_id'];
	$user_id = (int) $_POST['user_id'];

	// Por uma razão de não haver submissão dupla do leitor no mesmo post
	// iremos aplicar um COOKIE sempre que ele o fizer.
	// Desta maneira garantimos que não há leitores a fazerem dezenas de votações.
	// Esta condição analisa se o COOKIE para este post já se encontra registado
	// no browser cliente.
	if ( isset( $_COOKIE["ewp_pontos_autor_{$user_id}_{$post_id}"] ) ) {
		echo 'already did';

	// Se a função calculou e adicionou a pontuação, então vamos guardar um cookie
	} elseif ( false !== ewp_pontos_autor_calculate_save_points( $points, $user_id, $post_id ) ) {
		echo setcookie( "ewp_pontos_autor_{$user_id}_{$post_id}", '1', time() + 60*60*24*365 );

	}

	die();

}

// Esta função ajuda a separar a lógica. Ela aceita o número de pontos a acrescentar,
// o ID do autor do post e o ID do post e guarda ao valor já registado
function ewp_pontos_autor_calculate_save_points( $points, $user_id, $post_id ) {
	$actual_points = (int) get_user_meta( $user_id, 'ewp_pontos_autor', true );
	$points = $actual_points + $points;

	return update_user_meta( $user_id, 'ewp_pontos_autor', $points );

}

Neste momento já temos o nosso plugin completamente funcional.

APRESENTAR A PONTUAÇÃO DE CADA AUTOR

Chegamos à recta final do nosso artigo. Vamos agora mostrar como iremos exibir a pontuação total que cada autor de posts tem mostrando uma coluna na listagem de utilizadores (usuários) na administração do WordPress. Para isso é necessário algumas action hooks, vamos adicioná-las todas de uma vez na função init:

// Adiciona uma coluna com os pontos de cada um dos utilizadores
add_filter( 'manage_users_columns', 'ewp_pontos_autor_manage_users_columns' );

// Adiciona o conteúdo da calouna por cada linha (célula) repesentada pelo autor
add_action( 'manage_users_custom_column', 'ewp_pontos_autor_manage_users_custom_column', 10, 3 );

// Define quais as colunas sorteáveis, vamos incluir a de pontos também
add_action( 'manage_users_sortable_columns', 'ewp_pontos_autor_manage_users_sortable_columns' );

Agora basta adicionar as funções que estão ligadas às respectivas action hooks:

// Esta função recebe o array com as colunas.
// Vamos adicionar a coluna ewppoints com a label 'Pontos'
function ewp_pontos_autor_manage_users_columns($columns ) {
	$columns['ewppoints'] = 'Pontos';	
	return $columns;

}

// Esta função faz o display do conteúdo da coluna por cada autor.
function ewp_pontos_autor_manage_users_custom_column( $value, $column_name, $user_id ) {

	// Quando a coluna a ser visualizada é a ewppoints, ele dispara o seu conteúdo
	if( 'ewppoints' == $column_name ) {
		// Vai buscar a meta que fomos guardando e incrementando anteriormente via ajax
		return number_format_i18n( (float) get_user_meta( $user_id, 'ewp_pontos_autor', true ), 0 );

	}

}

// Vamos colocar a nossa coluna também sorteável
function ewp_pontos_autor_manage_users_sortable_columns($columns ) {
		$columns['ewppoints'] = 'ewppoints';
		return $columns;

}

Desta maneira irá aparecer uma nova coluna na lista de autores com a respectiva pontuação.

Faça o download do código deste artigo!

Até breve!