Back-End

7 jun, 2013

Block com template para Drupal 7

Publicidade

Themed Block é um módulo sandbox que exemplifica a criação programática de um block com template para o Drupal 7.

Não perca tempo lendo este post, baixe o código por git clone e divirta-se:

git clone –branch master panchiniak@git.drupal.org:sandbox/panchiniak/1961770.git themed_block

Se você precisa de mais informações sobre o comando acima, ou quer ver o bixo todo antes de cloná-lo, visite a página oficial de instruções para versionamento do Themed Block.

[ironia mode on]

Se estas palavras ainda estão sendo lidas, então, ou a árvore não foi suficiente e você precisa de alguma explicação, ou você é a minha mãe. Vou supor que o seu nome não é Izidora e prosseguir com explicações no melhor estilo Livro dos Espíritos.

[ironia mode off]

1. Por que Themed Block cria um block com template no diretório theme?

Porque ele quer etiquetar o conteúdo do block com <strong>.

É uma boa prática deixar as etiquetas html fora do código PHP. Por que? Porque, como bem papeou oSebas:

Embora viva em uma, você não é uma ilha. Alguém, menos afeito ao PHP, pode querer embelezar o seu bloco. Assim, será útil separar em diferentes arquivos o que é funcionalidade, daquilo que é aparência.

Em tudo que diga respeito ao Drupal, é muito importante a separação entre funcionalidade,aparência e conteúdo.

2. Mas, você ainda não respondeu: por que o diretório theme?

Porque é um nome descritivo, e é útil acompanhar a galera naquilo que é mais usado. Mas, sintaticamente, poderia ser qualquer outro nome.

3. E esse template consiste no quê?

Siga o link da pergunta e veja. Note que embora o arquivo de template seja .php, a intenção é fazê-lo, ao máximo possível, um arquivo HTML. O prefixo tpl, antes de php, indica isso. Perceba que apenas o conteúdo é “printado” pelo PHP, enquanto as etiquetas HTML ficam de fora.

4. Qual é a função do hook_block_info, no arquivo themed_block.module?

Consulte o excelente post do Denis sobre a criação programática de blocos. A conversa aqui é mais específica, pô. Queremos falar sobre block com template, enquanto o Denis já cobriu a criação programática de blocos.

5. Está certo. Então, como funcionam o hook_block_view e o hook_theme?

Quando usamos hooks, é sempre bom olhar a descrição deles na seção de API do Drupal.

/**
 * Implements hook_block_view().
 */
function themed_block_block_view($delta = 'themed_block') {
  if ($node = menu_get_object()) {
    $block['subject'] = t('Themed Block');
    $user = user_load($node->uid);
    $user_home_link = drupal_get_path_alias('user/' . $user->uid);
  }

  return isset($block) ? $block = array(
    'subject' => $block['subject'],
    'content' => theme(
      'themed_block', array(
        'author' =>array(
          'author_name' => l($user->name,$user_home_link),
        ),
      )
    ),
  ):

  FALSE;
}

Essa descrição do hook_block_view nos permite entender o que está acontecendo. Basicamente, em themed_block_block_viewThemed Block diz ao Drupal três coisas:

  1. a identificação do block, que é o valor de $delta, seguindo o que ficara definido em themed_block_block_info;
  2. subject do block, que poderá ser sobreescrito na página de administração emadmin/structure/block/manage/themed_block/themed_block, sob o formulário de Block title e,
  3. o conteúdo do block, que será encapsulado pela função theme, e finalmente lido pelothemed_block_block_theme.
<span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;">Observação: nesse singelo exemplo, o nome do bloco é igual ao nome do módulo que o cria, mas isso não é o ideal. Você deveria usar um nome que descreva os propósitos do </span><em style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;">block</em><span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;">. Se o </span><em style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;">block</em><span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;"> se chamasse themed_block_example, por exemplo, teríamos sua administração em</span><em style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;">admin/structure/block/manage/themed_block/themed_block_example</em><span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;">. Esse detalhe é importante, porque o seu módulo poderia criar diversos blocos, cada um com seu prpóprio nome e finalidade.</span>

6. Então agora você já sabe o que eu quero saber.

Sei. Agora, você quer saber como funciona themed_block_theme, e qual é a mágica que envia valores ao template. Pois bem. Primeiro, o módulo diz ao Drupal onde vive o querido template. Isso acontece pela variável $path. Em seguida, fazemos retornar desse hook_theme a variável $author de themed_block, conforme o povoamento que se deu em themed_block_block_view. Esses dados ficarão disponíveis para o template, que é identificado em ‘template’ => ‘themed-block-template’. Veja que não deve ser incluída a extensão (.tpl.php) na identificação do arquivo, pois o Drupal cuidará disso.

7. Massa, mas você poderia postar o código inteiro aí? Não quero clicar em nenhum desses links-tentação.

Feito!

<?php /**
 * @file
 * This is themed_block.module for Drupal
 */

/**
 * Implements hook_help().
 *
 * Displays help and module information.
 */
function themed_block_help($path, $arg) {

  switch ($path) {
    case "admin/help#themed_block":
      return  t('Themed Block creates a themed block.') ;
    break;
  }
}

/**
 * Implements hook_block_info().
 */
function themed_block_block_info() {

  $blocks['themed_block'] = array(
    'info' =?> t('Themed Block'),
    'cache' => DRUPAL_NO_CACHE,
  );
  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function themed_block_block_view($delta = 'themed_block') {

  if ($node = menu_get_object()) {
    $block['subject'] = t('Themed Block');
    $user = user_load($node->uid);
    $user_home_link = drupal_get_path_alias('user/' . $user->uid);
  }

  return isset($block) ? $block = array(
    'subject' => $block['subject'],
    'content' => theme(
      'themed_block', array(
        'author' =>array(
          'author_name' => l($user->name,$user_home_link),
        ),
      )
    ),
  ) : FALSE;
}

/**
 * Implements hook_theme().
 */
function themed_block_theme() {

  $path = drupal_get_path('module', 'themed_block') . '/theme';
  return array(
    'themed_block' => array(
      'variables' => array('#author' => NULL),
      'path' => $path,
      'template' => 'themed-block-template'
    ),
  );
}

8. Ah, posso fazar mais duas perguntas?

Aff… Sim, diga.

9. Uhm… você está impaciente?

Não, pode perguntar.

10. Como faço para ver o danado do block, e o que significa ($node = menu_get_object())?

As duas perguntas estão relacionadas. A função menu_get_object, por padrão, retorna o node que estiver sendo exibido. Portanto, se e apenas se estiver sendo exibido algum node, a variável $node passa a armazenar o objeto, e o operador = deixa de ser falso. Em outras palavras, como pretendemos enviar para o bloco o nome do autor do node que esteja sendo exibido, então só queremos exibir o bloco quando houver algum node cujo autor possa ser exibido. Capitice?

O objeto node armazena muitas informações úteis, mas não armazena o nome do autor do conteúdo, embora armazene o número de identificação do famigerado usuário. Assim, Themed Block usa user_load para obter o nome a partir do(a) user id entregue pelo objeto node. Belezinha? Finalmente, tudo isse é entregue ao precioso template na forma de um link para a home page do usuário/autor. Na prática, você poderá ver o resultado desta arte habilitando o block Themed Block em /admin/structure/block.

 

Agradecimentos vão para Ferrari, Sebas, e toda a galera da Taller. Sem contar, é claro, os eternos agradecimentos à Izidora (in memorian).