Back-End

29 jan, 2013

Adicionar sistema de categorização aos usuários no WordPress

Publicidade

Temos falado muito na Escola WordPress sobre custom taxonomies e custom post types. Elaboramos, também, vários artigos sobre como criar sistemas completos e até complexos com estas duas maravilhas do WordPress. No entanto a criação de relações com as custom taxonomies não é apenas dirigida aos post types, podemos também criar sistemas de categorização de usuários e é disso mesmo que vamos falar hoje: como fazer e mostrando algumas possibilidades que podemos ter ao usar este método de organização de usuários.

Conceito de objeto e taxonomy no WordPress

Para quem não sabe, custom taxonomies é uma “ferramenta” disponibilizada pelo WordPress que possibilita a criação de uma nova forma de organização de posts através de uma única chamada no código; é uma API portanto. Dois exemplos de taxonomies já vêm embutidos no WordPress, as Categorias e Post Tags.

Na verdade, a API de custom taxonomies permite adicionar qualquer objeto registado no WordPress, devido à forma como ela está totalmente construída. Um objeto para o WordPress é qualquer estrutura que representa um tipo de conteúdo com propriedades e métodos, que pode ou não ser acedido através do frontend, através de queries e que suporta rewrite tags, caso os links permanentes estejam ativados. Assim, para o WordPress temos três tipos de estruturas já registadas que assentam nesse conceito:

  • Posts;
  • Comentários;
  • Usuários.

Estes três tipos de estrutura podem ser extendidos e qualquer developer pode criar outros tipos de objecto/estrutura para o WordPress, no entanto, não existe uma API flexível que possibilite tratar disso tudo em conjunto, ficando tremendamente mais fácil criar custom post types. Aliado a isso, qualquer tipo de objeto pode ter associado a si uma custom taxonomy. É partindo deste princípio que vamos elaborar neste artigo um novo sistema de organização para usuários de uma maneira fácil e intuitiva e que pode ser aplicada de várias maneiras e com vários objetivos.

Criando o arquivo de plugin 

Antes de começar a nossa programação, vamos começar por criar o arquivo de plugin que vai albergar o nosso código. Criar um plugin é sempre a melhor opção, ao contrário de colocar tudo no functions.php do tema. Existe um artigo já escrito aqui na Escola WordPress que explica as razões pelas quais se deve criar um plugin e como criá-lo.

Vamos, então, criar rum arquivo chamado profissao-usuario.php na pasta wp-content/plugins e incluir nele o seguinte cabeçalho:

<?php
/*
Plugin Name: Profissão para Usuários
Plugin URI: http://www.escolawp.com/
Description: Um plugin didático que criar um sistema de organização de usuários por profissões
Version: 1.0
Author: Escola WordPress
Author URI: http://www.escolawp.com/
License: GPLv2
*/

É neste arquivo que vamos incluir todo o código que se seguirá. Agora, vá na administração do WordPress e ative esse plugin para podermos começar a programar o nosso sistema.

Registando uma custom taxonomy 

Vamos criar um sistema de organização de usuários por profissão. Desta maneira, a nossa custom taxonomy irá albergar várias profissões e assim associar a cada usuário a sua profissão. Primeiro, vamos usar a função register_taxonomy() para registar a nossa taxonomy profissao usando o seguinte código que vamos colocar dentro do arquivo de plugin que criamos na seção anterior:

/**
* Regista a cusotm taxonomy 'profissao' que irá ser associada ao objecto 'user'
*/
function ewp_registar_usuario_profissao() {

register_taxonomy(
'profissao',
'user',
array(
'public' => true, // Esta taxonomy poderá ser acessada a partir do frontend
'labels' => array(
'name' => __( 'Profissões' ),
'singular_name' => __( 'Profissão' ),
'menu_name' => __( 'Profissões' ),
'search_items' => __( 'Procurar Profissões' ),
'popular_items' => __( 'Profissões populares' ),
'all_items' => __( 'Todas as Profissões' ),
'edit_item' => __( 'Editar Profissão' ),
'update_item' => __( 'Atualizar Profissão' ),
'add_new_item' => __( 'Adicionar Profissão' ),
'new_item_name' => __( 'Nome da Profissão' ),
'add_or_remove_items' => __( 'Adicionar/Remover Profissões' ),
'choose_from_most_used' => __( 'Procurar entre as profissões mais populares' ),
),
'rewrite' => array(
'with_front' => true,
'slug' => 'author/profissao' // Usamos 'author' para manter a estrutura de links coerente
),
'capabilities' => array(
'manage_terms' => 'edit_users', // Vamos manter as mesmas permissões que as de edição de usuário
'edit_terms'   => 'edit_users', // de maneira a manter a estrutura simples
'delete_terms' => 'edit_users',
'assign_terms' => 'read',
),
'update_count_callback' => 'ewp_atualiza_contador_profissao' // Usamos uma função customizada para contar o número de usuários associados a determinada profissão
)
);

}

Com o código acima, acabamos de registar uma custom taxonomy ao objeto «user», porém se você tentar visualizar qualquer usuário não irá aparecer nenhuma “caixa” ou formulário para você escolher as profissões – isto porque essa API apenas está disponível para post types. Dessa maneira teremos que escrever o nosso próprio código.

A função de atualização do contador

Neste momento ficou ainda pendente a função customizada para contar o número de usuários associados a determinada profissão. Assim, o que teremos que fazer é criar uma função que faça uma query ao banco de dados, de modo que possamos obter tais informações sempre que solicitado e que as guardar de volta no banco de dados na coluna count da linha correspondente ao termo que se encontra na tabela wp_term_taxonomy.

O código é o seguinte:

/**
* Esta função serve para fazer a atualização do contador de usuários associados a determinada profissão.
* Isto permite que o contador esteja sempre atualizado, o que trás o benefício do WordPress retornar sempre essa
* taxonomia quando for pedido um wp_query por termos dessa taxonomia e que os possamos organizar por número de usuários
* associados a determinada profissão.
*
* Para mais informações poderá ver a função _update_post_term_count() na core do WordPress.
*
* @param array $terms Lista de IDs dos termos da taxonomia
* @param object $taxonomy Objecto da taxonomia com que estamos a trabalhar
*/
function ewp_atualiza_contador_profissao( $terms, $taxonomy ) {
global $wpdb;

// Por cada termo da taxonomia vamos correr o código...
foreach ( (array) $terms as $term ) {

// Puxamos do banco de dados o contador atual
$count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $term ) );

// E guardamos o número de usuários associados a esse termo
do_action( 'edit_term_taxonomy', $term, $taxonomy );
$wpdb->update( $wpdb->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term ) );
do_action( 'edited_term_taxonomy', $term, $taxonomy );
// Devemos manter sempre estas do_action() pois são específicas do WordPress e são responsáveis
// por, além de outras coisas, aumentar o contador.

}
}

Neste momento, internamente a nossa taxonomy está funcionando. Esta função é bastante simples e muito direta, no entanto, poderá ser necessário modificá-la para alguns objetivos e propósitos.

Página de gestão de profissões 

Selecção_001-1024x493Agora que terminamos todo o trabalho de background, criando as bases que vão permitir integrar os usuários a cada termo/profissão da taxonomia, vamos dar início ao trabalho de interface, começando por habilitar a página de gestão de profissões:

add_action( 'admin_menu', 'ewp_pagina_gestao_admin' );

/**
* Regista a página de gestão de profisssões de usuários na administração do WordPress.
* Criamos uma página no submenu de usuários.
*/
function ewp_pagina_gestao_admin() {

$tax = get_taxonomy( 'profissao' );

add_users_page(
esc_attr( $tax->labels->menu_name ),
esc_attr( $tax->labels->menu_name ),
$tax->cap->manage_terms,
'edit-tags.php?taxonomy=' . $tax->name
);

}

add_filter( 'parent_file', 'fix_user_tax_page' );

/**
* Esta função serve para colocar a página de gestão de profissões dentro do submenu dos usuários sem "bugs"
*/
function fix_user_tax_page( $parent_file = '' ) {
global $pagenow;

if ( ! empty( $_GET[ 'taxonomy' ] ) && $_GET[ 'taxonomy' ] == 'profissao' && $pagenow == 'edit-tags.php' ) {
$parent_file = 'users.php';
}

return $parent_file;
}

Com estas duas funções, a página de gestão das profissões encontra-se situada no submenu dos usuários e pode ser visualizada na sua total funcionalidade. No entanto é necessário salientar que ainda é preciso fazer algumas alterações.

Alterar a coluna “posts” para “usuários” 

Algo que pode ser “perturbador” é a coluna Posts, que se encontra na tabela da página de gestão das profissões. Como esta taxonomia não está ligada a nenhum post type, não faz sentido essa coluna estar aí, portanto vamos retirá-la. No lugar vamos colocar uma coluna com o contador de usuários por profissão. Isso é atingível com o seguinte código:

add_filter( 'manage_edit-profissao_columns', 'ewp_customiza_colunas_tabela_profissao' );

/**
* Esta função remove a coluna 'Posts' da tabela de profissões e, no lugar dessa, acrescenta
* uma coluna chamada 'Usuários' tornando tudo mais consistente.
*
* @param array $columns Um array com as colunas registadas
*/
function ewp_customiza_colunas_tabela_profissao( $columns ) {
unset( $columns['posts'] ); // Remove a coluna posts
$columns['users'] = __( 'Usuários' ); // Adicionar uma coluna users
return $columns;

}

add_action( 'manage_profissao_custom_column', 'ewp_mostra_conteudo_colunas_tabela_profissao', 10, 3 );

/**
* Esta função mostra o conteúdo de cada coluna customizada.
* Neste momento apenas a coluna 'users' está criada de maneira a poder mostrar o contador de usuários por profissão.
*
* @param string $display O WordPress passa uma string vazia neste sitio... enfim!
* @param string $column O nome da coluna customizada
* @param int $term_id O ID do termo a ser visualizado
*/
function ewp_mostra_conteudo_colunas_tabela_profissao( $display, $column, $term_id ) {
if ( 'users' === $column ) {
$term = get_term( $term_id, 'profissao' );
echo $term->count;

}

}

A primeira coluna remove a coluna Posts e adiciona a coluna Usuários no lugar desta. A segunda função “alimenta” a coluna por cada uma das profissões que são passadas a esta função.

Até aqui a nossa interface para gerir as profissões está terminada. Vamos passar para a fase final deste processo: ligar cada usuário a cada termo.

Interface para associair a profissão

Menu_002A seguinte função adiciona uma dropdown com todas as profissões ao perfil de cada usuário de maneira que ele possa escolher a sua dentre uma lista pré-configurada de algumas. É possível criar conceitos mais complicados, mas aqui vamos ficar com o mais simples:

add_action( 'show_user_profile', 'ewp_adiciona_seccao_profissao' );
add_action( 'edit_user_profile', 'ewp_adiciona_seccao_profissao' );

/**
* Esta função adiciona uma dropdown com todas as profissões de maneira que o usuário possa
* escolher a sua de uma lista preconfigurada de algumas.
*
* @param object $user O objecto do usuário atualmente a ser visualizado
*/
function ewp_adiciona_seccao_profissao( $user ) {

$tax = get_taxonomy( 'profissao' );

// Temos que ter a certeza que o usuário que está a visualizar term permissão
// para alterar a profissão.
if ( ! current_user_can( $tax->cap->assign_terms ) )
return;

// Vamos buscar um array com todas as profissões pre-configuradas
$terms = get_terms( 'profissao', array( 'hide_empty' => false ) ); ?>

<h3><?php _e( 'Profissão' ); ?></h3>

<table>

<tr>
<th><label for="profissao"><?php _e( 'Selecione uma Profissão' ); ?></label></th>

<td>
<?php
// Vamos analisar se existem profissões para escolher
if ( ! empty( $terms ) ) :
?>
<select name="profissao" id="profissao">
<option value="">&mdash; Selecione uma profissão &mdash;</option>
<?php foreach ( $terms as $term ) : ?>
<option value="<?php echo esc_attr( $term->slug ); ?>"<?php selected( true, is_object_in_term( $user->ID, 'profissao', $term ) ); ?>>
<?php echo $term->name; ?>
</option>
<?php endforeach; ?>
</select>

<?php else : ?>
Não existem profissões disponíveis!

<?php endif; ?>
</td>
</tr>

</table>
<?php }

add_action( 'personal_options_update', 'ewp_guarda_profissao' );
add_action( 'edit_user_profile_update', 'ewp_guarda_profissao' );

/**
* Esta função guarda o valor da profissão do usuário a partir do valor escolhido no perfil.
* Usamos simplesmente a função wp_set_object_terms() para guardar a profissão.
*
* @param int $user_id O ID do usuário para guardar a profissão
*/
function ewp_guarda_profissao( $user_id ) {
$tax = get_taxonomy( 'profissao' );

// Certificamo-nos que o usuário tem permissão para alterar a profissão
if ( !current_user_can( 'edit_user', $user_id ) && current_user_can( $tax->cap->assign_terms ) )
return false;

// Buscamos o valor da profissão escolhido pelo usuário
$term = esc_attr( $_POST['profissao'] );

// Guardamos o valor da profissão no banco de dados através da função
// nativa do WordPress wp_set_object_terms()
wp_set_object_terms( $user_id, array( $term ), 'profissao', false);

// Limpamos a cache de termos (importante para manter a consistência)
clean_object_term_cache( $user_id, 'profissao' );

}

O exemplo criado acima é bastante básico e poderá não ser o suficiente na maior parte dos casos, no entanto fica o conceito de como proceder para criar esta interface para associar a profissão ao usuário.

Créditos: Este trabalho teve por base um artigo do Justin Tadlock.

Obviamente, neste artigo vimos uma forma bastante básica de associar taxonomias aos usuário. Você poderá criar e associar as que pretender e quantas as que quiser, basta para isso seguir este artigo para obter a parte básica deste conceito. São muitos os propósitos de se usar este conceito para organizar usuários em vez de ter que criar novos papéis e adicionar capacidades aos usuários, por exemplo, se você quiser organizar uma equipa de futebol você poderá organizar cada usuário por grupos, e você poderá adicionar mais do que um grupo e taxonomia.

DOWNLOAD DO CÓDIGO DESTE TUTORIAL

Espero que este artigo seja produtivo para criar sites WordPress mais confortáveis e organizados!

Até para a semana!