View source
<?php
define('BACKGROUND_BATCH_ENABLED', FALSE);
define('BACKGROUND_BATCH_DELAY', 1);
define('BACKGROUND_BATCH_PROCESS_LIFESPAN', 10);
define('BACKGROUND_BATCH_PROCESS_ETA', TRUE);
function background_batch_menu() {
$items = array();
$items['admin/config/system/batch/settings'] = array(
'type' => MENU_DEFAULT_LOCAL_TASK,
'title' => 'Settings',
'weight' => 1,
);
$items['admin/config/system/batch'] = array(
'title' => 'Batch',
'description' => 'Administer batch jobs',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'background_batch_settings_form',
),
'access arguments' => array(
'administer site',
),
'file' => 'background_batch.admin.inc',
);
$items['admin/config/system/batch/overview'] = array(
'type' => MENU_LOCAL_TASK,
'title' => 'Overview',
'description' => 'Batch job overview',
'page callback' => 'background_batch_overview_page',
'access arguments' => array(
'administer site',
),
'file' => 'background_batch.pages.inc',
'weight' => 3,
);
return $items;
}
function background_batch_menu_alter(&$items) {
$items['batch'] = array(
'page callback' => 'background_batch_page',
'access callback' => TRUE,
'theme callback' => '_system_batch_theme',
'type' => MENU_CALLBACK,
'file' => 'background_batch.pages.inc',
'module' => 'background_batch',
);
}
function background_batch_batch_alter(&$batch) {
if (!variable_get('background_batch_enabled', BACKGROUND_BATCH_ENABLED)) {
return;
}
if ($batch['progressive'] && $batch['url'] == 'batch') {
foreach ($batch['sets'] as &$set) {
if (!empty($set['operations'])) {
foreach ($set['operations'] as &$operation) {
$operation = array(
'_background_batch_operation',
array(
$operation,
),
);
}
}
}
$batch['timestamp'] = microtime(TRUE);
}
global $user;
$batch['uid'] = $user->uid;
}
function background_batch_library() {
$libraries = array();
$libraries['background-process.batch'] = array(
'title' => 'Background batch API',
'version' => '1.0.0',
'js' => array(
drupal_get_path('module', 'background_batch') . '/js/batch.js' => array(
'group' => JS_DEFAULT,
'cache' => FALSE,
),
),
'dependencies' => array(
array(
'background_batch',
'background-process.progress',
),
),
);
$libraries['background-process.progress'] = array(
'title' => 'Background batch progress',
'version' => VERSION,
'js' => array(
drupal_get_path('module', 'background_batch') . '/js/progress.js' => array(
'group' => JS_DEFAULT,
'cache' => FALSE,
),
),
);
return $libraries;
}
function _background_batch_operation($operation, &$context) {
$fine_progress = !empty($context['sandbox']['background_batch_fine_progress']);
if ($fine_progress) {
$batch_context = new BackgroundBatchContext($context);
}
else {
$batch_context = $context;
}
$operation[1][] =& $batch_context;
call_user_func_array($operation[0], $operation[1]);
if ($fine_progress) {
$batch_context = (array) $batch_context;
foreach (array_keys($batch_context) as $key) {
$context[$key] = $batch_context[$key];
}
}
else {
$batch_context = new BackgroundBatchContext($context);
$batch_context['finished'] = $context['finished'];
}
}
function _background_batch_process($id = NULL) {
$process = BackgroundProcess::currentProcess();
if (!$process) {
return;
}
if (!$id) {
$process
->keepAlive(FALSE);
return;
}
$data = db_query("SELECT batch FROM {batch} WHERE bid = :bid", array(
':bid' => $id,
), array(
'target' => 'background_process',
))
->fetchColumn();
if (!$data) {
$process
->keepAlive(FALSE);
return;
}
require_once 'includes/batch.inc';
$batch =& batch_get();
$batch = unserialize($data);
global $user;
if ($batch['uid'] != $user->uid) {
$process
->keepAlive(FALSE);
return drupal_access_denied();
}
timer_start('background_batch_processing');
$percentage = 0;
$lifespan = $process
->getOption('batch_lifespan') * 1000;
while ($percentage < 100) {
$current_set =& _batch_current_set();
$queue = _batch_queue($current_set);
if ($queue
->numberOfItems() <= 0) {
$current_set['count'] = 0;
$percentage = 100;
break;
}
list($percentage, $message) = _batch_process();
if (timer_read('background_batch_processing') > $lifespan) {
break;
}
}
if ($percentage >= 100) {
$batch['finish_time'] = microtime(TRUE);
$process
->setProgress(1);
$process
->keepAlive(FALSE);
}
}
function background_batch_process_batch($redirect = NULL, $url = 'batch', $redirect_callback = 'drupal_goto') {
$batch =& batch_get();
drupal_theme_initialize();
if (isset($batch)) {
$process_info = array(
'current_set' => 0,
'progressive' => TRUE,
'url' => $url,
'url_options' => array(),
'source_url' => $_GET['q'],
'redirect' => $redirect,
'theme' => $GLOBALS['theme_key'],
'redirect_callback' => $redirect_callback,
);
$batch += $process_info;
drupal_alter('batch', $batch);
$batch['id'] = db_next_id();
foreach ($batch['sets'] as $key => $batch_set) {
_batch_populate_queue($batch, $key);
}
$t = get_t();
$batch['error_message'] = $t('Please continue to <a href="@error_url">the error page</a>', array(
'@error_url' => url($url, array(
'query' => array(
'id' => $batch['id'],
'op' => 'finished',
),
)),
));
if (isset($_GET['destination'])) {
$batch['destination'] = $_GET['destination'];
unset($_GET['destination']);
}
db_insert('batch')
->fields(array(
'bid' => $batch['id'],
'timestamp' => REQUEST_TIME,
'token' => drupal_get_token($batch['id']),
'batch' => serialize($batch),
))
->execute();
$_SESSION['batches'][$batch['id']] = TRUE;
$function = $batch['redirect_callback'];
if (function_exists($function)) {
}
}
die("TEST");
}
function _background_batch_process_callback($batch) {
$rbatch =& batch_get();
$rbatch = $batch;
require_once 'background_batch.pages.inc';
_background_batch_page_start();
}
class BackgroundBatchContext extends ArrayObject {
private $batch = NULL;
private $process = NULL;
public function __construct() {
$args = func_get_args();
return call_user_func_array(array(
'parent',
'__construct',
), $args);
}
public function getBatch() {
if (!$this->batch) {
$this->batch =& batch_get();
}
return $this->batch;
}
public function getProcess() {
if (!$this->process) {
$this->process = BackgroundProcess::loadByHandle('background_batch:' . $this->batch['id']);
$this->process
->setProgressInterval(variable_get('background_batch_delay', BACKGROUND_BATCH_DELAY));
}
return $this->process;
}
public static function processMessage($current_set, $finished = 0, $eta = 0) {
$total = $current_set['total'];
$count = $current_set['count'];
$elapsed = $current_set['elapsed'];
$start_time = $current_set['start'];
$progress_message = $current_set['progress_message'];
$current = $total - $count;
$step = 1 / $total;
$base = $current * $step;
$progress = $base + $finished * $step;
$time = microtime(TRUE);
$elapsed = floor($time - $start_time);
$values = array(
'@remaining' => $count,
'@total' => $total,
'@current' => $current,
'@percentage' => $progress * 100,
'@elapsed' => format_interval($elapsed),
'@estimate' => format_interval(floor($eta) - floor($time)),
);
$message = strtr($progress_message, $values);
return array(
$progress,
$message,
);
}
public function offsetSet($name, $value) {
if ($name == 'finished' || ($name = 'message')) {
if ($this
->getBatch() && $this
->getProcess()) {
list($progress, $message) = self::processMessage($this->batch['sets'][$this->batch['current_set']], $value, $this->process
->calculateETA());
$message .= $message && $this['message'] ? '<br/>' : '';
$message .= $this['message'];
if ($progress >= $this->process
->getProgress()) {
$this->process
->setProgress($progress, $message ? $message : NULL);
}
}
}
return parent::offsetSet($name, $value);
}
}