It's my first time working with the Batch API. I have a batch operation that I have almost working, but it gets stuck on the first item and I'm out of ideas on how to fix it.
What the batch thing does is iterate over a bunch of nodes and transform the fake-locations scattered over a dozen text fields into real Location CCK fields. When the batch process runs, it continually fixes the first node over and over again. My logs fill up with the Location module deleting orphaned locations, and if I dpm($node)
, it shows the first node over and over again.
I've checked my $batch
variable, and the operations
array does have all different nids.
Here's the code:
function rlh_tweaks_menu() {
$items['location-fix'] = array(
'title' => 'Location fixer',
'page callback' => 'rlh_tweaks_location_fix',
'access callback' => '_rlh_tweaks_user_one_only',
);
return $items;
}
function rlh_tweaks_location_fix() {
$batch = array(
'finished' => '_rlh_tweaks_batch_finished',
);
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'business');
$result = $query->execute();
foreach($result['node'] as $nid => $data) {
$batch['operations'][] = array('_rlh_tweaks_batch_update_location', array($nid));
}
batch_set($batch);
batch_process('node');
}
function _rlh_tweaks_batch_update_location($nid, &$context) {
if (!isset($context['sandbox']['progress'])) {
$context['sandbox']['progress'] = 0;
$context['sandbox']['max'] = db_query('SELECT COUNT(DISTINCT nid) FROM {node} WHERE type = \'business\'')->fetchField();
}
// Here we actually perform our processing on the current node.
$node = node_load($nid);
$location = _rlh_tweaks_update_node_location($node);
$lid = location_save($location);
if(!empty($lid)) {
$node->field_location[LANGUAGE_NONE]['0'] = location_load_location($lid);
}
node_save($node);
// Store some result for post-processing in the finished callback.
$context['results'][] = check_plain($node->title);
// Update our progress information.
$context['sandbox']['progress']++;
$context['sandbox']['current_node'] = $node->nid;
$context['message'] = t('Now processing %node', array('%node' => $node->title));
// Inform the batch engine that we are not finished,
// and provide an estimation of the completion level we reached.
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
function _rlh_tweaks_update_node_location($node) {
$street_part_keys = array('street_no', 'pre_dir', 'street_name', 'post_dir', 'street_type');
$all_parts = array('street_no', 'pre_dir', 'street_name', 'post_dir', 'street_type', 'suite_no', 'city', 'po_box', 'state', 'zip');
$parts = array();
foreach($all_parts as $key) {
$parts[$key] = _rlh_tweaks_get_text_field_value($node, $key);
}
$street_parts = array();
foreach($street_part_keys as $key) {
if(!empty($parts[$key])) {
$street_parts[] = $parts[$key];
}
}
$street = implode(' ', $street_parts);
if(empty($street)) {
if(empty($parts['po_box'])) {
continue;
} else {
$street = $parts['po_box'];
}
}
$location = array(
'street' => $street,
'additional' => $parts['suite_no'],
'city' => $parts['city'],
'province' => $parts['state'],
'postal_code' => $parts['zip'],
'country' => 'us'
);
return $location;
/*
if(!empty($lid)) {
$node->field_location[LANGUAGE_NONE]['0'] = location_load_location($lid);
}
return $node); */
}
function _rlh_tweaks_batch_finished($success, $results, $operations) {
if ($success) {
// Here we do something meaningful with the results.
$message = t("!count items were processed.", array(
'!count' => count($results),
));
$message .= theme('item_list', array('items' => $results));
drupal_set_message($message);
}
else {
// An error occurred.
// $operations contains the operations that remained unprocessed.
$error_operation = reset($operations);
$message = t('An error occurred while processing %error_operation with arguments: @arguments', array(
'%error_operation' => $error_operation[0],
'@arguments' => print_r($error_operation[1], TRUE),
));
drupal_set_message($message, 'error');
}
}
function _rlh_tweaks_get_text_field_value($node, $field_name) {
$item = field_get_items('node', $node, 'field_' . $field_name);
return $item[0]['safe_value'];
}
function _rlh_tweaks_user_one_only() {
global $user;
if($user->uid == '1') {
return TRUE;
}
return FALSE;
}
Why is this not moving on to the rest of the batch operations?