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.

Como criar um módulo", conforme falei na parte 2, vou abordar agora como adicionar configurações específicas no módulo. Essas configurações são formulários em duas páginas diferentes. Em uma página, é pra escolher o comportamento padrão de cada vez que rodar o meu custom_deploy. A segunda, será onde vou rodar o custom_deploy, que irá se comportar de acordo o que defini na primeira página." data-share-imageurl="">