schedules.inc in Backup and Migrate 5.2
Same filename and directory in other branches
All of the schedule handling code needed for Backup and Migrate.
File
includes/schedules.incView source
<?php
/**
* @file
* All of the schedule handling code needed for Backup and Migrate.
*/
/**
* Run the preconfigured schedules. Called on cron.
*/
function backup_migrate_schedules_run() {
require_once './' . drupal_get_path('module', 'backup_migrate') . '/includes/profiles.inc';
foreach (backup_migrate_get_schedules() as $schedule) {
$now = time();
if ($schedule['enabled'] && $schedule['last_run'] < $now - $schedule['period']) {
if ($settings = backup_migrate_get_profile($schedule['profile_id'])) {
$settings['destination_id'] = $schedule['destination_id'];
backup_migrate_perform_backup($settings);
_backup_migrate_schedule_set_last_run($schedule['schedule_id'], $now);
_backup_migrate_schedule_remove_expired_backups($schedule['destination_id'], $schedule['keep']);
}
else {
_backup_migrate_message("Schedule '%schedule' could not be run because requires a profile which is missing.", array(
'%schedule' => $schedule['name'],
), 'error');
}
}
}
}
/**
* Get all the available backup schedules.
*/
function backup_migrate_get_schedules() {
static $schedules = NULL;
// Get the list of schedules and cache them locally.
if ($schedules === NULL) {
$schedules = array();
$all_schedules = module_invoke_all('backup_migrate_schedules');
// Reindex since module_invoke_all stomps on numerical indices (thanks to array_merge).
foreach ($all_schedules as $schedule) {
$schedules[$schedule['schedule_id']] = $schedule;
}
}
return $schedules;
}
/**
* Get the schedule info for the schedule with the given ID, or NULL if none exists.
*/
function backup_migrate_get_schedule($schedule_id) {
$schedules = backup_migrate_get_schedules();
return @$schedules[$schedule_id];
}
/**
* Implementation of hook_backup_migrate_schedules().
*
* Get the backup schedules stored in the db.
*/
function backup_migrate_backup_migrate_schedules() {
// Get the saved scheduless
$result = db_query('SELECT * FROM {backup_migrate_schedules}');
while ($schedule = db_fetch_array($result)) {
$schedule['db'] = TRUE;
$out[$schedule['schedule_id']] = $schedule;
}
return $out;
}
/**
* Update an existing schedule or create a new one.
*/
function backup_migrate_schedule_save_schedule(&$schedule) {
// Calculate the period in seconds
$periods = _backup_migrate_frequency_periods();
$period = $periods[$schedule['period']['type']];
$schedule['period'] = $schedule['period']['number'] * $period['seconds'];
if ($schedule['schedule_id']) {
db_query("UPDATE {backup_migrate_schedules} \n SET name = '%s',\n destination_id = '%s',\n profile_id = %d,\n keep = %d,\n period = %d,\n enabled = %d\n WHERE schedule_id = %d", $schedule['name'], $schedule['destination_id'], $schedule['profile_id'], $schedule['keep'], $schedule['period'], $schedule['enabled'], $schedule['schedule_id']);
}
else {
$schedule['schedule_id'] = db_next_id('{backup_migrate_schedules}_schedule_id');
db_query("INSERT INTO {backup_migrate_schedules} (schedule_id, name, destination_id, profile_id, keep, period, enabled) VALUES (%d, '%s', '%s', %d, %d, %d, %d)", $schedule['schedule_id'], $schedule['name'], $schedule['destination_id'], $schedule['profile_id'], $schedule['keep'], $schedule['period'], $schedule['enabled']);
}
}
/**
* Delete a saved schedule from the database.
*/
function backup_migrate_schedule_delete_schedule($schedule_id) {
$schedule = backup_migrate_get_schedule($schedule_id);
if ($schedule && $schedule['db']) {
db_query("DELETE FROM {backup_migrate_schedules} WHERE schedule_id = %d", $schedule_id);
_backup_migrate_message('Schedule deleted: %schedule', array(
'%schedule' => $schedule['name'],
));
}
}
/* UI Menu Callbacks */
/**
* List the the available schedules in the UI.
*/
function backup_migrate_ui_schedule_display_schedules() {
require_once './' . drupal_get_path('module', 'backup_migrate') . '/includes/destinations.inc';
require_once './' . drupal_get_path('module', 'backup_migrate') . '/includes/profiles.inc';
$out = array();
foreach (backup_migrate_get_schedules() as $schedule) {
$destination = backup_migrate_get_destination($schedule['destination_id']);
$profile = backup_migrate_get_profile($schedule['profile_id']);
$row = array(
check_plain($schedule['name']),
$destination ? l($destination['name'], 'admin/content/backup_migrate/destination/files/' . $destination['destination_id']) : t("Missing"),
$profile ? $profile['name'] : t("Missing"),
_backup_migrate_schedule_format_frequency($schedule['period']),
$schedule['keep'] ? $schedule['keep'] : t('All'),
$schedule['enabled'] ? t('Enabled') : t('Disabled'),
$schedule['last_run'] ? format_date($schedule['last_run'], 'small') : t('Never'),
implode(" | ", _backup_migrate_schedule_get_links($schedule['schedule_id'])),
);
if (!$schedule['enabled']) {
foreach ($row as $key => $field) {
$row[$key] = array(
'data' => $field,
'class' => 'schedule-list-disabled',
);
}
}
$out[] = $row;
}
$headers = array(
t('Name'),
t('Destination'),
t('Profile'),
t('Frequency'),
t('Keep'),
t('Enabled'),
t('Last run'),
t('Operations'),
);
drupal_add_css(drupal_get_path('module', 'backup_migrate') . '/backup_migrate.css');
if ($out) {
$out = theme("table", $headers, $out);
}
else {
$out = t('There are no schedules to display.');
}
return $out . ' ' . l(t("Create new schedule..."), 'admin/content/backup_migrate/schedule/add');
}
/**
* Get a form to create a new schedule.
*/
function backup_migrate_ui_schedule_create() {
$schedule = array(
'name' => t("Untitled Schedule"),
'enabled' => 1,
'keep' => 0,
'period' => 60 * 60 * 24,
);
$output = drupal_get_form('backup_migrate_ui_schedule_configure_form', $schedule);
return $output;
}
/**
* Get a form to configure the schedule.
*/
function backup_migrate_ui_schedule_configure($schedule_id) {
if ($schedule = backup_migrate_get_schedule($schedule_id)) {
return drupal_get_form('backup_migrate_ui_schedule_configure_form', $schedule);
}
return NULL;
}
/**
* Get a form to configure the schedule.
*/
function backup_migrate_ui_schedule_configure_form($schedule) {
if ($schedule) {
require_once './' . drupal_get_path('module', 'backup_migrate') . '/includes/destinations.inc';
require_once './' . drupal_get_path('module', 'backup_migrate') . '/includes/profiles.inc';
$form = array();
$form['schedule_id'] = array(
"#type" => "value",
"#default_value" => $schedule['schedule_id'],
);
$form['enabled'] = array(
"#type" => "checkbox",
"#title" => t("Enabled"),
"#field_suffix" => t("Hour(s)"),
"#default_value" => $schedule['enabled'],
);
$form['name'] = array(
"#type" => "textfield",
"#title" => t("Schedule Name"),
"#default_value" => $schedule['name'],
);
$form['profile_id'] = array(
"#type" => "select",
"#title" => t("Settings Profile"),
"#options" => _backup_migrate_get_profile_form_item_options(),
"#default_value" => $schedule['profile_id'],
);
$form['profile_id']['#description'] .= ' ' . l(t("Create new profile..."), "admin/content/backup_migrate/profile/add");
if (!$form['profile_id']['#options']) {
$form['profile_id']['#options'] = array(
'0' => t('-- None Available --'),
);
}
$period_options = array();
foreach (_backup_migrate_frequency_periods() as $type => $period) {
$period_options[$type] = $period['title'];
}
$default_period = _backup_migrate_schedule_get_frequency_period($schedule['period']);
$default_period_num = $schedule['period'] / $default_period['seconds'];
$form['period'] = array(
"#type" => "item",
"#title" => t("Backup every"),
"#prefix" => '<div class="container-inline">',
"#suffix" => '</div>',
"#tree" => TRUE,
);
$form['period']['number'] = array(
"#type" => "textfield",
"#size" => 6,
"#default_value" => $default_period_num,
);
$form['period']['type'] = array(
"#type" => "select",
"#options" => $period_options,
"#default_value" => $default_period['type'],
);
$form['keep'] = array(
"#type" => "textfield",
"#size" => 6,
"#title" => t("Number of Backup files to keep"),
"#description" => t("The number of backup files to keep before deleting old ones. Use 0 to never delete backups"),
"#default_value" => $schedule['keep'],
);
$destination_options = _backup_migrate_get_destination_form_item_options('scheduled backup');
$form['destination_id'] = array(
"#type" => "select",
"#title" => t("Destination"),
"#description" => t("Choose where the backup file will be saved. Backup files contain sensitive data, so be careful where you save them."),
"#options" => $destination_options,
"#default_value" => $schedule['destination_id'],
);
$form['destination_id']['#description'] .= ' ' . l(t("Create new destination..."), "admin/content/backup_migrate/destination/add");
$form['submit'] = array(
'#type' => 'submit',
'#weight' => 99,
'#value' => t('Save Schedule'),
);
return $form;
}
return array();
}
/**
* Validate the schedule configuration form.
*/
function backup_migrate_ui_schedule_configure_form_validate($form_id, $form_values) {
if (!is_numeric($form_values['period']['number']) || $form_values['period']['number'] <= 0) {
form_set_error('[period][number]', t('Backup period must be a number greater than 0.'));
}
if (!is_numeric($form_values['keep']) || $form_values['keep'] < 0) {
form_set_error('[keep]', t('Number to keep must be an integer greater than or equal to 0.'));
}
}
/**
* Submit the schedule configuration form.
*/
function backup_migrate_ui_schedule_configure_form_submit($form_id, $form_values) {
backup_migrate_schedule_save_schedule($form_values);
return "admin/content/backup_migrate/schedule";
}
/**
* Delete a schedule.
*/
function backup_migrate_ui_schedule_delete($schedule_id) {
return drupal_get_form('backup_migrate_ui_schedule_delete_confirm', $schedule_id);
}
/**
* Ask confirmation for deletion of a schedule.
*/
function backup_migrate_ui_schedule_delete_confirm($schedule_id) {
$form['schedule_id'] = array(
'#type' => 'value',
'#value' => $schedule_id,
);
$schedule = backup_migrate_get_schedule($schedule_id);
return confirm_form($form, t('Are you sure you want to delete the schedule %schedule?', array(
'%schedule' => $schedule['name'],
)), 'admin/content/backup_migrate/schedule', t('This will cannot be undone.'), t('Delete'), t('Cancel'));
}
/**
* Delete a destination after confirmation.
*/
function backup_migrate_ui_schedule_delete_confirm_submit($form_id, $form_values) {
$schedule_id = $form_values['schedule_id'];
backup_migrate_schedule_delete_schedule($schedule_id);
return "admin/content/backup_migrate/schedule";
}
/* Utilities */
/**
* Get the action links for a schedule.
*/
function _backup_migrate_schedule_get_links($schedule_id) {
$out = array();
if ($schedule = backup_migrate_get_schedule($schedule_id)) {
if ($schedule['db']) {
$out[] = l(t("Configure..."), "admin/content/backup_migrate/schedule/configure/" . $schedule_id);
$out[] = l(t("Delete..."), "admin/content/backup_migrate/schedule/delete/" . $schedule_id);
}
}
return $out;
}
/**
* Set the last run time of a schedule to the given timestamp, or now if none specified.
*/
function _backup_migrate_schedule_set_last_run($schedule_id, $timestamp = NULL) {
if ($timestamp === NULL) {
$timestamp = time();
}
if ($schedule_id) {
db_query("UPDATE {backup_migrate_schedules}\n SET last_run = %d\n WHERE schedule_id = '%s'", $timestamp, $schedule_id);
}
}
/**
* Remove older backups keeping only the number specified by the aministrator.
*/
function _backup_migrate_schedule_remove_expired_backups($destination_id, $num_to_keep) {
require_once './' . drupal_get_path('module', 'backup_migrate') . '/includes/destinations.inc';
// If num to keep is not 0 (0 is infinity).
if ($num_to_keep && ($destination = backup_migrate_get_destination($destination_id))) {
if ($destination_files = backup_migrate_destination_get_files($destination)) {
// Sort the files by modified time.
foreach ($destination_files as $file) {
$files[str_pad($file['filemtime'], 10, "0", STR_PAD_LEFT) . "-" . $i++] = $file['filepath'];
}
// If we are beyond our limit, remove as many as we need.
$num_files = count($files);
if ($num_files > $num_to_keep) {
$num_to_delete = $num_files - $num_to_keep;
// Sort by date.
ksort($files);
// Delete from the start of the list (earliest).
for ($i = 0; $i < $num_to_delete; $i++) {
$filepath = array_shift($files);
file_delete($filepath);
}
}
}
}
}
/**
* Format a frequency in human-readable form.
*/
function _backup_migrate_schedule_format_frequency($frequency) {
$period = _backup_migrate_schedule_get_frequency_period($frequency);
$out = format_plural($frequency / $period['seconds'], $period['singular'], $period['plural']);
return $out;
}
/**
* Get the period of the frequency (ie: seconds, minutes etc.)
*/
function _backup_migrate_schedule_get_frequency_period($frequency) {
$out = "";
foreach (array_reverse(_backup_migrate_frequency_periods()) as $period) {
if ($period['seconds'] && $frequency % $period['seconds'] === 0) {
return $period;
}
}
}
/**
* Get a list of available backup periods. Only returns time periods which have a
* (reasonably) consistent number of seconds.
*/
function _backup_migrate_frequency_periods() {
return array(
'seconds' => array(
'type' => 'seconds',
'seconds' => 1,
'title' => t('Seconds'),
'singular' => t('Once a second'),
'plural' => t('Every @count seconds'),
),
'minutes' => array(
'type' => 'minutes',
'seconds' => 60,
'title' => t('Minutes'),
'singular' => t('Once a minute'),
'plural' => t('Every @count minutes'),
),
'hours' => array(
'type' => 'hours',
'seconds' => 3600,
'title' => t('Hours'),
'singular' => t('Once an hour'),
'plural' => t('Every @count hours'),
),
'days' => array(
'type' => 'days',
'seconds' => 86400,
'title' => t('Days'),
'singular' => t('Once a day'),
'plural' => t('Every @count days'),
),
'weeks' => array(
'type' => 'weeks',
'seconds' => 604800,
'title' => t('Weeks'),
'singular' => t('Once a week'),
'plural' => t('Every @count weeks'),
),
);
}
Functions
Name | Description |
---|---|
backup_migrate_backup_migrate_schedules | Implementation of hook_backup_migrate_schedules(). |
backup_migrate_get_schedule | Get the schedule info for the schedule with the given ID, or NULL if none exists. |
backup_migrate_get_schedules | Get all the available backup schedules. |
backup_migrate_schedules_run | Run the preconfigured schedules. Called on cron. |
backup_migrate_schedule_delete_schedule | Delete a saved schedule from the database. |
backup_migrate_schedule_save_schedule | Update an existing schedule or create a new one. |
backup_migrate_ui_schedule_configure | Get a form to configure the schedule. |
backup_migrate_ui_schedule_configure_form | Get a form to configure the schedule. |
backup_migrate_ui_schedule_configure_form_submit | Submit the schedule configuration form. |
backup_migrate_ui_schedule_configure_form_validate | Validate the schedule configuration form. |
backup_migrate_ui_schedule_create | Get a form to create a new schedule. |
backup_migrate_ui_schedule_delete | Delete a schedule. |
backup_migrate_ui_schedule_delete_confirm | Ask confirmation for deletion of a schedule. |
backup_migrate_ui_schedule_delete_confirm_submit | Delete a destination after confirmation. |
backup_migrate_ui_schedule_display_schedules | List the the available schedules in the UI. |
_backup_migrate_frequency_periods | Get a list of available backup periods. Only returns time periods which have a (reasonably) consistent number of seconds. |
_backup_migrate_schedule_format_frequency | Format a frequency in human-readable form. |
_backup_migrate_schedule_get_frequency_period | Get the period of the frequency (ie: seconds, minutes etc.) |
_backup_migrate_schedule_get_links | Get the action links for a schedule. |
_backup_migrate_schedule_remove_expired_backups | Remove older backups keeping only the number specified by the aministrator. |
_backup_migrate_schedule_set_last_run | Set the last run time of a schedule to the given timestamp, or now if none specified. |