Batch Operations – Como criar suas operações em lote, parte 1

Olá Soldado! 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 ." data-share-imageurl="">

Olá Soldado! 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:

Agora sim! Vamos ao que interessa.

O que é uma operação em lote ?

  • Conceito geral
    • Permitir gerir de forma organizada grande volumes de dados;
    • Permitir criar diversas operações, cada uma com suas responsabilidades;
  • Para o Drupal
    • 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 desejar 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.

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.

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;
}

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.

/**
 * Implements hook_permission().
 */
function dcamp_sp_importer_permission() {

  return array(
    'importer page' =>  array(
      'title' => t('Access to importer page'),
      'description' => t('Oppa gangnam style!'),
    ),
  );
}

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.

/**
 * 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;
}

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!

/**
 * 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: http://drupal.org/node/180528
  batch_set($batch);
}

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

Para inicializar uma batch operations 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.

A implementação das funções declaradas no $batch ficará para parte 2 desse artigo.

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

{pt: Nós vamos encorajá-lo a desenvolver as três grande virtudes de um programador: preguiça, impaciência e hybris.}

1. Para instalar o git flow no Ubuntu:

{en: For installing git flow on Ubuntu:}

apt-get install git-flow

Dica da Preguiça: Veja instruções para outros sistemas operacionais