'textfield',
'#default_value' => variable_get('background_batch_delay', BACKGROUND_BATCH_DELAY),
'#title' => 'Delay',
'#description' => t('Time in microseconds for progress refresh'),
);
$form['background_batch_process_lifespan'] = array(
'#type' => 'textfield',
'#default_value' => variable_get('background_batch_process_lifespan', BACKGROUND_BATCH_PROCESS_LIFESPAN),
'#title' => 'Process lifespan',
'#description' => t('Time in milliseconds for progress lifespan'),
);
$form['background_batch_show_eta'] = array(
'#type' => 'checkbox',
'#default_value' => variable_get('background_batch_show_eta', BACKGROUND_BATCH_PROCESS_ETA),
'#title' => 'Show ETA of batch process',
'#description' => t('Whether ETA (estimated time of arrival) information should be shown'),
);
return system_settings_form($form);
}
/**
* Overview of current and recent batch jobs.
*/
function background_batch_overview_page() {
$data = array();
$bids = db_select('batch', 'b')
->fields('b', array('bid'))
->orderBy('b.bid', 'ASC')
->execute()
->fetchAllKeyed(0, 0);
foreach ($bids as $bid) {
$progress = progress_get_progress('_background_batch:' . $bid);
$eta = progress_estimate_completion($progress);
$data[] = array(
$progress->end ? $bid : l($bid, 'batch', array('query' => array('op' => 'start', 'id' => $bid))),
sprintf("%.2f%%", $progress->progress * 100),
$progress->message,
$progress->start ? format_date((int)$progress->start, 'small') : t('N/A'),
$progress->end ? format_date((int)$progress->end, 'small') : ($eta ? format_date((int)$eta, 'small') : t('N/A')),
);
}
$header = array('Batch ID', 'Progress', 'Message', 'Started', 'Finished/ETA');
return theme('table', array(
'header' => $header,
'rows' => $data
));
}
/**
* State-based dispatcher for the batch processing page.
*/
function background_batch_page() {
$id = isset($_REQUEST['id']) ? $_REQUEST['id'] : FALSE;
if (!$id) {
return drupal_not_found();
}
// Retrieve the current state of batch from db.
$data = db_query("SELECT batch FROM {batch} WHERE bid = :bid", array(':bid' => $id))->fetchColumn();
if (!$data) {
return drupal_not_found();
}
$batch =& batch_get();
$batch = unserialize($data);
// Check if the current user owns (has access to) this batch.
global $user;
if ($batch['uid'] != $user->uid) {
return drupal_access_denied();
}
$op = isset($_REQUEST['op']) ? $_REQUEST['op'] : '';
switch ($op) {
case 'start':
return _background_batch_page_start();
case 'do':
return _background_batch_page_do_js();
case 'do_nojs':
return _background_batch_page_do_nojs();
case 'finished':
progress_remove_progress('_background_batch:' . $id);
return _batch_finished();
default:
drupal_goto('admin/config/system/batch/overview');
}
}
/**
* Start a batch job in the background
*/
function _background_batch_initiate($process = NULL) {
require_once('includes/batch.inc');
$batch =& batch_get();
$id = $batch['id'];
$handle = 'background_batch:' . $id;
if (!$process) {
$process = background_process_get_process($handle);
}
if ($process) {
// If batch is already in progress, goto to the status page instead of starting it.
if ($process->exec_status == BACKGROUND_PROCESS_STATUS_RUNNING) {
return $process;
}
// If process is locked and hasn't started for X seconds, then relaunch
if (
$process->exec_status == BACKGROUND_PROCESS_STATUS_LOCKED &&
$process->start_stamp + variable_get('background_process_redispatch_threshold', BACKGROUND_PROCESS_REDISPATCH_THRESHOLD) < time()
) {
$process = BackgroundProcess::load($process);
$process->dispatch();
}
return $process;
}
else {
// Hasn't run yet or has stopped. (re)start batch job.
$process = new BackgroundProcess($handle);
$process->service_host = 'background_batch';
if ($process->lock()) {
$message = $batch['sets'][0]['init_message'];
progress_initialize_progress('_' . $handle, $message);
if (function_exists('progress_set_progress_start')) {
progress_set_progress_start('_' . $handle, $batch['timestamp']);
}
else {
db_query("UPDATE {progress} SET start = :start WHERE name = :name", array(':start' => $batch['timestamp'], ':name' => '_' . $handle));
}
$result = $process->execute('_background_batch_process', array($id));
return $process;
}
}
}
function _background_batch_page_start() {
_background_batch_initiate();
if (isset($_COOKIE['has_js']) && $_COOKIE['has_js']) {
return _background_batch_page_progress_js();
}
else {
return _background_batch_page_do_nojs();
}
}
/**
* Batch processing page with JavaScript support.
*/
function _background_batch_page_progress_js() {
require_once('includes/batch.inc');
$batch = batch_get();
$current_set = _batch_current_set();
drupal_set_title($current_set['title'], PASS_THROUGH);
// Merge required query parameters for batch processing into those provided by
// batch_set() or hook_batch_alter().
$batch['url_options']['query']['id'] = $batch['id'];
$js_setting['batch'] = array();
$js_setting['batch']['errorMessage'] = $current_set['error_message'] . '
' . $batch['error_message'];
// Check wether ETA information should be shown.
if (variable_get('background_batch_show_eta', BACKGROUND_BATCH_PROCESS_ETA)) {
$js_setting['batch']['initMessage'] = 'ETA: ' . t('N/A') . '
' . $current_set['init_message'];
}
else {
$js_setting['batch']['initMessage'] = $current_set['init_message'];
}
$js_setting['batch']['uri'] = url($batch['url'], $batch['url_options']);
$js_setting['batch']['delay'] = variable_get('background_batch_delay', BACKGROUND_BATCH_DELAY);
drupal_add_js($js_setting, 'setting');
drupal_add_library('background_batch', 'background-process.batch');
return '