Temos falado aqui na Escola WordPress sobre custom taxonomies e custom post types e temos criado vários tutoriais em 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 neste tutorial, como fazer e mostrando algumas possibilidades que podemos ter ao usar este método de organização de usuários.

CONCEITO DE OBJECTO 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-se a qualquer objecto registado no WordPress, devido à forma como ela está totalmente construída. Um objecto 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 objecto pode ter associado a si uma custom taxonomy. É partindo deste principio que vamos elaborar neste tutorial 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 objectivos.

CRIANDO O FICHEIRO DE PLUGIN

Antes de começar a nossa programação vamos começar por criar o ficheiro 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 cria rum ficheiro 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 ficheiro que vamos incluir todo o código que se seguirá. Agora aceda à administração do WordPress e active esse plugin para podermos começar a programar o nosso sistema.

REGISTANDO UMA CUSTOM TAXONOMY

Neste tutorial 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 dessa maneira 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 ficheiro de plugin que criámos na secçã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 acabámos de registar uma custom taxonomy ao objecto «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 qu faça uma query ao banco de dados de modo a obtermos tais informações sempre que solicitado e que as volte a guardar 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á a funcionar. Esta função é bastante simples e muito direta, no entanto poderá ser necessáiro modificá-la para alguns objetivos e propósitos.

PÁGINA DE GESTÃO DE PROFISSÕES

Agora que terminámos 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 inicio 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 faltam algumas alterações que precisam ser feitas e que iremos proceder mais à frente.

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 e no lugar 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 encontra-se terminada. Vamos passar à fase final deste processo: ligar cada usuário a cada termo.

INTERFACE PARA ASSOCIAR A PROFISSÃO

A seguinte função adiciona uma dropdown com todas as profissões ao perfil de cada usuário de maneira que o usuário possa escolher a sua de uma lista pre-configurada de algumas. É possível criar conceitos mais complicados, mas aqui neste tutorial vamos ficar pelo 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 class="form-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 em cima é 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 tutorial estivemos a ver 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 par isso seguir este tutorial 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 papeis 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 tutorial seja produtivo para criar sites WordPress mais confortáveis e organizados!

Até para a semana!