Back-End

16 nov, 2009

Prover campos personalizados para o Views

Publicidade

Hoje vou mostrar como criar um pequeno módulo com um campo que é
gravado em uma tabela própria e, em seguida, disponibilizar esse campo
para filtragem e ordenação no módulo Views.

Antes de começarmos, precisamos nos ambientar. Para quem nunca criou
um módulo para o Drupal, recomendo, antes de ler esse tutorial, ler
essa documentação: http://drupal.org/node/508

Um outro requisito para entender plenamente esse tutorial (sua segunda
parte, mais especificamente), é um pouco de conhecimento do módulo
Views. Para baixar e testar esse módulo, acesse http://drupal.org/project/views Uma documentação inicial está disponível em http://drupal.org/node/47412.
Ao final desse artigo, você poderá baixar o módulo de teste que vamos criar.

Sabendo essas coisas, vamos lá.

Parte 1 – Criação do módulo

Para esse tutorial vamos assumir alguns padrões:

  • O nome do módulo será “modteste” (sem aspas, obviamente);
  • O nome do campo adicional será “meucampo” e seu label será “Meu campo”;
  • O nome das tabelas que iremos criar são: modteste e modteste_options

Antes de mais nada precisamos criar um módulo e, para isso, precisamos criar uma pasta com o nome do nosso módulo.
Assim, acesse a pasta modules da sua instalação do Drupal e crie uma
pasta chamada modteste. Dentro dessa pasta crie, a princípio, 3
arquivos: modteste.info modteste.install modteste.module

Cada arquivo desse tem um propósito:

  • modteste.info: Esse arquivo informa ao Drupal qual versão, subgrupo e outras informações de instalação do seu módulo;
  • modteste.install: Aqui temos criação e remoção de tabelas,
    parâmetros de configuração etc. Se você planeja alguma funcionalidade
    para o momento da instalação ou remoção do seu módulo, você deve definir
    aqui;
  • modteste.module: Esse é o módulo em si. É aqui que toda a magia acontece;

Abaixo temos um exemplo do arquivo modteste.info (clique na imagem para ampliar)

Explicando:

name = modteste: Esse é o nome do módulo

description = Permite criar um tipo de teste: Essa é a descrição do módulo. Ela será mostrada na área de instalação de módulos do Drupal

package = Testes: Esse é o pacote do módulo. Na área de
instalação de módulos do Drupal, esse será o nome do separador
(fieldset) que conterá o seu módulo

version = VERSION: Aqui é a versão do seu módulo. Se você
deixar VERSION ele pegará a versão atual do Drupal. É recomendável que
você defina números de versões coerentes com o Drupal que você está
utilizando. Assim, se a série do Drupal para a qual o seu módulo foi
feito é a 5, utilize algo como 5.x-0.1, onde: 5.x é a série para a qual
o seu módulo foi feito e 0.1 é efetivamente a versão do seu módulo. Uma
coisa importante sobre as versões é notar que mesmo que você faça um
módulo quando o Drupal estava na versão 5.3, utilize 5.x pois você está
fazendo o módulo para essa série, e não para a versão específica, uma
vez que o que vem depois do ponto é só o número de bugfixes da série.

A seguir o arquivo modteste.install (clique na imagem para ampliar):

Explicando:

Esse arquivo conta, essencialmente, com duas funções:

modteste_install(): função que realiza o procedimento de
instalação. É executada quando se marca o checkbox e envia o formulário
na área de instalação de módulos do Drupal.

modteste_uninstall(): função que realiza o procedimento de
desinstalação. É executada quando o módulo é desabilitado na área de
instalação de módulos do Drupal e, em seguida, marcado o checkbox e
enviado o formulário na aba Desinstalar, também na área de instalação
de módulos do Drupal.

Note que, no exemplo, só foram feitas a criação e a exclusão de
tabelas. No entanto pode-se realizar qualquer ação nesse momento. Isso
vai depender do que o seu módulo precisa para cada momento. Esse
arquivo só é necessário, efetivamente, se você vai realizar alguma
configuração no momento da instalação/desinstalação.

Por fim temos o arquivo modteste.module. Vamos ver os pontos-chave
desse arquivo. Pretendo escrever um outro tutorial explicando, mais
detalhadamente, como criar um módulo.

Primeiro a função modteste_uninstall() que monta o formulário em si:


/**
* Implementação do hook_form().
*/
function modteste_form(&$node){
$type = node_get_types('type', $node);
$form['title'] = array(
'#type' =>'textfield',
'#title' =>check_plain($type->title_label) ,
'#required' =>TRUE,
'#default_value' =>$node->title,
'#weight' => -5
);
$form['meucampo'] = array(
'#type'=>'radios',
'#title'=>t('Um campo a mais'),
'#default_value' =>$node->meucampo,
'#options'=> _modteste_options());
$form['body_filter']['body'] = array(
'#type' =>'textarea',
'#title' =>check_plain($type->body_label) ,
'#default_value' =>$node->body,
'#rows' =>20,
'#required' =>TRUE);
$form['body_filter']['filter'] = filter_form($node->format);
return$form;
}

Essa função implementa 3 campos. Dois desses campos são padrão para
qualquer tipo de conteúdo no Drupal(node): o título e o corpo(title e
body).

Todo tipo no Drupal possui um título e um corpo. Esses dados são,
por padrão, gravados na tabela node(somente o title) e
node_revisions(title e body).

O terceiro campo do formulário é o nosso campo personalizado. Esse
campo será, na verdade, um conjunto de radio buttons onde podemos
escolher um valor.

Um princípio importante na hora de trabalhar com o Drupal é não
mexer nos módulos e tabelas que ele cria, pois essas mudanças podem se
perder quando você atualizar o Drupal na próxima vez. Só mexa no que o
Drupal já traz se você estiver corrigindo um bug (correção que você deve
enviar para os desenvolvedores do Drupal, para poder melhorá-lo para a
sua próxima versão), caso contrário, evite.

Tendo isso em mente, criamos uma tabela com o mesmo nome do nosso
módulo (modteste). Essa tabela terá dois campos: um será o nosso campo
efetivamente, e o segundo o nid(node id) que é o “elo”(foreign key)
entre o nosso campo e o node dele.

Se você prestou atenção no arquivo modteste.install verá que ele
cria uma segunda tabela, e já a popula. Essa é uma tabela auxiliar para
o nosso módulo e será nela que iremos guardar os valores possíveis para
o nosso campo.

Como já foi dito, esse terceiro campo(meucampo) é um conjunto de radio
buttons. Para tanto, a sua definição pede uma opção chamada “#options”
que nada mais é que um array contendo o par chave/valor para cada um
dos radio buttons.

No nosso caso, esses valores vêm de uma tabela auxiliar chamada
modteste_options, então fiz uma pequena função para carregar esses
valores:

function _modteste_options(){
$result = db_query("SELECT * FROM {modteste_options}");
while($option = db_fetch_array($result)){
$options[$option['mid']] = $option['name'];
}
return$options;
}

Note que essa função começa com o caractere _ .Essa é uma convenção
do Drupal que significa que é uma função interna para esse módulo.

Por fim temos as seguintes funções:

function modteste_insert($node){
if(user_access('criar um teste')){
db_query("INSERT INTO {modteste}(nid, meucampo) VALUES (%d, %d)", $node->nid, $node->meucampo);
}
}

function modteste_update($node){
if(user_access('alterar seu próprio teste')){
db_query("UPDATE {modteste} SET nid=%d, meucampo=%d WHERE nid=%d", $node->nid, $node->meucampo, $node->nid);
}
}

function modteste_delete($node){
if(user_access('alterar seu próprio teste')){
db_query("DELETE FROM {modteste} WHERE nid=%d", $node->nid);
}
}

Essas três funções fazem, respectivamente, a inserção, a alteração e a remoção do nosso campo na tabela auxiliar.
Note que não precisamos escrever nenhuma instrução SQL para a tabela
node ou node_revisions. Isso é feito internamente pelo Drupal.

Esses são os pontos-chave para o nosso módulo. Como dito antes, você
pode baixar o módulo no final desse artigo e ver como é feito o
restante do módulo.

Parte 2 – Integração com o módulo Views

Agora vamos ver como integrar nosso módulo com o módulo Views.

Nesse artigo não vamos cobrir o módulo Views, apenas a integração do nosso módulo com ele.

O módulo Views permite criar visualizações personalizadas para
determinadas situações. Existem diversas opções para criar Views,
recomendo você dar uma olhada com mais calma nesse módulo. Em breve
devo lançar um screencast só com o módulo Views.

O módulo Views, assim como o Drupal inteiro, trabalha com hooks que nada mais são do que funções que podem ser estendidas.

Assim, o módulo Views implementa algumas funções que podemos
estender para habilitar o nosso campo personalizado para construção de Views.

Vamos ver 2 dessas funções:

hook_views_tables(): Nessa função são definidas tabelas usadas para o relacionamento entre o módulo Views e o seu módulo.
hook_views_arguments(): Nessa função são definidos os campos que podem ser usados como argumentos(via URL) para uma View.

Abaixo temos o código dessas duas funções:

function modteste_views_tables(){
$tables['modteste'] = array(
'name' =>'modteste',
'provider' =>'internal',
'join' =>array(
'left' =>array(
'table' =>'node',
'field' =>'nid'
),
'right' =>array(
'field' =>'nid'
)
),
"filters" =>array(
'meucampo' =>array(
'name' =>t('Teste: Meu campo'),
'list' =>'views_handler_filter_modteste_meu_campo',
'operator' =>'views_handler_operator_andor',
'help' =>t('Permite você filtrar pelo Meu Campo'),
),
),
'sorts' =>array(
'meucampo' =>array(
'name' =>t('Teste: Meu Campo'),
'handler' =>'views_handler_sort_modteste_sort',
'help' =>t('Ordenar pelo meu campo'),
),
),
);
return$tables;
}
function modteste_views_arguments(){
$arguments = array(
'modteste_meucampo' =>array(
'name' =>t("Teste: Meu campo"),
'handler' =>"views_handler_arg_modteste_meucampo",
),
);
return$arguments;
}

Na função modteste_views_tables() nós definimos qual o nome da
tabela que vamos utilizar para o relacionamento e como esse
relacionamento se dará(veja o array join nessa função). Também
definimos os filtros(filters) e as ordenações(sorts). Para esses dois últimos, o módulo faz uso de funções callback, que nada mais são
funções que são chamadas para executar e retornar um valor(ou conjunto
de valores) sem precisarmos escrevê-las no local onde as chamamos.

É nessas funções callback que está o código a ser executado quando filtrarmos ou ordenarmos um campo.

A função modteste_views_arguments() tem um funcionamento semelhante.
Ela especifica o nome de um campo(no caso acima modteste_meucampo) e
uma função callback que será usada para executar a filtragem.
Aparentemente ela é semelhante ao filters da outra função, mas a
diferença essencial é que ela implementa o nosso campo como um
argumento para filtragem pela URL. Assim, eu posso chamar minha View,
passando por argumento na URL o valor(no caso) do Meu Campo e a View
fará a filtragem por nodes que tenham Meu Campo com esse valor.

Por fim, para manter as coisas organizadas, criamos um arquivo
chamado views_modteste.inc e colocamos todas as funções de View nesse
arquivo(as duas funções que estamos estendendo e suas callback). No
arquivo modteste.module criamos então um mecanismo para que o Drupal
encontre esse arquivo, criando uma função hook_init() como a abaixo:

function modteste_init(){
if(module_exists('views')){
include_once('./'. drupal_get_path('module', 'modteste') .'/views_modteste.inc');
}
}

Essa função irá carregar as nossas funções de Views somente se existir o módulo Views (e esse estiver habilitado).

Assim concluímos esse tutorial.
Espero que ele sirva para você.
Esteja à vontade para comentar.

Abraço!

Anexo Tamanho
modteste.tar.gz 2.69 KB

*
Artigo publicado em Drupal Brasil por Rafael Ferreira Silva