2批量删除模块batchdelete

作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com

我们再来看一个例子,批量删除模块batchdelete,这个模块主要用来批量删除节点的,还可以删除自定义区块、词汇表,不过后面两者的删除,没有用到批处理机制。

我们来看一下代码,菜单项定义:

function batchdelete_menu() {

  $items['admin/config/development/batchdelete'] = array(

    'title'            => 'Batch delete node',

    'page callback'    => 'drupal_get_form',

'page arguments'    =>  array('batchdelete_form'),

    'access arguments' => array('administer site configuration'),

    'weight'           => 1,

    'type'             => MENU_NORMAL_ITEM,

   

  );

  $items['admin/config/development/batchdelete/node'] = array(

    'title'            => 'Batch delete node',

    'page callback'    => 'drupal_get_form',

'page arguments'    =>  array('batchdelete_form'),

    'access arguments' => array('administer site configuration'),

    'weight'           => 1,

    'type'             => MENU_DEFAULT_LOCAL_TASK,

   

  );

  $items['admin/config/development/batchdelete/block'] = array(

    'title'            => 'Batch delete block',

    'page callback'    => 'drupal_get_form',

'page arguments'    =>  array('batchdelete_block_form'),

    'access arguments' => array('administer site configuration'),

    'weight'           => 2,

    'type'             => MENU_LOCAL_TASK,

   

  );

  $items['admin/config/development/batchdelete/taxonomy'] = array(

    'title'            => 'Batch delete taxonomy term',

    'page callback'    => 'drupal_get_form',

'page arguments'    =>  array('batchdelete_taxonomy_form'),

    'access arguments' => array('administer site configuration'),

    'weight'           => 3,

    'type'             => MENU_LOCAL_TASK,

   

  );

  return $items;

}

这里我们为节点、区块、分类,分别定义了一个菜单项,我们来看一下,节点的删除代码。

function batchdelete_form(){

  $options = array();

  $types = node_type_get_types();

  foreach ($types as $key => $values) {

    $options[$key] = $values->name;

  }


  $form['types'] = array(

    '#title' => t('Content types to be delete'),

    '#type' =>'checkboxes',

    '#description' =>t('All nodes of these selected types will be deleted'),

    '#options' => $options,

  );

 

  $form['submit'] = array(

    '#type' =>'submit',

    '#value' => t('Delete'),

  );

  return $form;

}

 

function batchdelete_form_submit($form,&$form_state){

  $types = array_filter($form_state['values']['types']);

  $batch =array(

    'operations' => array(

      array('batchdelete_node_process', array($types)),

    ),

    'finished' => 'batchdelete_node_finished',

    'title' => t('删除节点'),

    'init_message' => t('开始批量删除.'),

    //'progress_message' => t('Reindexed @current out of @total.'),

    'error_message' => t('批量删除遇到错误.'),

  );

  batch_set($batch);

}

function batchdelete_node_process($types, &$context){

  $size =100;

  //$types_str ='story,page';

  //$types_str = "'".implode("','", $types)."'";

  //drupal_set_message('types:'.print_r($types));

  //debug($types);

  if(!isset($context['sandbox']['progress'])){

    $context['sandbox']['progress'] = 0;

    $context['sandbox']['max'] = db_select('node', 'n')

      ->condition('n.type', $types, 'IN')

      ->countQuery()

      ->execute()

      ->fetchField();

    //drupal_set_message('max:'.$context['sandbox']['max']);

  }

  //$sql = "SELECT nid FROM {node} WHERE type in ($types_str)";

  //$result = db_query_range($sql,0,$size);

  $query =db_select('node', 'n')

    ->fields('n', array('nid'))

    ->condition('n.type', $types, 'IN')

    ->range(0, $size);

  $result = $query->execute();


  foreach ($result as $record) {

    //drupal_set_message('123max:'.$result->nid);  

    node_delete($result->nid);

    $context['sandbox']['progress']++;

    //$context['message'] = t('删除节点 %nid',array('%nid' => $node['nid']));

  }

  if($context['sandbox']['progress'] ==$context['sandbox']['max']){

    $context['finished'] = 1;

  }else{

    $context['finished'] = $context['sandbox']['progress']/$context['sandbox']['max'];

  }

}

 

function batchdelete_node_finished($success, $results, $operations){

  if ($success) {

    // Here we do something meaningful with the results.

    $message = t('节点删除完成');

  }

  else {

    // An error occurred.

    // $operations contains the operations that remained unprocessed.

    $error_operation = reset($operations);

    $message = '在删除节点时出现一个错误'. $error_operation[0] .' 其参数为 :'. print_r($error_operation[0], TRUE);

  }

  drupal_set_message($message);

}

这段代码,和我们前面第一个例子非常类似,其实我们第一个例子里面的代码,就是从这个模块复制过来的。而batchdelete模块,则是从Drupal6下面升级过来的,我们最初编写的是Drupal6下面的,现在升级到了Drupal7。升级的过程中,就遇到了向批处理的处理函数中传递参数的问题,batchdelete_node_process$types最初是放在后面的,结果后来发现了问题,调试了多次,我们可以看到代码里面还有很多的调试信息,最后才发现参数的顺序问题。

删除自定义区块的代码,还没有升级过来。我们看一下删除词汇表的:

function batchdelete_taxonomy_form(){

  $options=array();

  $vocabs = taxonomy_get_vocabularies();

  foreach($vocabs as $vocab){

    $options[$vocab->vid] = $vocab->name; 

  }

  $form['vids'] = array(

    '#title' => t('要删除的分类词汇表ID'),

    '#type' =>'checkboxes',

    '#description' =>t('请选择哪些分类词汇表要被删除。'),

    '#options' => $options,

  );

  $form['submit'] = array(

    '#type' =>'submit',

    '#value' => t('Delete'),

  );

  return $form;

}

function batchdelete_taxonomy_form_submit($form,&$form_state){

  $vids = array_filter($form_state['values']['vids']);

  foreach($vids as $vid){

    //taxonomy_del_vocabulary($vid);

    $transaction = db_transaction();

    try {

      // Only load terms without a parent, child terms will get deleted too.

      $result = db_query('SELECT t.tid FROM {taxonomy_term_data} t INNER JOIN {taxonomy_term_hierarchy} th ON th.tid = t.tid WHERE t.vid = :vid AND th.parent = 0', array(':vid' => $vid))->fetchCol();

      foreach ($result as $tid) {

        taxonomy_term_delete($tid);

      }

      return SAVED_DELETED;

    }

    catch (Exception $e) {

      $transaction->rollback();

      watchdog_exception('taxonomy', $e);

      throw $e;

    }

  }

}

我们这里面删除的是词汇表下面的所有分类术语,而没有删除词汇表本身。taxonomy_get_vocabularies,用来获取所有的词汇表;taxonomy_del_vocabulary可以用来删除词汇表,taxonomy_term_delete用来删除分类术语。我们这里在删除的过程中,使用了事务处理,它的代码结构大致是这样的:

    $transaction = db_transaction();

    try {

      //做一些操作.

    }

    catch (Exception $e) {

      $transaction->rollback();

      watchdog_exception('taxonomy', $e);

      throw $e;

    }

其实在编写好batchdelete的最初版本后,发现drupal.org上面有个类似的模块,Bulk delete,也是Drupal6下面的模块,我的模块比它晚写了三个月,所以编写的时候,没有注意到,已经存在这样一个模块了。不过,现在Bulk delete模块已经不再维护,为什么呢?因为VBO模块的存在。


Drupal版本: