drupal-civicrm/sites/all/modules/backup_migrate/includes/locations.inc

544 lines
14 KiB
PHP
Raw Permalink Normal View History

2018-01-14 15:10:16 +02:00
<?php
/**
* @file
* All of the location handling code needed for Backup and Migrate.
*/
backup_migrate_include('crud');
/**
* Get the available location types.
*/
function backup_migrate_get_location_subtypes() {
backup_migrate_include('crud', 'destinations', 'sources');
return backup_migrate_crud_subtypes('destination') + backup_migrate_crud_subtypes('source');
}
/**
* Implementation of hook_backup_migrate_locations().
*
* Get the built in backup locations and those in the db.
*/
function backup_migrate_backup_migrate_locations() {
$out = array();
// Allow the filter plugins to declare the default locations.
backup_migrate_include('filters');
$out += backup_migrate_filters_invoke_all('locations');
return $out;
}
/**
* Get all the available backup location.
*
* @param $op
* The operation which will be performed on the location. Hooks can use this
* to return only those locations appropriate for the given op.
* Options include:
* 'manual backup' - locations available for manual backup
* 'scheduled backup' - locations available for schedules backup
* 'list files' - locations whose backup files can be listed
* 'restore' - locations whose files can be restored from
* 'all' - all available locations should be returned
*/
function backup_migrate_get_locations($op = 'all') {
$locations = &drupal_static('backup_migrate_get_locations', NULL);
// Get the list of locations and cache them locally.
if ($locations === NULL) {
$locations = backup_migrate_crud_get_items('location');
}
// Return all if that's what was asked for.
if ($op == 'all') {
return $locations;
}
// Return only those locations which support the given op.
$out = array();
if ($locations) {
foreach ($locations as $key => $location) {
if ($location->op($op)) {
$out[$key] = $location;
}
}
}
return $out;
}
/**
* Get the location of the given id.
*/
function backup_migrate_get_location($id) {
$locations = backup_migrate_get_locations('all');
return empty($locations[$id]) ? NULL : $locations[$id];
}
/**
* A base class for creating locations.
*/
class backup_migrate_location extends backup_migrate_item {
var $db_table = "backup_migrate_destinations";
var $type_name = "location";
var $default_values = array('settings' => array());
var $singular = 'location';
var $plural = 'locations';
var $title_plural = 'Locations';
var $title_singular = 'Location';
var $subtype = "";
var $supported_ops = array();
/**
* This function is not supposed to be called. It is just here to help the po extractor out.
*/
function strings() {
// Help the pot extractor find these strings.
t('location');
t('locations');
t('Location');
t('Locations');
}
function ops() {
return $this->supported_ops;
}
/**
* Does this location support the given operation.
*/
function op($op) {
$ops = (array)$this->ops();
return in_array($op, $ops);
}
/**
* Remove the given op from the support list.
*/
function remove_op($op) {
$key = array_search($op, $this->supported_ops);
if ($key !== FALSE) {
unset($this->supported_ops[$key]);
}
}
function get_name() {
return @$this->name;
}
function set_name($name) {
return $this->name = $name;
}
function set_location($location) {
$this->location = $location;
}
function get_location() {
return @$this->location;
}
function get_display_location() {
return $this->get_location();
}
function settings($key = NULL) {
$out = $this->settings;
if ($key) {
$out = isset($out[$key]) ? $out[$key] : NULL;
}
return $out;
}
/**
* Get the type name of this location for display to the user.
*/
function get_subtype_name() {
if ($type = $this->get('subtype')) {
$types = $this->location_types();
return isset($types[$type]['type_name']) ? $types[$type]['type_name'] : $type;
}
}
/**
* Get the edit form for the item.
*/
function edit_form() {
if (!empty($this->supported_ops)) {
$form = parent::edit_form();
$form['subtype'] = array(
"#type" => "value",
"#default_value" => $this->get('subtype'),
);
}
else {
$types = $this->location_types();
$items = array();
// If no (valid) node type has been provided, display a node type overview.
foreach ($types as $key => $type) {
if (@$type['can_create']) {
$type_url_str = str_replace('_', '-', $key);
$out = '<dt>'. l($type['type_name'], BACKUP_MIGRATE_MENU_PATH . "/settings/$this->type_name/add/$type_url_str", array('attributes' => array('title' => t('Add a new @s location.', array('@s' => $type['type_name']))))) .'</dt>';
$out .= '<dd>'. filter_xss_admin($type['description']) .'</dd>';
$items[] = $out;
}
}
if (count($items)) {
$output = t('Choose the type of location you would like to create:') .'<dl>'. implode('', $items) .'</dl>';
}
else {
$output = t('No types available.');
}
$form['select_type'] = array(
'#type' => 'markup',
'#markup' => $output,
);
}
return $form;
}
/**
* Get the available location types.
*/
function location_types() {
return backup_migrate_get_location_subtypes();
}
/**
* Get the message to send to the user when confirming the deletion of the item.
*/
function delete_confirm_message() {
return t('Are you sure you want to delete the %name?', array('%name' => $this->get_name()));
}
/**
* Get the columns needed to list the type.
*/
function get_list_column_info() {
$out = parent::get_list_column_info();
$out = array(
'name' => array('title' => t('Name')),
'subtype_name' => array('title' => t('Type')),
'display_location' => array('title' => t('Location')),
) + $out;
return $out;
}
/**
* Get a row of data to be used in a list of items of this type.
*/
function get_list_row() {
$out = parent::get_list_row();
// Suppress locations with no actions as there's no value in showing them (and they may confuse new users).
if (empty($out['actions'])) {
return NULL;
}
return $out;
}
/**
* Get the action links for a location.
*/
function get_action_links() {
$out = parent::get_action_links();
$item_id = $this->get_id();
// Don't display the download/delete/restore ops if they are not available for this location.
if ($this->op('list files') && user_access("access backup files")) {
$out = array('list files' => l(t("list files"), BACKUP_MIGRATE_MENU_PATH . "/$this->type_name/list/files/". $item_id)) + $out;
}
if (!$this->op('configure') || !user_access('administer backup and migrate')) {
unset($out['edit']);
}
return $out;
}
/**
* Determine if we can read the given file.
*/
function can_read_file($file_id) {
return $this->op('restore');
}
/**
* Get the form for the settings for this location type.
*/
function settings_default() {
return array();
}
/**
* Get the form for the settings for this location.
*/
function settings_form($form) {
return $form;
}
/**
* Validate the form for the settings for this location.
*/
function settings_form_validate($form_values) {
}
/**
* Submit the settings form. Any values returned will be saved.
*/
function settings_form_submit($form_values) {
return $form_values;
}
/**
* Get the form for the settings for this filter.
*/
function backup_settings_default() {
return array();
}
/**
* Get the form for the settings for this filter.
*/
function backup_settings_form($settings) {
return array();
}
/**
* Get the form for the settings for this filter.
*/
function backup_settings_form_validate($form, &$form_state) {
}
/**
* Submit the settings form. Any values returned will be saved.
*/
function backup_settings_form_submit($form, &$form_state) {
}
/**
* Get the form for the settings for this filter.
*/
function restore_settings_default() {
return array();
}
/**
* Get the form for the settings for this filter.
*/
function restore_settings_form($settings) {
return array();
}
/**
* Get the form for the settings for this filter.
*/
function restore_settings_form_validate($form_values) {
}
/**
* Submit the settings form. Any values returned will be saved.
*/
function restore_settings_form_submit($form_values) {
return $form_values;
}
/**
* Create a new location of the correct type.
*/
function create($params = array()) {
$out = NULL;
$types = backup_migrate_get_location_subtypes();
// Get the type passed in in the params, or if none, check the url for a valid type name.
// This is to allow new location type to be specified in the path.
$location_type = !empty($params['subtype']) ? $params['subtype'] : NULL;
if ($location_type && ($type = @$types[$location_type])) {
// Include the necessary file if specified by the type.
if (!empty($type['file'])) {
require_once './'. $type['file'];
}
$out = new $type['class']($params + array('subtype' => $location_type));
}
if (empty($out)) {
$out = parent::create($params);
}
return $out;
}
/**
* Get a url from the parts.
*/
function url($hide_password = TRUE) {
return $this->glue_url($this->dest_url, $hide_password);
}
/**
* Glue a URLs component parts back into a URL.
*/
function glue_url($parts, $hide_password = TRUE) {
// Obscure the password if we need to.
$parts['pass'] = $hide_password ? "" : $parts['pass'];
// Assemble the URL.
$out = "";
$out .= $parts['scheme'] .'://';
$out .= $parts['user'] ? urlencode($parts['user']) : '';
$out .= ($parts['user'] && $parts['pass']) ? ":". urlencode($parts['pass']) : '';
$out .= ($parts['user'] || $parts['pass']) ? "@" : "";
$out .= $parts['host'];
$out .= !empty($parts['port']) ? ':'. $parts['port'] : '';
$out .= "/". $parts['path'];
return $out;
}
/**
* Break a URL into it's component parts.
*/
function set_url($url) {
$parts = (array)parse_url($url);
$parts['user'] = urldecode(@$parts['user']);
$parts['pass'] = urldecode(@$parts['pass']);
$parts['path'] = urldecode(@$parts['path']);
$parts['path'] = ltrim(@$parts['path'], "/");
$this->dest_url = $parts;
}
/**
* Retrieve a list of filetypes supported by this source/destination.
*/
function file_types() {
return array();
}
}
/**
* A base class for creating locations.
*/
class backup_migrate_location_remote extends backup_migrate_location {
/**
* The location is a URI so parse it and store the parts.
*/
function get_location() {
return $this->url(FALSE);
}
/**
* The location to display is the url without the password.
*/
function get_display_location() {
return $this->url(TRUE);
}
/**
* Return the location with the password.
*/
function set_location($location) {
$this->location = $location;
$this->set_url($location);
}
/**
* Get a url from the parts.
*/
function url($hide_password = TRUE) {
return $this->glue_url($this->dest_url, $hide_password);
}
/**
* Glue a URLs component parts back into a URL.
*/
function glue_url($parts, $hide_password = TRUE) {
// Obscure the password if we need to.
$parts['pass'] = $hide_password ? "" : $parts['pass'];
// Assemble the URL.
$out = "";
$out .= $parts['scheme'] .'://';
$out .= $parts['user'] ? urlencode($parts['user']) : '';
$out .= ($parts['user'] && $parts['pass']) ? ":". urlencode($parts['pass']) : '';
$out .= ($parts['user'] || $parts['pass']) ? "@" : "";
$out .= $parts['host'];
$out .= !empty($parts['port']) ? ':'. $parts['port'] : '';
$out .= "/". $parts['path'];
return $out;
}
/**
* Break a URL into it's component parts.
*/
function set_url($url) {
$parts = (array)parse_url($url);
$parts['user'] = urldecode(@$parts['user']);
$parts['pass'] = urldecode(@$parts['pass']);
$parts['path'] = urldecode(@$parts['path']);
$parts['path'] = ltrim(@$parts['path'], "/");
$this->dest_url = $parts;
}
/**
* location configuration callback.
*/
function edit_form() {
$form = parent::edit_form();
$form['scheme'] = array(
"#type" => "select",
"#title" => t("Scheme"),
"#default_value" => @$this->dest_url['scheme'] ? $this->dest_url['scheme'] : 'mysql',
"#required" => TRUE,
"#options" => array($GLOBALS['db_type'] => $GLOBALS['db_type']),
"#weight" => 0,
);
$form['host'] = array(
"#type" => "textfield",
"#title" => t("Host"),
"#default_value" => @$this->dest_url['host'] ? $this->dest_url['host'] : 'localhost',
"#required" => TRUE,
"#weight" => 10,
);
$form['path'] = array(
"#type" => "textfield",
"#title" => t("Path"),
"#default_value" => @$this->dest_url['path'],
"#required" => TRUE,
"#weight" => 20,
);
$form['user'] = array(
"#type" => "textfield",
"#title" => t("Username"),
"#default_value" => @$this->dest_url['user'],
"#required" => TRUE,
"#weight" => 30,
);
$form['pass'] = array(
"#type" => "password",
"#title" => t("Password"),
"#default_value" => @$this->dest_url['pass'],
'#description' => '',
"#weight" => 40,
);
if (@$this->dest_url['pass']) {
$form['old_password'] = array(
"#type" => "value",
"#value" => @$this->dest_url['pass'],
);
$form['pass']["#description"] .= t(' You do not need to enter a password unless you wish to change the currently saved password.');
}
return $form;
}
/**
* Submit the configuration form. Glue the url together and add the old password back if a new one was not specified.
*/
function edit_form_submit($form, &$form_state) {
$form_state['values']['pass'] = $form_state['values']['pass'] ? $form_state['values']['pass'] : $form_state['values']['old_password'];
$form_state['values']['location'] = $this->glue_url($form_state['values'], FALSE);
parent::edit_form_submit($form, $form_state);
}
}