I am using the Batch API in Drupal 7 and I just realized that the reason why my count and totals are not showing correctly is because the initial total is based on a count of the operations given to it.
The thing is I set it up so that each operation processes 100 nodes. I have to update information in nodes that meet certain criteria and there are almost 7,000 nodes that have to be updated. So I thought it would be more efficient to fix multiple nodes per operation call.
Instead it seems like I should put in an operation per node or an operation per 100 nodes (even though my current setup seems to keep calling the same operation with no problems). So what should it be? I guess I could use the context variable to force it to count properly, but I don't like hacking around issues if I don't have to.
Below is the code I am using:
/**
* Load the nodes with the broken language bodies and fix them.
*/
function my_fixes_broken_bodies() {
$brokenBodyCnt = my_fixes_count_broken_bodies();
$operations = array();
$limit = 100;
$count = ceil($brokenBodyCnt / $limit);
// Give helpful information about how many nodes are being operated on.
drupal_set_message(t('There are @brokenBodyCnt nodes to fix. And we are fixing @limit nodes per call. So the operation will require @count HTTP requests.', array('@brokenBodyCnt' => $brokenBodyCnt, '@limit' => $limit, '@count' => $count)));
//Setup the operations for the fixes
$operations[] = array('my_fixes_broken_bodies_op', array('broken body fix'));
$batch = array(
'operations' => $operations,
'finished' => 'my_fixes_finished',
'title' => t('Fixing broken node body language settings.'),
'init_message' => t('The broken body fix is starting...'),
'progress_message' => t('Processed @current out of @total.'),
'error_message' => t('The broken body fix has encountered an error.'),
);
return $batch;
}
/**
* Batch operation for fixing the broken bodies.
*/
function my_fixes_broken_bodies_op($operation_details, &$context) {
if (empty($context['sandbox'])) {
$context['sandbox'] = array();
$context['sandbox']['progress'] = 0;
$context['sandbox']['current_node'] = 0;
// Save node count for the termination message.
$context['sandbox']['max'] = my_fixes_count_broken_bodies();
}
// Process nodes by groups of 100
$limit = 100;
// Retrieve the next group of nids.
$result = db_query("SELECT n.nid, FROM_UNIXTIME(n.created) AS created, n.title, n.type, n.language AS 'Node Language', b.language AS 'Body Language'
FROM node n INNER JOIN field_data_body b ON nid = entity_id
WHERE n.language != b.language AND status = 1
ORDER BY nid ASC LIMIT $limit");
$results = $result->fetchAll();
foreach ($results as $row) {
$node = node_load($row->nid);
if (isset($node->body['en']) && !isset($node->body[$node->language])) {
$node->body[$node->language] = $node->body['en'];
$node->body['en'] = NULL;
node_save($node);
}
$context['results'][] = $node->nid . ' : ' . check_plain($node->title) . ' ' . $operation_details;
// Update our progress information.
$context['sandbox']['progress']++;
$context['sandbox']['current_node'] = $node->nid;
$context['message'] = check_plain($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']);
}
_my_fixes_update_http_requests();
}