View source
<?php
function hosting_task_menu() {
$items = array();
$tasks = hosting_available_tasks();
foreach ($tasks as $type => $type_tasks) {
if (empty($type_tasks)) {
continue;
}
foreach ($type_tasks as $task => $info) {
if (empty($info['hidden'])) {
$path = sprintf("node/%%hosting_%s_node/%s_%s", $type, $type, $task);
$items[$path] = array(
'title' => $info['title'],
'description' => $info['description'],
'page callback' => 'drupal_get_form',
'page arguments' => array(
'hosting_task_confirm_form',
1,
$task,
),
'access callback' => 'hosting_task_menu_access_csrf',
'access arguments' => array(
1,
$task,
),
'type' => MENU_CALLBACK,
);
$items[$path] = array_merge($items[$path], $info);
}
}
}
$items['hosting/tasks/%node/list'] = array(
'title' => t('Task list'),
'description' => t('AJAX callback for refreshing task list'),
'page callback' => 'hosting_task_ajax_list',
'page arguments' => array(
2,
),
'access callback' => 'node_access',
'access arguments' => array(
'view',
2,
),
'type' => MENU_CALLBACK,
);
$items['hosting/tasks/%node/cancel'] = array(
'title' => t('Task list'),
'description' => t('Callback for stopping tasks'),
'page callback' => 'hosting_task_cancel',
'page arguments' => array(
2,
),
'access callback' => 'hosting_task_cancel_access',
'access arguments' => array(
2,
),
'type' => MENU_CALLBACK,
);
$items['hosting/tasks/queue'] = array(
'title' => t('Task list'),
'description' => t('AJAX callback for refreshing task queue'),
'page callback' => 'hosting_task_ajax_queue',
'access arguments' => array(
'access task logs',
),
'type' => MENU_CALLBACK,
);
return $items;
}
function hosting_task_ajax_list($node) {
$return['markup'] = hosting_task_table($node);
$return['changed'] = $node->changed;
$return['navigate_url'] = url('node/' . $node->nid);
drupal_json($return);
exit;
}
function hosting_task_ajax_queue() {
$view = views_get_view('hosting_task_list');
$view
->set_display('block');
$view
->pre_execute();
$return['markup'] = $view
->render('block');
drupal_json($return);
exit;
}
function hosting_task_cancel($node) {
if ($node->type == 'task') {
if ($node->task_status == HOSTING_TASK_QUEUED) {
$ref = node_load($node->rid);
hosting_add_task($node->rid, $node->task_type, array(), HOSTING_TASK_ERROR);
hosting_task_log($node->vid, 'error', t("Task was cancelled."));
drupal_goto('node/' . $node->rid);
}
}
drupal_access_denied();
}
function hosting_task_cancel_access($node) {
global $user;
if (!isset($_GET['token']) || !drupal_valid_token($_GET['token'], $user->uid)) {
return FALSE;
}
if (user_access('administer tasks')) {
return TRUE;
}
if (user_access('cancel own tasks') && user_access('create ' . $node->task_type . ' task') && node_access('view', $node)) {
return TRUE;
}
}
function hosting_task_menu_access($node, $task) {
if (user_access("create " . $task . " task")) {
if ($node->type == 'site') {
if (hosting_task_outstanding($node->nid, 'delete') || $node->site_status == HOSTING_SITE_DELETED) {
return FALSE;
}
if ($task == 'login-reset' && $node->site_status != HOSTING_SITE_ENABLED) {
return FALSE;
}
$safe_tasks = array(
'backup',
'backup-delete',
'verify',
'enable',
);
if (!in_array($task, $safe_tasks)) {
$profile = node_load($node->profile);
if ($profile->short_name == 'hostmaster') {
return FALSE;
}
}
$site_enabled = hosting_task_outstanding($node->nid, 'enable') || $node->site_status == HOSTING_SITE_ENABLED;
$deletable = $task == "delete";
$enabable = $task == "enable";
$delete_or_enable = $deletable || $enabable;
if (!$site_enabled) {
return $delete_or_enable;
}
else {
return !variable_get('hosting_require_disable_before_delete', TRUE) && $deletable || !$delete_or_enable;
}
}
if ($node->type == 'platform') {
if (!node_access('update', $node, $GLOBALS['user'])) {
return FALSE;
}
if (hosting_task_outstanding($node->nid, 'delete') || $node->platform_status == HOSTING_PLATFORM_DELETED) {
return FALSE;
}
if ($node->platform_status == HOSTING_PLATFORM_LOCKED) {
$platform_tasks = array(
'verify',
'unlock',
'delete',
'migrate',
);
return in_array($task, $platform_tasks);
}
else {
if ($task == 'unlock') {
return FALSE;
}
return TRUE;
}
}
if ($node->type === 'server') {
if (!node_access('update', $node, $GLOBALS['user'])) {
return FALSE;
}
return TRUE;
}
}
return FALSE;
}
function hosting_task_menu_access_csrf($node, $task) {
global $user;
$interactive_tasks = array(
'migrate',
'clone',
);
if (!in_array($task, $interactive_tasks) && (!isset($_GET['token']) || !drupal_valid_token($_GET['token'], $user->uid))) {
return FALSE;
}
return hosting_task_menu_access($node, $task);
}
function hosting_task_node_info() {
$types["task"] = array(
"type" => 'task',
"name" => 'Task',
"module" => 'hosting_task',
"has_title" => FALSE,
"title_label" => '',
"description" => hosting_node_help("task"),
"has_body" => 0,
"body_label" => '',
"min_word_count" => 0,
);
return $types;
}
function hosting_task_access($op, $node, $account) {
if (hosting_feature('client')) {
return NULL;
}
if (user_access('administer tasks', $account)) {
return TRUE;
}
}
function hosting_task_perm() {
return array(
'administer tasks',
'create backup task',
'create restore task',
'create disable task',
'create enable task',
'create delete task',
'create verify task',
'create lock task',
'create unlock task',
'create login-reset task',
'create backup-delete task',
'view own tasks',
'view task',
'access task logs',
'retry failed tasks',
'update status of tasks',
'cancel own tasks',
);
}
function hosting_task_hosting_queues() {
$queue['tasks'] = array(
'name' => t('Task queue'),
'description' => t('Process the queue of outstanding hosting tasks.'),
'type' => 'serial',
'frequency' => strtotime("1 minute", 0),
'items' => 5,
'total_items' => hosting_task_count(),
'singular' => t('task'),
'plural' => t('tasks'),
'running_items' => hosting_task_count_running(),
);
return $queue;
}
function hosting_task_log($vid, $type, $message, $error = '', $timestamp = NULL) {
static $nids = array();
$timestamp = $timestamp ? $timestamp : time();
if (!isset($nids[$vid])) {
$nids[$vid] = (int) db_result(db_query('SELECT nid FROM {hosting_task} WHERE vid = %d', $vid));
}
db_query("INSERT INTO {hosting_task_log} (vid, nid, type, message, error, timestamp) VALUES (%d, %d, '%s', '%s', '%s', %d)", $vid, $nids[$vid], $type, $message, $error, $timestamp);
}
function hosting_task_retry($task_id) {
$node = node_load($task_id);
if ($node->task_status != HOSTING_TASK_QUEUED) {
drupal_set_message(t("The task is being retried and has been added to the hosting queue again"));
hosting_task_log($node->vid, 'queue', t("The task is being retried and has been added to the hosting queue again"));
$node->revision = TRUE;
$node->changed = time();
$node->task_status = HOSTING_TASK_QUEUED;
node_save($node);
}
}
function hosting_add_task($nid, $type, $args = null, $status = HOSTING_TASK_QUEUED) {
global $user;
$task = hosting_get_most_recent_task($nid, $type);
$hostmaster_nid = hosting_get_hostmaster_nid();
if ($nid == $hostmaster_nid && in_array($type, array(
'delete',
'disable',
))) {
drupal_set_message(t('You cannot !task the Hostmaster site.', array(
'!task' => $type,
)), 'warning');
watchdog('hostmaster', t('Attempt to !task the Hostmaster site blocked.', array(
'!task' => $type,
)), array(), WATCHDOG_WARNING);
return FALSE;
}
$node = db_fetch_object(db_query("SELECT nid, uid, title FROM {node} WHERE nid=%d", $nid));
if (!$task) {
$task = new stdClass();
}
$task->type = 'task';
$task->title = t("!type !title", array(
'!type' => $type,
'!title' => $node->title,
));
$task->task_type = $type;
$task->rid = $node->nid;
$task->uid = $user->uid ? $user->uid : $node->uid;
$task->status = 1;
$task->task_status = $status;
if ($status == HOSTING_TASK_QUEUED) {
$task->revision = TRUE;
}
if (is_array($args)) {
$task->task_args = $args;
}
node_save($task);
drupal_set_message(t("Task %type was added to the queue. Next queue run is %date, server time is %time.", array(
'%type' => $type,
'%date' => format_date(_hosting_queue_next_run('tasks'), 'custom', 'H:i:sO'),
'%time' => format_date(time(), 'custom', 'H:i:sO'),
)));
return $task;
}
function hosting_task_confirm_form($form_state, $node, $task) {
drupal_add_js(drupal_get_path('module', 'hosting_task') . '/hosting_task.js');
$tasks = hosting_available_tasks($node->type);
if (!isset($tasks[$task]['dialog']) || !$tasks[$task]['dialog']) {
hosting_add_task($node->nid, $task);
drupal_goto('node/' . $node->nid);
}
$form['help'] = array(
'#value' => $tasks[$task]['description'],
);
$form['nid'] = array(
'#type' => 'value',
'#value' => $node->nid,
);
$form['task'] = array(
'#type' => 'value',
'#value' => $task,
);
$form['parameters'] = array(
'#tree' => TRUE,
);
$func = 'hosting_task_' . str_replace('-', '_', $task) . '_form';
if (function_exists($func)) {
$form['parameters'] += $func($node);
}
$func = $func . '_validate';
if (function_exists($func)) {
$form['#validate'][] = $func;
$form['#func_param_1'] = $node;
$form['#func_param_2'] = $task;
}
$question = t("Are you sure you want to @task @object?", array(
'@task' => $task,
'@object' => $node->title,
));
$path = !empty($_REQUEST['destination']) ? $_REQUEST['destination'] : 'node/' . $node->nid;
$form = confirm_form($form, $question, $path, '', $tasks[$task]['title']);
$form['actions']['#prefix'] = '<div id="hosting-task-confirm-form-actions" class="container-inline">';
return $form;
}
function hosting_task_restore_form($node) {
$list = hosting_site_backup_list($node->nid);
if (sizeof($list)) {
$form['bid'] = array(
'#type' => 'radios',
'#title' => t('Backups'),
'#options' => $list,
'#required' => TRUE,
);
}
else {
$form['no_backups'] = array(
'#type' => 'item',
'#title' => t('Backups'),
'#value' => t('There are no valid backups available.'),
);
}
return $form;
}
function hosting_task_restore_form_validate($form, &$form_state) {
if ($form['parameters']['no_backups']) {
form_set_error('no_backups', t('There are no valid backups available.'));
}
}
function hosting_task_confirm_form_submit($form, &$form_state) {
$values = $form_state['values'];
hosting_add_task($values['nid'], $values['task'], $values['parameters']);
$form_state['redirect'] = 'node/' . $values['nid'];
modalframe_close_dialog();
}
function hosting_task_set_title(&$node) {
$ref = db_fetch_object(db_query("SELECT vid, nid, title, type FROM {node} WHERE nid=%d", $node->rid));
$tasks = hosting_available_tasks($ref->type);
$node->title = drupal_ucfirst($tasks[$node->task_type]['title']) . ': ' . $ref->title;
db_query("UPDATE {node} SET title='%s' WHERE nid=%d", $node->title, $node->nid);
db_query("UPDATE {node_revisions} SET title='%s' WHERE vid=%d", $node->title, $node->vid);
}
function hosting_tasks_queue($count = 20) {
global $provision_errors;
drush_log(dt("Running tasks queue"));
$tasks = _hosting_get_new_tasks($count);
foreach ($tasks as $task) {
drush_invoke_process('@self', "hosting-task", array(
$task->nid,
), array(
'strict' => FALSE,
), array(
'fork' => TRUE,
));
}
}
function hosting_task_outstanding($nid, $type) {
$return = db_result(db_query("\n SELECT t.nid FROM {hosting_task} t\n INNER JOIN {node} n ON t.vid = n.vid \n WHERE \n t.rid = %d \n AND t.task_status = %d \n AND t.task_type = '%s' \n ORDER BY t.vid DESC\n LIMIT 1", $nid, HOSTING_TASK_QUEUED, $type));
return $return;
}
function hosting_task_count() {
return db_result(db_query("SELECT COUNT(t.vid) FROM {hosting_task} t INNER JOIN {node} n ON t.vid = n.vid WHERE t.task_status = %d", HOSTING_TASK_QUEUED));
}
function hosting_task_count_running() {
return db_result(db_query("SELECT COUNT(t.nid) FROM {node} n INNER JOIN {hosting_task} t ON n.vid=t.vid WHERE type='task' AND t.task_status = '%d'", HOSTING_TASK_PROCESSING));
}
function hosting_available_tasks($type = NULL, $reset = FALSE) {
static $cache = array();
if (!sizeof($cache) || $reset) {
$cache = module_invoke_all('hosting_tasks');
drupal_alter('hosting_tasks', $cache);
}
if (isset($type)) {
return $cache[$type];
}
else {
return $cache;
}
}
function hosting_task_insert($node) {
$node->executed = isset($node->executed) ? $node->executed : NULL;
$node->delta = isset($node->delta) ? $node->delta : NULL;
db_query("INSERT INTO {hosting_task} (vid, nid, task_type, task_status, rid, executed, delta) VALUES (%d, %d, '%s', %d, %d, %d, %d)", $node->vid, $node->nid, $node->task_type, $node->task_status, $node->rid, $node->executed, $node->delta);
if (isset($node->task_args) && is_array($node->task_args)) {
foreach ($node->task_args as $key => $value) {
db_query("INSERT INTO {hosting_task_arguments} (vid, nid, name, value) VALUES (%d, %d, '%s', '%s')", $node->vid, $node->nid, $key, $value);
}
}
hosting_task_set_title($node);
}
function hosting_task_update($node) {
if (!empty($node->revision)) {
hosting_task_insert($node);
}
else {
hosting_task_set_title($node);
db_query("UPDATE {hosting_task} SET nid=%d, task_type = '%s', task_status = %d, rid = %d, executed=%d, delta=%d WHERE vid=%d", $node->nid, $node->task_type, $node->task_status, $node->rid, $node->executed, $node->delta, $node->vid);
if (isset($node->task_args) && is_array($node->task_args)) {
db_query("DELETE FROM {hosting_task_arguments} WHERE vid=%d", $node->vid);
foreach ($node->task_args as $key => $value) {
db_query("INSERT INTO {hosting_task_arguments} (vid, nid, name, value) VALUES (%d, %d, '%s', '%s')", $node->vid, $node->nid, $key, $value);
}
}
}
}
function hosting_nodeapi_task_delete_revision(&$node) {
db_query('DELETE FROM {hosting_task} WHERE vid = %d', $node->vid);
db_query('DELETE FROM {hosting_task_arguments} WHERE vid = %d', $node->vid);
db_query('DELETE FROM {hosting_task_log} WHERE vid = %d', $node->vid);
}
function hosting_task_delete($node) {
db_query('DELETE FROM {hosting_task} WHERE nid = %d', $node->nid);
db_query('DELETE FROM {hosting_task_arguments} WHERE nid = %d', $node->nid);
db_query('DELETE FROM {hosting_task_log} WHERE nid = %d', $node->nid);
}
function hosting_task_load($node) {
$additions = db_fetch_object(db_query('SELECT task_type, executed, delta, rid, task_status FROM {hosting_task} WHERE vid = %d', $node->vid));
$result = db_query("SELECT name, value FROM {hosting_task_arguments} WHERE vid=%d", $node->vid);
if ($result) {
while ($arg = db_fetch_object($result)) {
$additions->task_args[$arg->name] = $arg->value;
}
}
return $additions;
}
function hosting_task_retry_form($form_state, $nid) {
$form['#prefix'] = '<div class="hosting-task-retry">';
$form['task'] = array(
'#type' => 'hidden',
'#default_value' => $nid,
);
$form['retry'] = array(
'#type' => 'submit',
'#value' => t('Retry'),
);
$form['#suffix'] = '</div>';
return $form;
}
function hosting_task_retry_form_submit($form, &$form_state) {
hosting_task_retry($form_state['values']['task']);
modalframe_close_dialog();
}
function hosting_task_update_status_form($form_state, $vid) {
$form['#prefix'] = '<div class="hosting-task-retry">';
$form['task'] = array(
'#type' => 'hidden',
'#default_value' => $vid,
);
$form['update-status'] = array(
'#type' => 'submit',
'#value' => t('Update status'),
);
$form['#suffix'] = '</div>';
return $form;
}
function hosting_task_update_status_form_submit($form, &$form_state) {
hosting_task_update_status($form_state['values']['task']);
modalframe_close_dialog();
}
function hosting_task_view($node, $teaser = FALSE, $page = FALSE) {
drupal_add_js(drupal_get_path('module', 'hosting') . '/hosting.js');
$node = node_prepare($node, $teaser);
$ref = node_load($node->rid);
hosting_set_breadcrumb($node);
$node->content['info']['#prefix'] = '<div id="hosting-task-info" class="clear-block">';
$node->content['info']['reference'] = array(
'#type' => 'item',
'#title' => drupal_ucfirst($ref->type),
'#value' => _hosting_node_link($node->rid),
);
if ($node->task_status != HOSTING_TASK_QUEUED) {
if ($node->task_status == HOSTING_TASK_PROCESSING) {
$node->content['info']['started'] = array(
'#type' => 'item',
'#title' => t('Started'),
'#value' => format_date($node->executed),
'#weight' => 1,
);
$node->content['info']['delta'] = array(
'#type' => 'item',
'#title' => t('Processing time'),
'#value' => format_interval(time() - $node->executed),
'#weight' => 2,
);
}
else {
$node->content['info']['executed'] = array(
'#type' => 'item',
'#title' => t('Executed'),
'#value' => format_date($node->executed),
'#weight' => 1,
);
$node->content['info']['delta'] = array(
'#type' => 'item',
'#title' => t('Execution time'),
'#value' => format_interval($node->delta),
'#weight' => 2,
);
}
}
else {
$queues = hosting_get_queues();
$queue = $queues['tasks'];
$next = _hosting_queue_next_run($queue);
$node->content['info']['notexecuted'] = array(
'#type' => 'item',
'#title' => t('This task has not been processed yet'),
'#value' => t('It will be processed around %date, if the queue is not too crowded. The queue is currently run every %freq, was last run %last and processes %items items at a time. Server time is %time.', array(
'%freq' => format_interval($queue['frequency']),
'%date' => format_date($next, 'custom', 'H:i:sO'),
'%last' => hosting_format_interval($queue['last_run']),
'%items' => $queue['items'],
'%time' => format_date(time(), 'custom', 'H:i:sO'),
)),
);
}
if ($node->task_status) {
$node->content['info']['status'] = array(
'#type' => 'item',
'#title' => t('Status'),
'#value' => _hosting_parse_error_code($node->task_status),
);
}
$node->content['info']['#suffix'] = '</div>';
if (user_access('retry failed tasks') && $node->task_status == HOSTING_TASK_ERROR) {
$node->content['retry'] = array(
'#type' => 'markup',
'#value' => drupal_get_form('hosting_task_retry_form', $node->nid),
'#weight' => 5,
);
}
if (user_access('update status of tasks') && $node->task_status == HOSTING_TASK_PROCESSING) {
$node->content['update-status'] = array(
'#type' => 'markup',
'#value' => drupal_get_form('hosting_task_update_status_form', $node->vid),
'#weight' => 5,
);
}
if (user_access('access task logs')) {
if ($table = _hosting_task_log_table($node->vid)) {
$node->content['hosting_log'] = array(
'#weight' => 10,
'#type' => 'item',
'#value' => $table,
);
}
}
return $node;
}
function _hosting_task_log_table($vid) {
$result = db_query("SELECT * FROM {hosting_task_log} WHERE vid = %d ORDER BY lid", $vid);
if ($result) {
$header = array(
'data' => 'Log message',
);
while ($entry = db_fetch_object($result)) {
if (strlen($entry->message) > 300) {
$summary = "<span class='hosting-task-summary'>" . filter_xss(substr($entry->message, 0, 75), array()) . "... <a href='javascript:void(0)' class='hosting-summary-expand modalframe-exclude'>(" . t('Expand') . ')</a></span>';
$message = $summary . "<span class='hosting-task-full'>" . filter_xss($entry->message) . '</span>';
}
else {
$message = filter_xss($entry->message);
}
$row = array(
array(
'data' => $message,
'class' => 'hosting-status',
),
);
$rows[] = array(
'data' => $row,
'class' => _hosting_task_log_class($entry->type),
);
}
return theme("table", $header, (array) $rows, array(
'id' => 'hosting-task-log',
'class' => 'hosting-table',
));
}
return false;
}
function _hosting_task_log_class($type) {
switch (strtolower($type)) {
case 'warning':
case 'cancel':
case 'rollback':
$type = 'warning';
break;
case 'failed':
case 'error':
$type = 'error';
break;
case 'queue':
$type = 'queue';
break;
case 'ok':
case 'completed':
case 'success':
$type = 'success';
break;
case 'notice':
case 'info':
case 'message':
default:
$type = 'info';
}
return 'hosting-' . $type;
}
function hosting_get_most_recent_task($rid, $type) {
$nid = db_result(db_query("SELECT t.nid FROM {hosting_task} t INNER JOIN {node} n ON n.vid = t.vid WHERE task_type='%s' and t.rid=%d ORDER BY t.vid DESC limit 1", $type, $rid));
if ($nid) {
return node_load($nid);
}
return false;
}
function hosting_get_tasks($filter_by = null, $filter_value = null, $count = 5, $element = 0) {
$nodes = array();
$args[] = 'task';
$cond = '';
if ($filter_by && $filter_value) {
$cond = ' AND t.' . $filter_by . ' = %d';
$args[] = $filter_value;
}
$result = pager_query(db_rewrite_sql("SELECT n.*, t.task_status, t.task_type, t.rid FROM {node} n INNER JOIN {hosting_task} t on n.vid=t.vid WHERE type='%s'" . $cond . " ORDER BY n.vid DESC"), $count, $element, NULL, $args);
while ($row = db_fetch_object($result)) {
$nodes[] = $row;
}
return $nodes;
}
function _hosting_get_new_tasks($limit = 20) {
$return = array();
$result = db_query("SELECT t.nid\n FROM {hosting_task} t\n INNER JOIN {node} n ON t.vid = n.vid\n WHERE t.task_status = %d GROUP BY t.rid ORDER BY n.changed, n.nid ASC LIMIT %d", HOSTING_TASK_QUEUED, $limit);
while ($node = db_fetch_object($result)) {
$return[$node->nid] = node_load($node->nid);
}
return $return;
}
define('HOSTING_TASK_PROCESSING', -1);
define('HOSTING_TASK_QUEUED', 0);
define('HOSTING_TASK_SUCCESS', 1);
define('HOSTING_TASK_ERROR', 2);
define('HOSTING_TASK_WARNING', 3);
function _hosting_task_error_codes() {
$codes = array(
HOSTING_TASK_SUCCESS => t('Successful'),
HOSTING_TASK_QUEUED => t('Queued'),
HOSTING_TASK_ERROR => t('Failed'),
HOSTING_TASK_PROCESSING => t('Processing'),
HOSTING_TASK_WARNING => t('Warning'),
);
return $codes;
}
function _hosting_parse_error_code($code) {
$messages = _hosting_task_error_codes();
return $messages[$code];
}
function hosting_task_status($filter_by, $filter_value, $type = 'install') {
$args[] = 'task';
$args[] = $type;
$cond = '';
if ($filter_by && $filter_value) {
$cond = ' AND t.' . $filter_by . ' = %d';
$args[] = $filter_value;
}
$result = db_fetch_array(db_query("SELECT t.task_status AS status FROM {node} n INNER JOIN {hosting_task} t on n.vid=t.vid WHERE n.type='%s' AND t.task_type='%s' " . $cond . " ORDER BY t.vid DESC", $args));
return $result['status'];
}
function hosting_task_status_output($filter_by, $filter_value, $type = 'install') {
$status = hosting_task_status($filter_by, $filter_value, $type);
if (is_int($status)) {
return _hosting_parse_error_code($status);
}
else {
return $status;
}
}
function hosting_task_list($filter_by = null, $filter_value = null) {
return _hosting_task_list($filter_by, $filter_value, 25, 12, 'title');
}
function hosting_task_summary($filter_by = null, $filter_value = null) {
modalframe_parent_js();
$more_link = l(t('More tasks'), 'hosting/queues/tasks');
return hosting_task_queue_block() . $more_link;
}
function hosting_task_queue_block() {
drupal_add_js(drupal_get_path('module', 'hosting_task') . '/hosting_task.js');
$settings['hostingTaskRefresh'] = array(
'queueBlock' => 1,
);
drupal_add_js($settings, 'setting');
$nodes = hosting_get_tasks('t.task-status', HOSTING_TASK_QUEUED, 5);
$headers = array(
t('Task'),
t('Actions'),
);
$rows[] = array();
foreach ($nodes as $node) {
$row = array();
$row['type'] = array(
'data' => drupal_ucfirst(str_replace(array(
'_',
'-',
), ' ', $node->task_type)) . ' ' . _hosting_node_link($node->rid),
'class' => 'hosting-status',
);
$log_button = _hosting_task_button(t('View'), 'node/' . $node->nid, t("Display the task log"), 'hosting-button-log', isset($node->nid) && user_access('access task logs'), true, false);
$row['actions'] = array(
'data' => $log_button,
'class' => 'hosting-actions',
);
$class = hosting_task_status_class($node->task_status);
$rows[] = array(
'data' => $row,
'class' => $class,
);
}
return "<div id='hosting-task-queue-block'>" . theme('table', $headers, $rows, array(
'class' => 'hosting-table',
)) . "</div>";
}
function hosting_task_table($node) {
$output = '';
$headers[] = t('Task');
$headers[] = array(
'data' => t('Actions'),
'class' => 'hosting-actions',
);
$tasklist = hosting_task_fetch_tasks($node->nid);
foreach ($tasklist as $task => $info) {
$row = array();
if (!isset($info['nid']) && !$info['task_permitted']) {
continue;
}
$row['type'] = array(
'data' => $info['title'],
'class' => 'hosting-status',
);
$actions = array();
if (isset($info['task_status']) && $info['task_status'] == 0) {
$actions['cancel'] = _hosting_task_button(t('Cancel'), sprintf("hosting/tasks/%d/cancel", $info['nid']), t("Cancel the task and remove it from the queue"), 'hosting-button-stop', !$info['task_permitted']);
}
else {
$actions['run'] = _hosting_task_button(t('Run'), sprintf("node/%d/%s_%s", $node->nid, $node->type, $task), $info['description'], 'hosting-button-run', $info['task_permitted'], $info['dialog']);
}
$actions['log'] = _hosting_task_button(t('View'), isset($info['nid']) ? 'node/' . $info['nid'] : '<front>', t("Display the task log"), 'hosting-button-log', isset($info['nid']) && user_access('access task logs'), TRUE, FALSE);
$row['actions'] = array(
'data' => implode('', $actions),
'class' => 'hosting-actions',
);
$rows[] = array(
'data' => $row,
'class' => $info['class'],
);
}
$output .= theme('table', $headers, $rows, array(
'class' => 'hosting-table',
));
return $output;
}
function _hosting_task_button($title, $link, $description, $class = '', $status = TRUE, $dialog = FALSE, $add_token = TRUE) {
global $user;
if ($status) {
$classes[] = 'hosting-button-enabled';
if (!empty($class)) {
$classes[] = $class;
}
if ($dialog) {
$classes[] = 'hosting-button-dialog';
}
$options['attributes'] = array(
'title' => $description,
'class' => implode(" ", $classes),
);
if ($add_token) {
$options['query'] = array(
'token' => drupal_get_token($user->uid),
);
}
return l($title, $link, $options);
}
else {
return "<span class='hosting-button-disabled'>" . $title . "</span>";
}
}
function _hosting_task_list($filter_by, $filter_value, $count = 5, $element = 0, $field = 'title', $skip = array(), $pager = TRUE) {
$nodes = hosting_get_tasks($filter_by, $filter_value, $count, $element);
if (!$nodes) {
return t('No tasks available');
}
else {
$headers[t('Task')] = '';
foreach ($nodes as $node) {
$row = array();
if ($field == 'title') {
$data = drupal_ucfirst($node->task_type) . ' ' . _hosting_node_link($node->rid);
}
else {
$data = $node->{$field};
}
$row['type'] = array(
'data' => $data,
'class' => 'hosting-status',
);
if (!in_array('created', $skip)) {
$row['created'] = t("@interval ago", array(
'@interval' => format_interval(time() - $node->created, 1),
));
$headers[t('Created')] = '';
}
$row['executed'] = t("@interval ago", array(
'@interval' => format_interval(time() - $node->changed, 1),
));
$headers[t('Executed')] = '';
$headers[t('Actions')] = '';
$actions['log'] = l(t('View'), 'node/' . $node->nid, array(
'attributes' => array(
'class' => 'hosting-button-dialog hosting-button-enabled hosting-button-log',
),
));
$row['actions'] = array(
'data' => $actions['log'],
'class' => 'hosting-actions',
);
$class = hosting_task_status_class($node->task_status);
$rows[] = array(
'data' => $row,
'class' => $class,
);
}
$output = theme('table', array_keys($headers), $rows, array(
'class' => 'hosting-table',
));
if ($pager === TRUE) {
$output .= theme('pager', NULL, $count, $element);
}
elseif (is_string($pager)) {
$output .= $pager;
}
return $output;
}
}
function hosting_task_fetch_tasks($rid) {
$node = node_load($rid);
$result = db_query("SELECT n.nid, t.task_type, t.task_status FROM {node} n INNER JOIN {hosting_task} t ON n.vid = t.vid \n WHERE n.type = 'task' AND t.rid = %d\n ORDER BY t.task_status ASC, n.changed DESC", $rid);
while ($obj = db_fetch_object($result)) {
$return[$obj->task_type] = array(
'nid' => $obj->nid,
'task_status' => $obj->task_status,
'exists' => TRUE,
);
}
$tasks = hosting_available_tasks($node->type);
ksort($tasks);
foreach ($tasks as $type => $hook_task) {
if (!isset($return[$type])) {
$return[$type] = array();
}
$access_callback = !empty($hook_task['access callback']) ? $hook_task['access callback'] : 'hosting_task_menu_access';
$task = array();
$task = array_merge($return[$type], $hook_task);
$allowed = isset($task['exists']) && !in_array($task['task_status'], array(
HOSTING_TASK_QUEUED,
HOSTING_TASK_PROCESSING,
)) || !isset($task['exists']);
if ($allowed && empty($task['hidden']) && $access_callback($node, $type)) {
$task['task_permitted'] = TRUE;
}
else {
$task['task_permitted'] = FALSE;
}
if (!isset($task['dialog'])) {
$task['dialog'] = FALSE;
}
if (!isset($task['task_status'])) {
$task['task_status'] = NULL;
}
$task['class'] = hosting_task_status_class($task['task_status']);
$return[$type] = $task;
}
return $return;
}
function hosting_task_status_class($status = null) {
$class = null;
if (!is_null($status)) {
switch ($status) {
case HOSTING_TASK_SUCCESS:
$class = 'hosting-success';
break;
case HOSTING_TASK_ERROR:
$class = 'hosting-error';
break;
case HOSTING_TASK_QUEUED:
$class = 'hosting-queue';
break;
case HOSTING_TASK_PROCESSING:
$class = 'hosting-processing';
break;
case HOSTING_TASK_WARNING:
$class = 'hosting-warning';
break;
}
}
return $class;
}
function hosting_task_views_api() {
return array(
'api' => 3,
'path' => drupal_get_path('module', 'hosting_task'),
);
}
function hosting_task_preprocess_views_view_table(&$vars) {
$id = "{$vars['view']->name}-{$vars['view']->current_display}";
switch ($id) {
case 'hosting_task_list-block':
modalframe_parent_js();
drupal_add_js(drupal_get_path('module', 'hosting_task') . '/hosting_task.js');
$settings['hostingTaskRefresh'] = array(
'queueBlock' => 1,
);
drupal_add_js($settings, 'setting');
break;
}
}
function hosting_task_update_status($task) {
if (is_numeric($task)) {
$vid = $task;
}
else {
$vid = $task->vid;
}
$status = hosting_task_parse_log($vid);
db_query('UPDATE {hosting_task} SET task_status=%d WHERE vid = %d', $status, $vid);
module_invoke_all('hosting_task_update_status', $task, $status);
return $status;
}
function hosting_task_parse_log($vid) {
$update = HOSTING_TASK_SUCCESS;
$result = db_query('SELECT type FROM {hosting_task_log} WHERE vid = %d', $vid);
while ($status = db_result($result)) {
if ($status == 'error' || $status == 'failed') {
$update = HOSTING_TASK_ERROR;
}
elseif ($update != HOSTING_TASK_ERROR && $status == 'warning') {
$update = HOSTING_TASK_WARNING;
}
}
return $update;
}