Back-End

26 jul, 2013

Batch Operations: Como criar suas operações em lote – Parte 01

Publicidade

No artigo de hoje será explicado como criar uma operação em lote. Este recurso é muito interessante por que se trata de uma forma de processar grandes volumes de dados sem ocorrer o timed out do navegador.

Antes de expôr o assunto propriamente dito, gostaria de ressaltar o que não será abordado:

  • hook_menu: Este hook será utilizado no artigo, porém não há necessidade de entendê-lo profundamente. Caso tenha interesse de estudá-lo . Entre neste outro artigo.
  • Watchdog: mais informações.
  • drupal_set_message: mais informações.

Agora sim! Vamos ao que interessa.

O que é uma operação em lote ?

  • Conceito geral
  1. Permitir gerir de forma organizada grande volumes de dados;
  2. Permitir criar diversas operações, cada uma com suas responsabilidades;
  • Para o Drupal
  1. Permitir operar grande volume de dados sem que aconteça o timed out na requisição.

Para fins didáticos, crie todos os algoritmos aqui mostrados dentro do seu arquivo .module. Caso você se interesse por algo mais profissional, faça o download do módulo. O download está no texto logo abaixo.

Vamos planejar!

Antes de por a mão no código, precisamos planejar o que queremos executar. Neste artigo vamos criar um batch operation para cadastrar artigos.

O código que será usado aqui já está pronto e modularizado; se deseja acompanhar com o módulo instalado, faça o download aqui (caso tenha interesse acesse o github).

Fluxo de processos de um batch

Após definirmos o que será feito, devemos saber como é um fluxo de processos de um batch.

fluxo_de_processos_de_um_batch

Mapeamento e parametrização

Neste bloco, a primeira coisa que precisamos fazer é criar um módulo e depois implementar um hook_menu ou então implementar esse hook num módulo já criado.

[php]define(‘DCAMP_SP_IMPORTER_SETTINGS_PATH’, ‘admin/structure/importer’);

/**
* Implements hook_menu().
*/
function dcamp_sp_importer_menu() {

$items[DCAMP_SP_IMPORTER_SETTINGS_PATH] = array(
‘title’ => ‘Importer’,
‘page callback’ => ‘drupal_get_form’,
‘page arguments’ => array(‘dcamp_sp_settings_importer_form’),
‘access arguments’ => array(‘importer page’),
‘type’ => MENU_CALLBACK,
);

return $items;
}[/php]

Neste hook menu estamos definindo onde será chamado o formulário que definirá o que será executado no batch. Um detalhe importante, no atributo ‘access arguments’ existe uma permissão definida – está permissão não é padrão do Drupal. Para criá-la, precisamos implementar o hook_permission.

[php]/**
* Implements hook_permission().
*/
function dcamp_sp_importer_permission() {

return array(
‘importer page’ => array(
‘title’ => t(‘Access to importer page’),
‘description’ => t(‘Oppa gangnam style!’),
),
);
}[/php]

Lembre-se que toda vez que implementamos um novo hook precisamos limpar o cache do drupal. Para limpá-lo você tem duas formas, pela interface administrava ou drush.

Agora é preciso criar a função que define o formulário solicitado no hook menu.

[php]/*** Settings importer form.
* @param [array] $form
* @param [array] $form_state
* @return [array] $form
*/
function dcamp_sp_settings_importer_form($form, $form_state) {

$form[‘amount_articles’] = array(
‘#type’ => ‘textfield’,
‘#title’ => t("Articles’s amount to import"),
‘#required’ => TRUE,
‘#size’ => 4,
‘#maxlength’ => 4,
‘#default_value’ => 100,
‘#element_validate’ => array(‘element_validate_number’),
);

$form[‘submit’] = array(
‘#type’ => ‘submit’,
‘#value’ => t(‘Submit’),
);

return $form;
}[/php]

No código acima foi utilizado dois elementos de formulário: um campo do tipo textfield e um botão submit. Para maiores detalhes acesse a api de formulários.

Construído o formulário, será necessário criar a função de submissão. É nela que irá começar a brincadeira!

[php]/**
* Settings importer form submit callback.
* @param [array] $form [description]
* @param [array] $form_state [description]
*/
function dcamp_sp_settings_importer_form_submit(&$form, &$form_state){

// This number is the amount of articles already imported.
$article_number = variable_get(‘dcamp_sp_importer_article_number’, 0);

// Batch’s definitions.
$batch = array(
‘title’ => t(‘Processing Importer DCAMP’),
‘operations’ => array(
// Callback function for the operation and their arguments.
array(‘dcamp_sp_importer_importing’, array(
$form_state[‘values’][‘amount_articles’],
$article_number,
)
),
),
‘finished’ => ‘dcamp_sp_importer_importing_finished’,
‘init_message’ => t(‘Importer DCAMP is starting.’),
‘error_message’ => t(‘Importer DCAMP has encountered an error.’),
‘progress_message’ => t(‘Article importing’),
);

// I do not set a batch_process because here is a form submiting.
// For more details access: <a href="http://drupal.org/node/180528" target="_blank">http://drupal.org/node/180528</a>
batch_set($batch);
}[/php]

O que nos interessa nesse algoritmo acima é o que acontece dentro da variável $batch.

Para inicializar uma batch operations nós precisamos declarar um array() com o seguintes parâmetros:

  • ‘title’: título que será usado na interface.
  • ‘operations’: este array serve para definir quais funções deverão ser executadas no batch. A ordem de execução dessas funções segue a ordem definida no array.

    Dentro de cada função declarada você pode também passar parâmetros, para isso basta criar um array.

  • ‘finished’: aqui é declarado o nome da função que irá fazer a finalização do batch. Nele poderá expor os resultados do batch e redirecionar o usuário para uma outra interface.
  • ‘init_message’: antes de iniciar a barra de progress (progress bar) o Drupal mostra essa mensagem.
  • ‘error_message’: Está mensagem só aparecerá caso houve algum problema durante o batch.
  • ‘progress_message’: Está mensagem irá aparecer embaixo do progress bar durante todo o processo.

Para que o batch seja iniciado é preciso executar a função batch_set(). Seu parâmetro é a variável $batch, que contém todas as propriedades necessárias para sua execução.

Após a execução dessa função, precisamos implementar as funções declaradas no $batch – mas isso estará apenas na parte 02 do artigo.

Para quem quiser continuar sem ter a parte 02 do artigo, basta fazer download do módulo (o link para download encontra-se no início desse artigo).