Issue #1431634 by Tor Arne Thune: API docs cleanup for update module

merge-requests/26/head
Jennifer Hodgdon 2012-06-15 12:51:09 -07:00
parent 7cf1e7711c
commit e3c2e01e10
13 changed files with 585 additions and 414 deletions

View File

@ -1,5 +1,10 @@
<?php
/**
* @file
* Module for testing Update Manager functionality.
*/
/**
* Implements hook_system_theme_info().
*/
@ -34,13 +39,13 @@ function update_test_menu() {
/**
* Implements hook_system_info_alter().
*
* This checks the 'update_test_system_info' variable and sees if we need to
* alter the system info for the given $file based on the setting. The setting
* is expected to be a nested associative array. If the key '#all' is defined,
* its subarray will include .info keys and values for all modules and themes
* on the system. Otherwise, the settings array is keyed by the module or
* theme short name ($file->name) and the subarrays contain settings just for
* that module or theme.
* Checks the 'update_test_system_info' variable and sees if we need to alter
* the system info for the given $file based on the setting. The setting is
* expected to be a nested associative array. If the key '#all' is defined, its
* subarray will include .info keys and values for all modules and themes on the
* system. Otherwise, the settings array is keyed by the module or theme short
* name ($file->name) and the subarrays contain settings just for that module or
* theme.
*/
function update_test_system_info_alter(&$info, $file) {
$setting = variable_get('update_test_system_info', array());
@ -56,13 +61,12 @@ function update_test_system_info_alter(&$info, $file) {
/**
* Implements hook_update_status_alter().
*
* This checks the 'update_test_update_status' variable and sees if we need to
* alter the update status for the given project based on the setting. The
* setting is expected to be a nested associative array. If the key '#all' is
* defined, its subarray will include .info keys and values for all modules
* and themes on the system. Otherwise, the settings array is keyed by the
* module or theme short name and the subarrays contain settings just for that
* module or theme.
* Checks the 'update_test_update_status' variable and sees if we need to alter
* the update status for the given project based on the setting. The setting is
* expected to be a nested associative array. If the key '#all' is defined, its
* subarray will include .info keys and values for all modules and themes on the
* system. Otherwise, the settings array is keyed by the module or theme short
* name and the subarrays contain settings just for that module or theme.
*/
function update_test_update_status_alter(&$projects) {
$setting = variable_get('update_test_update_status', array());
@ -80,18 +84,20 @@ function update_test_update_status_alter(&$projects) {
}
/**
* Page callback, prints mock XML for the update module.
* Page callback: Prints mock XML for the Update Manager module.
*
* The specific XML file to print depends on two things: the project we're
* trying to fetch data for, and the desired "availability scenario" for that
* project which we're trying to test. Before attempting to fetch this data
* (by checking for updates on the available updates report), callers need to
* define the 'update_test_xml_map' variable as an array, keyed by project
* name, indicating which availability scenario to use for that project.
* project which we're trying to test. Before attempting to fetch this data (by
* checking for updates on the available updates report), callers need to define
* the 'update_test_xml_map' variable as an array, keyed by project name,
* indicating which availability scenario to use for that project.
*
* @param $project_name
* The project short name update.module is trying to fetch data for (the
* The project short name the update manager is trying to fetch data for (the
* fetch URLs are of the form: [base_url]/[project_name]/[core_version]).
*
* @see update_test_menu()
*/
function update_test_mock_page($project_name) {
$xml_map = variable_get('update_test_xml_map', FALSE);
@ -115,7 +121,7 @@ function update_test_mock_page($project_name) {
}
/**
* Implement hook_archiver_info().
* Implements hook_archiver_info().
*/
function update_test_archiver_info() {
return array(
@ -147,13 +153,23 @@ function update_test_filetransfer_info() {
}
/**
* Mock FileTransfer object to test the settings form functionality.
* Mocks a FileTransfer object to test the settings form functionality.
*/
class UpdateTestFileTransfer {
/**
* Returns an UpdateTestFileTransfer object.
*
* @return
* A new UpdateTestFileTransfer object.
*/
public static function factory() {
return new UpdateTestFileTransfer;
}
/**
* Returns a settings form with a text field to input a username.
*/
public function getSettingsForm() {
$form = array();
$form['udpate_test_username'] = array(
@ -165,7 +181,9 @@ class UpdateTestFileTransfer {
}
/**
* Return an Error 503 (Service unavailable) page.
* Page callback: Displays an Error 503 (Service unavailable) page.
*
* @see update_test_menu()
*/
function update_callback_service_unavailable() {
drupal_add_http_header('Status', '503 Service unavailable');

View File

@ -1,3 +1,7 @@
/**
* @file
* RTL styles used by the Update Manager module.
*/
.update .project {
padding-right: .25em;

View File

@ -2,7 +2,7 @@
/**
* @file
* Hooks provided by the Update Status module.
* Hooks provided by the Update Manager module.
*/
/**
@ -14,23 +14,22 @@
* Alter the list of projects before fetching data and comparing versions.
*
* Most modules will never need to implement this hook. It is for advanced
* interaction with the update status module: mere mortals need not apply.
* The primary use-case for this hook is to add projects to the list, for
* example, to provide update status data on disabled modules and themes. A
* contributed module might want to hide projects from the list, for example,
* if there is a site-specific module that doesn't have any official releases,
* that module could remove itself from this list to avoid "No available
* releases found" warnings on the available updates report. In rare cases, a
* module might want to alter the data associated with a project already in
* the list.
* interaction with the Update Manager module. The primary use-case for this
* hook is to add projects to the list; for example, to provide update status
* data on disabled modules and themes. A contributed module might want to hide
* projects from the list; for example, if there is a site-specific module that
* doesn't have any official releases, that module could remove itself from this
* list to avoid "No available releases found" warnings on the available updates
* report. In rare cases, a module might want to alter the data associated with
* a project already in the list.
*
* @param $projects
* Reference to an array of the projects installed on the system. This
* includes all the metadata documented in the comments below for each
* project (either module or theme) that is currently enabled. The array is
* initially populated inside update_get_projects() with the help of
* _update_process_info_list(), so look there for examples of how to
* populate the array with real values.
* includes all the metadata documented in the comments below for each project
* (either module or theme) that is currently enabled. The array is initially
* populated inside update_get_projects() with the help of
* _update_process_info_list(), so look there for examples of how to populate
* the array with real values.
*
* @see update_get_projects()
* @see _update_process_info_list()
@ -118,6 +117,7 @@ function hook_update_status_alter(&$projects) {
* no problems, return an empty array.
*
* @see update_manager_archive_verify()
* @ingroup update_manager_file
*/
function hook_verify_update_archive($project, $archive_file, $directory) {
$errors = array();

View File

@ -2,15 +2,19 @@
/**
* @file
* Callbacks and related functions invoked by authorize.php to update projects
* on the Drupal site. We use the Batch API to actually update each individual
* project on the site. All of the code in this file is run at a low bootstrap
* level (modules are not loaded), so these functions cannot assume access to
* the rest of the update module code.
* Callbacks and related functions invoked by authorize.php to update projects.
*
* We use the Batch API to actually update each individual project on the site.
* All of the code in this file is run at a low bootstrap level (modules are not
* loaded), so these functions cannot assume access to the rest of the code of
* the Update Manager module.
*/
/**
* Callback invoked by authorize.php to update existing projects.
* Updates existing projects when invoked by authorize.php.
*
* Callback for system_authorized_init() in
* update_manager_update_ready_form_submit().
*
* @param $filetransfer
* The FileTransfer object created by authorize.php for use during this
@ -18,9 +22,9 @@
* @param $projects
* A nested array of projects to install into the live webroot, keyed by
* project name. Each subarray contains the following keys:
* - 'project': The canonical project short name.
* - 'updater_name': The name of the Updater class to use for this project.
* - 'local_url': The locally installed location of new code to update with.
* - project: The canonical project short name.
* - updater_name: The name of the Updater class to use for this project.
* - local_url: The locally installed location of new code to update with.
*/
function update_authorize_run_update($filetransfer, $projects) {
$operations = array();
@ -50,13 +54,16 @@ function update_authorize_run_update($filetransfer, $projects) {
}
/**
* Callback invoked by authorize.php to install a new project.
* Installs a new project when invoked by authorize.php.
*
* Callback for system_authorized_init() in
* update_manager_install_form_submit().
*
* @param FileTransfer $filetransfer
* The FileTransfer object created by authorize.php for use during this
* operation.
* @param string $project
* The canonical project short name (e.g. {system}.name).
* The canonical project short name (e.g., {system}.name).
* @param string $updater_name
* The name of the Updater class to use for installing this project.
* @param string $local_url
@ -90,7 +97,7 @@ function update_authorize_run_install($filetransfer, $project, $updater_name, $l
}
/**
* Copy a project to its proper place when authorized with elevated privileges.
* Batch callback: Copies project to its proper place when authorized to do so.
*
* @param string $project
* The canonical short name of the project being installed.
@ -102,7 +109,7 @@ function update_authorize_run_install($filetransfer, $project, $updater_name, $l
* @param FileTransfer $filetransfer
* The FileTransfer object to use for performing this operation.
* @param array $context
* Reference to an array used for BatchAPI storage.
* Reference to an array used for Batch API storage.
*/
function update_authorize_batch_copy_project($project, $updater_name, $local_url, $filetransfer, &$context) {
@ -118,15 +125,13 @@ function update_authorize_batch_copy_project($project, $updater_name, $local_url
$context['results']['tasks'] = array();
}
/**
* The batch API uses a session, and since all the arguments are serialized
* and unserialized between requests, although the FileTransfer object
* itself will be reconstructed, the connection pointer itself will be lost.
* However, the FileTransfer object will still have the connection variable,
* even though the connection itself is now gone. So, although it's ugly, we
* have to unset the connection variable at this point so that the
* FileTransfer object will re-initiate the actual connection.
*/
// The batch API uses a session, and since all the arguments are serialized
// and unserialized between requests, although the FileTransfer object itself
// will be reconstructed, the connection pointer itself will be lost. However,
// the FileTransfer object will still have the connection variable, even
// though the connection itself is now gone. So, although it's ugly, we have
// to unset the connection variable at this point so that the FileTransfer
// object will re-initiate the actual connection.
unset($filetransfer->connection);
if (!empty($context['results']['log'][$project]['#abort'])) {
@ -163,11 +168,16 @@ function update_authorize_batch_copy_project($project, $updater_name, $local_url
}
/**
* Batch callback for when the authorized update batch is finished.
* Batch callback: Performs actions when the authorized update batch is done.
*
* This processes the results and stashes them into SESSION such that
* authorize.php will render a report. Also responsible for putting the site
* back online and clearing the update status cache after a successful update.
*
* @param $success
* TRUE if the batch operation was successful; FALSE if there were errors.
* @param $results
* An associative array of results from the batch operation.
*/
function update_authorize_update_batch_finished($success, $results) {
foreach ($results['log'] as $project => $messages) {
@ -225,11 +235,16 @@ function update_authorize_update_batch_finished($success, $results) {
}
/**
* Batch callback for when the authorized install batch is finished.
* Batch callback: Performs actions when the authorized install batch is done.
*
* This processes the results and stashes them into SESSION such that
* authorize.php will render a report. Also responsible for putting the site
* back online after a successful install if necessary.
*
* @param $success
* TRUE if the batch operation was a success; FALSE if there were errors.
* @param $results
* An associative array of results from the batch operation.
*/
function update_authorize_install_batch_finished($success, $results) {
foreach ($results['log'] as $project => $messages) {
@ -279,26 +294,30 @@ function update_authorize_install_batch_finished($success, $results) {
}
/**
* Helper function to create a structure of log messages.
* Creates a structure of log messages.
*
* @param array $project_results
* An associative array of results from the batch operation.
* @param string $message
* A string containing a log message.
* @param bool $success
* (optional) TRUE if the operation the message is about was a success, FALSE
* if there were errors. Defaults to TRUE.
*/
function _update_batch_create_message(&$project_results, $message, $success = TRUE) {
$project_results[] = array('message' => $message, 'success' => $success);
}
/**
* Private helper function to clear cached available update status data.
* Clears cached available update status data.
*
* Since this function is run at such a low bootstrap level, update.module is
* not loaded. So, we can't just call _update_cache_clear(). However, the
* database is bootstrapped, so we can do a query ourselves to clear out what
* we want to clear.
* Since this function is run at such a low bootstrap level, the Update Manager
* module is not loaded. So, we can't just call _update_cache_clear(). However,
* the database is bootstrapped, so we can do a query ourselves to clear out
* what we want to clear.
*
* Note that we do not want to just truncate the table, since that would
* remove items related to currently pending fetch attempts.
* Note that we do not want to just truncate the table, since that would remove
* items related to currently pending fetch attempts.
*
* @see update_authorize_update_batch_finished()
* @see _update_cache_clear()

View File

@ -6,7 +6,7 @@
*/
/**
* Fetch an array of installed and enabled projects.
* Fetches an array of installed and enabled projects.
*
* This is only responsible for generating an array of projects (taking into
* account projects that include more than one module or theme). Other
@ -15,14 +15,39 @@
* that logic is only required when preparing the status report, not for
* fetching the available release data.
*
* This array is fairly expensive to construct, since it involves a lot of
* disk I/O, so we cache the results into the {cache_update} table using the
* 'update_project_projects' cache ID. However, since this is not the data
* about available updates fetched from the network, it is ok to invalidate it
* somewhat quickly. If we keep this data for very long, site administrators
* are more likely to see incorrect results if they upgrade to a newer version
* of a module or theme but do not visit certain pages that automatically
* clear this cache.
* This array is fairly expensive to construct, since it involves a lot of disk
* I/O, so we cache the results into the {cache_update} table using the
* 'update_project_projects' cache ID. However, since this is not the data about
* available updates fetched from the network, it is acceptable to invalidate it
* somewhat quickly. If we keep this data for very long, site administrators are
* more likely to see incorrect results if they upgrade to a newer version of a
* module or theme but do not visit certain pages that automatically clear this
* cache.
*
* @return
* An associative array of currently enabled projects keyed by the
* machine-readable project short name. Each project contains:
* - name: The machine-readable project short name.
* - info: An array with values from the main .info file for this project.
* - name: The human-readable name of the project.
* - package: The package that the project is grouped under.
* - version: The version of the project.
* - project: The Drupal.org project name.
* - datestamp: The date stamp of the project's main .info file.
* - _info_file_ctime: The maximum file change time for all of the .info
* files included in this project.
* - datestamp: The date stamp when the project was released, if known.
* - includes: An associative array containing all projects included with this
* project, keyed by the machine-readable short name with the human-readable
* name as value.
* - project_type: The type of project. Allowed values are 'module' and
* 'theme'.
* - project_status: This indicates if the project is enabled and will always
* be TRUE, as the function only returns enabled projects.
* - sub_themes: If the project is a theme it contains an associative array of
* all sub-themes.
* - base_themes: If the project is a theme it contains an associative array
* of all base-themes.
*
* @see update_process_project_info()
* @see update_calculate_project_data()
@ -53,25 +78,25 @@ function update_get_projects() {
}
/**
* Populate an array of project data.
* Populates an array of project data.
*
* This iterates over a list of the installed modules or themes and groups
* them by project and status. A few parts of this function assume that
* enabled modules and themes are always processed first, and if disabled
* modules or themes are being processed (there is a setting to control if
* disabled code should be included in the Available updates report or not),
* those are only processed after $projects has been populated with
* information about the enabled code. 'Hidden' modules and themes are always
* ignored. This function also records the latest change time on the .info
* files for each module or theme, which is important data which is used when
* deciding if the cached available update data should be invalidated.
* This iterates over a list of the installed modules or themes and groups them
* by project and status. A few parts of this function assume that enabled
* modules and themes are always processed first, and if disabled modules or
* themes are being processed (there is a setting to control if disabled code
* should be included or not in the 'Available updates' report), those are only
* processed after $projects has been populated with information about the
* enabled code. Modules and themes set as hidden are always ignored. This
* function also records the latest change time on the .info files for each
* module or theme, which is important data which is used when deciding if the
* cached available update data should be invalidated.
*
* @param $projects
* Reference to the array of project data of what's installed on this site.
* @param $list
* Array of data to process to add the relevant info to the $projects array.
* @param $project_type
* The kind of data in the list (can be 'module' or 'theme').
* The kind of data in the list. Can be 'module' or 'theme'.
* @param $status
* Boolean that controls what status (enabled or disabled) to process out of
* the $list and add to the $projects array.
@ -211,8 +236,13 @@ function _update_process_info_list(&$projects, $list, $project_type, $status) {
}
/**
* Given a $file object (as returned by system_get_files_database()), figure
* out what project it belongs to.
* Determines what project a given file object belongs to.
*
* @param $file
* A file object as returned by system_get_files_database().
*
* @return
* The canonical project short name.
*
* @see system_get_files_database()
*/
@ -228,7 +258,9 @@ function update_get_project_name($file) {
}
/**
* Process the list of projects on the system to figure out the currently
* Determines version and type information for currently installed projects.
*
* Processes the list of projects on the system to figure out the currently
* installed versions, and other information that is required before we can
* compare against the available releases to produce the status report.
*
@ -277,7 +309,7 @@ function update_process_project_info(&$projects) {
}
/**
* Calculate the current update status of all projects on the site.
* Calculates the current update status of all projects on the site.
*
* The results of this function are expensive to compute, especially on sites
* with lots of modules or themes, since it involves a lot of comparisons and
@ -285,13 +317,16 @@ function update_process_project_info(&$projects) {
* table using the 'update_project_data' cache ID. However, since this is not
* the data about available updates fetched from the network, it is ok to
* invalidate it somewhat quickly. If we keep this data for very long, site
* administrators are more likely to see incorrect results if they upgrade to
* a newer version of a module or theme but do not visit certain pages that
* administrators are more likely to see incorrect results if they upgrade to a
* newer version of a module or theme but do not visit certain pages that
* automatically clear this cache.
*
* @param array $available
* Data about available project releases.
*
* @return
* An array of installed projects with current update status information.
*
* @see update_get_available()
* @see update_get_projects()
* @see update_process_project_info()
@ -327,52 +362,50 @@ function update_calculate_project_data($available) {
}
/**
* Calculate the current update status of a specific project.
* Calculates the current update status of a specific project.
*
* This function is the heart of the update status feature. For each project
* it is invoked with, it first checks if the project has been flagged with a
* This function is the heart of the update status feature. For each project it
* is invoked with, it first checks if the project has been flagged with a
* special status like "unsupported" or "insecure", or if the project node
* itself has been unpublished. In any of those cases, the project is marked
* with an error and the next project is considered.
*
* If the project itself is valid, the function decides what major release
* series to consider. The project defines what the currently supported major
* versions are for each version of core, so the first step is to make sure
* the current version is still supported. If so, that's the target version.
* If the current version is unsupported, the project maintainer's recommended
* major version is used. There's also a check to make sure that this function
* never recommends an earlier release than the currently installed major
* version.
* versions are for each version of core, so the first step is to make sure the
* current version is still supported. If so, that's the target version. If the
* current version is unsupported, the project maintainer's recommended major
* version is used. There's also a check to make sure that this function never
* recommends an earlier release than the currently installed major version.
*
* Given a target major version, it scans the available releases looking for
* Given a target major version, the available releases are scanned looking for
* the specific release to recommend (avoiding beta releases and development
* snapshots if possible). This is complicated to describe, but an example
* will help clarify. For the target major version, find the highest patch
* level. If there is a release at that patch level with no extra ("beta",
* etc), then we recommend the release at that patch level with the most
* recent release date. If every release at that patch level has extra (only
* betas), then recommend the latest release from the previous patch
* level. For example:
* snapshots if possible). For the target major version, the highest patch level
* is found. If there is a release at that patch level with no extra ("beta",
* etc.), then the release at that patch level with the most recent release date
* is recommended. If every release at that patch level has extra (only betas),
* then the latest release from the previous patch level is recommended. For
* example:
*
* 1.6-bugfix <-- recommended version because 1.6 already exists.
* 1.6
* - 1.6-bugfix <-- recommended version because 1.6 already exists.
* - 1.6
*
* or
*
* 1.6-beta
* 1.5 <-- recommended version because no 1.6 exists.
* 1.4
* - 1.6-beta
* - 1.5 <-- recommended version because no 1.6 exists.
* - 1.4
*
* It also looks for the latest release from the same major version, even a
* beta release, to display to the user as the "Latest version" option.
* Additionally, it finds the latest official release from any higher major
* versions that have been released to provide a set of "Also available"
* Also, the latest release from the same major version is looked for, even beta
* releases, to display to the user as the "Latest version" option.
* Additionally, the latest official release from any higher major versions that
* have been released is searched for to provide a set of "Also available"
* options.
*
* Finally, and most importantly, it keeps scanning the release history until
* it gets to the currently installed release, searching for anything marked
* as a security update. If any security updates have been found between the
* recommended release and the installed version, all of the releases that
* Finally, and most importantly, the release history continues to be scanned
* until the currently installed release is reached, searching for anything
* marked as a security update. If any security updates have been found between
* the recommended release and the installed version, all of the releases that
* included a security fix are recorded so that the site administrator can be
* warned their site is insecure, and links pointing to the release notes for
* each security update can be included (which, in turn, will link to the
@ -381,9 +414,15 @@ function update_calculate_project_data($available) {
* This function relies on the fact that the .xml release history data comes
* sorted based on major version and patch level, then finally by release date
* if there are multiple releases such as betas from the same major.patch
* version (e.g. 5.x-1.5-beta1, 5.x-1.5-beta2, and 5.x-1.5). Development
* version (e.g., 5.x-1.5-beta1, 5.x-1.5-beta2, and 5.x-1.5). Development
* snapshots for a given major version are always listed last.
*
* @param $project
* An array containing information about a specific project.
* @param $project_data
* An array containing information about a specific project.
* @param $available
* Data about available project releases of a specific project.
*/
function update_calculate_project_update_status($project, &$project_data, $available) {
foreach (array('title', 'link') as $attribute) {
@ -707,16 +746,16 @@ function update_calculate_project_update_status($project, &$project_data, $avail
}
/**
* Retrieve data from {cache_update} or empty the cache when necessary.
* Retrieves data from {cache_update} or empties the cache when necessary.
*
* Two very expensive arrays computed by this module are the list of all
* installed modules and themes (and .info data, project associations, etc),
* and the current status of the site relative to the currently available
* releases. These two arrays are cached in the {cache_update} table and used
* whenever possible. The cache is cleared whenever the administrator visits
* the status report, available updates report, or the module or theme
* administration pages, since we should always recompute the most current
* values on any of those pages.
* installed modules and themes (and .info data, project associations, etc), and
* the current status of the site relative to the currently available releases.
* These two arrays are cached in the {cache_update} table and used whenever
* possible. The cache is cleared whenever the administrator visits the status
* report, available updates report, or the module or theme administration
* pages, since we should always recompute the most current values on any of
* those pages.
*
* Note: while both of these arrays are expensive to compute (in terms of disk
* I/O and some fairly heavy CPU processing), neither of these is the actual
@ -726,13 +765,13 @@ function update_calculate_project_update_status($project, &$project_data, $avail
* hour and never get invalidated just by visiting a page on the site.
*
* @param $cid
* The cache id of data to return from the cache. Valid options are
* The cache ID of data to return from the cache. Valid options are
* 'update_project_data' and 'update_project_projects'.
*
* @return
* The cached value of the $projects array generated by
* update_calculate_project_data() or update_get_projects(), or an empty
* array when the cache is cleared.
* update_calculate_project_data() or update_get_projects(), or an empty array
* when the cache is cleared.
*/
function update_project_cache($cid) {
$projects = array();
@ -764,13 +803,13 @@ function update_project_cache($cid) {
}
/**
* Filter the project .info data to only save attributes we need.
* Filters the project .info data to only save attributes we need.
*
* @param array $info
* Array of .info file data as returned by drupal_parse_info_file().
*
* @return
* Array of .info file data we need for the Update manager.
* Array of .info file data we need for the update manager.
*
* @see _update_process_info_list()
*/

View File

@ -1,3 +1,7 @@
/**
* @file
* Styles used by the Update Manager module.
*/
.update .project {
font-weight: bold;

View File

@ -6,7 +6,11 @@
*/
/**
* Callback to manually check the update status without cron.
* Page callback: Checks for updates and displays the update status report.
*
* Manually checks the update status without the use of cron.
*
* @see update_menu()
*/
function update_manual_status() {
_update_refresh();
@ -25,7 +29,10 @@ function update_manual_status() {
}
/**
* Process a step in the batch for fetching available update data.
* Batch callback: Processes a step in batch for fetching available update data.
*
* @param $context
* Reference to an array used for Batch API storage.
*/
function update_fetch_data_batch(&$context) {
$queue = DrupalQueue::get('update_fetch_tasks');
@ -70,12 +77,12 @@ function update_fetch_data_batch(&$context) {
}
/**
* Batch API callback when all fetch tasks have been completed.
* Batch callback: Performs actions when all fetch tasks have been completed.
*
* @param $success
* Boolean indicating the success of the batch.
* TRUE if the batch operation was successful; FALSE if there were errors.
* @param $results
* Associative array holding the results of the batch, including the key
* An associative array of results from the batch operation, including the key
* 'updated' which holds the total number of projects we fetched available
* update data for.
*/
@ -96,7 +103,7 @@ function update_fetch_data_finished($success, $results) {
}
/**
* Attempt to drain the queue of tasks for release history data to fetch.
* Attempts to drain the queue of tasks for release history data to fetch.
*/
function _update_fetch_data() {
$queue = DrupalQueue::get('update_fetch_tasks');
@ -108,13 +115,14 @@ function _update_fetch_data() {
}
/**
* Process a task to fetch available update data for a single project.
* Processes a task to fetch available update data for a single project.
*
* Once the release history XML data is downloaded, it is parsed and saved
* into the {cache_update} table in an entry just for that project.
* Once the release history XML data is downloaded, it is parsed and saved into
* the {cache_update} table in an entry just for that project.
*
* @param $project
* Associative array of information about the project to fetch data for.
*
* @return
* TRUE if we fetched parsable XML, otherwise FALSE.
*/
@ -184,7 +192,7 @@ function _update_process_fetch_task($project) {
}
/**
* Clear out all the cached available update data and initiate re-fetching.
* Clears out all the cached available update data and initiates re-fetching.
*/
function _update_refresh() {
module_load_include('inc', 'update', 'update.compare');
@ -211,7 +219,7 @@ function _update_refresh() {
}
/**
* Add a task to the queue for fetching release history data for a project.
* Adds a task to the queue for fetching release history data for a project.
*
* We only create a new fetch task if there's no task already in the queue for
* this particular project (based on 'fetch_task::' entries in the
@ -219,8 +227,8 @@ function _update_refresh() {
*
* @param $project
* Associative array of information about a project as created by
* update_get_projects(), including keys such as 'name' (short name),
* and the 'info' array with data from a .info file for the project.
* update_get_projects(), including keys such as 'name' (short name), and the
* 'info' array with data from a .info file for the project.
*
* @see update_get_projects()
* @see update_get_available()
@ -260,14 +268,17 @@ function _update_create_fetch_task($project) {
/**
* Generates the URL to fetch information about project updates.
*
* This figures out the right URL to use, based on the project's .info file
* and the global defaults. Appends optional query arguments when the site is
* This figures out the right URL to use, based on the project's .info file and
* the global defaults. Appends optional query arguments when the site is
* configured to report usage stats.
*
* @param $project
* The array of project information from update_get_projects().
* @param $site_key
* The anonymous site key hash (optional).
* (optional) The anonymous site key hash. Defaults to an empty string.
*
* @return
* The URL for fetching information about updates to the specified project.
*
* @see update_fetch_data()
* @see _update_process_fetch_task()
@ -293,10 +304,11 @@ function _update_build_fetch_url($project, $site_key = '') {
}
/**
* Return the base of the URL to fetch available update data for a project.
* Returns the base of the URL to fetch available update data for a project.
*
* @param $project
* The array of project information from update_get_projects().
*
* @return
* The base of the URL used for fetching available update data. This does
* not include the path elements to specify a particular project, version,
@ -309,10 +321,10 @@ function _update_get_fetch_url_base($project) {
}
/**
* Perform any notifications that should be done once cron fetches new data.
* Performs any notifications that should be done once cron fetches new data.
*
* This method checks the status of the site using the new data and depending
* on the configuration of the site, notifies administrators via email if there
* This method checks the status of the site using the new data and, depending
* on the configuration of the site, notifies administrators via e-mail if there
* are new releases or missing security updates.
*
* @see update_requirements()
@ -347,7 +359,7 @@ function _update_cron_notify() {
}
/**
* Parse the XML of the Drupal release history info files.
* Parses the XML of the Drupal release history info files.
*
* @param $raw_xml
* A raw XML string of available release data for a given project.

View File

@ -2,26 +2,25 @@
/**
* @file
* Install, update and uninstall functions for the update module.
* Install, update, and uninstall functions for the Update Manager module.
*/
/**
* Implements hook_requirements().
*
* @return
* An array describing the status of the site regarding available updates.
* If there is no update data, only one record will be returned, indicating
* that the status of core can't be determined. If data is available, there
* will be two records: one for core, and another for all of contrib
* (assuming there are any contributed modules or themes enabled on the
* site). In addition to the fields expected by hook_requirements ('value',
* 'severity', and optionally 'description'), this array will contain a
* 'reason' attribute, which is an integer constant to indicate why the
* given status is being returned (UPDATE_NOT_SECURE, UPDATE_NOT_CURRENT, or
* UPDATE_UNKNOWN). This is used for generating the appropriate e-mail
* notification messages during update_cron(), and might be useful for other
* modules that invoke update_requirements() to find out if the site is up
* to date or not.
* An array describing the status of the site regarding available updates. If
* there is no update data, only one record will be returned, indicating that
* the status of core can't be determined. If data is available, there will be
* two records: one for core, and another for all of contrib (assuming there
* are any contributed modules or themes enabled on the site). In addition to
* the fields expected by hook_requirements ('value', 'severity', and
* optionally 'description'), this array will contain a 'reason' attribute,
* which is an integer constant to indicate why the given status is being
* returned (UPDATE_NOT_SECURE, UPDATE_NOT_CURRENT, or UPDATE_UNKNOWN). This
* is used for generating the appropriate e-mail notification messages during
* update_cron(), and might be useful for other modules that invoke
* update_requirements() to find out if the site is up to date or not.
*
* @see _update_message_text()
* @see _update_cron_notify()
@ -96,19 +95,19 @@ function update_uninstall() {
}
/**
* Private helper method to fill in the requirements array.
* Fills in the requirements array.
*
* This is shared for both core and contrib to generate the right elements in
* the array for hook_requirements().
*
* @param $project
* Array of information about the project we're testing as returned by
* update_calculate_project_data().
* Array of information about the project we're testing as returned by
* update_calculate_project_data().
* @param $type
* What kind of project is this ('core' or 'contrib').
* What kind of project this is ('core' or 'contrib').
*
* @return
* An array to be included in the nested $requirements array.
* An array to be included in the nested $requirements array.
*
* @see hook_requirements()
* @see update_requirements()

View File

@ -2,7 +2,8 @@
/**
* @file
* Administrative screens and processing functions for the update manager.
* Administrative screens and processing functions of the Update Manager module.
*
* This allows site administrators with the 'administer software updates'
* permission to either upgrade existing projects, or download and install new
* ones, so long as the killswitch setting ('allow_authorize_operations') is
@ -11,51 +12,52 @@
* To install new code, the administrator is prompted for either the URL of an
* archive file, or to directly upload the archive file. The archive is loaded
* into a temporary location, extracted, and verified. If everything is
* successful, the user is redirected to authorize.php to type in their file
* transfer credentials and authorize the installation to proceed with
* elevated privileges, such that the extracted files can be copied out of the
* temporary location and into the live web root.
* successful, the user is redirected to authorize.php to type in file transfer
* credentials and authorize the installation to proceed with elevated
* privileges, such that the extracted files can be copied out of the temporary
* location and into the live web root.
*
* Updating existing code is a more elaborate process. The first step is a
* selection form where the user is presented with a table of installed
* projects that are missing newer releases. The user selects which projects
* they wish to upgrade, and presses the "Download updates" button to
* continue. This sets up a batch to fetch all the selected releases, and
* redirects to admin/update/download to display the batch progress bar as it
* runs. Each batch operation is responsible for downloading a single file,
* extracting the archive, and verifying the contents. If there are any
* errors, the user is redirected back to the first page with the error
* messages. If all downloads were extacted and verified, the user is instead
* redirected to admin/update/ready, a landing page which reminds them to
* backup their database and asks if they want to put the site offline during
* the upgrade. Once the user presses the "Install updates" button, they are
* redirected to authorize.php to supply their web root file access
* credentials. The authorized operation (which lives in update.authorize.inc)
* sets up a batch to copy each extracted update from the temporary location
* into the live web root.
* selection form where the user is presented with a table of installed projects
* that are missing newer releases. The user selects which projects they wish to
* update, and presses the "Download updates" button to continue. This sets up a
* batch to fetch all the selected releases, and redirects to
* admin/update/download to display the batch progress bar as it runs. Each
* batch operation is responsible for downloading a single file, extracting the
* archive, and verifying the contents. If there are any errors, the user is
* redirected back to the first page with the error messages. If all downloads
* were extacted and verified, the user is instead redirected to
* admin/update/ready, a landing page which reminds them to backup their
* database and asks if they want to put the site offline during the update.
* Once the user presses the "Install updates" button, they are redirected to
* authorize.php to supply their web root file access credentials. The
* authorized operation (which lives in update.authorize.inc) sets up a batch to
* copy each extracted update from the temporary location into the live web
* root.
*/
/**
* @defgroup update_manager_update Update manager: update
* @defgroup update_manager_update Update Manager module: update
* @{
* Update manager for updating existing code.
* Update Manager module functionality for updating existing code.
*
* Provides a user interface to update existing code.
*/
/**
* Build the form for the update manager page to update existing projects.
* Form constructor for the update form of the Update Manager module.
*
* This presents a table with all projects that have available updates with
* checkboxes to select which ones to upgrade.
*
* @param $form
* @param $form_state
* @param $context
* String representing the context from which we're trying to update, can be:
* 'module', 'theme' or 'report'.
* @return
* The form array for selecting which projects to update.
* String representing the context from which we're trying to update.
* Allowed values are 'module', 'theme', and 'report'.
*
* @see update_manager_update_form_validate()
* @see update_manager_update_form_submit()
* @see update_menu()
* @ingroup forms
*/
function update_manager_update_form($form, $form_state = array(), $context) {
if (!_update_manager_check_backends($form, 'update')) {
@ -263,7 +265,7 @@ function update_manager_update_form($form, $form_state = array(), $context) {
}
/**
* Returns HTML for the first page in the update manager wizard to select projects.
* Returns HTML for the first page in the process of updating projects.
*
* @param $variables
* An associative array containing:
@ -280,7 +282,11 @@ function theme_update_manager_update_form($variables) {
}
/**
* Validation callback to ensure that at least one project is selected.
* Form validation handler for update_manager_update_form().
*
* Ensures that at least one project is selected.
*
* @see update_manager_update_form_submit()
*/
function update_manager_update_form_validate($form, &$form_state) {
if (!empty($form_state['values']['projects'])) {
@ -295,11 +301,11 @@ function update_manager_update_form_validate($form, &$form_state) {
}
/**
* Submit function for the main update form.
* Form submission handler for update_manager_update_form().
*
* This sets up a batch to download, extract and verify the selected releases
* Sets up a batch that downloads, extracts, and verifies the selected releases.
*
* @see update_manager_update_form()
* @see update_manager_update_form_validate()
*/
function update_manager_update_form_submit($form, &$form_state) {
$projects = array();
@ -329,7 +335,12 @@ function update_manager_update_form_submit($form, &$form_state) {
}
/**
* Batch callback invoked when the download batch is completed.
* Batch callback: Performs actions when the download batch is completed.
*
* @param $success
* TRUE if the batch operation was successful, FALSE if there were errors.
* @param $results
* An associative array of results from the batch operation.
*/
function update_manager_download_batch_finished($success, $results) {
if (!empty($results['errors'])) {
@ -352,15 +363,21 @@ function update_manager_download_batch_finished($success, $results) {
}
/**
* Form constructor for the update ready form.
*
* Build the form when the site is ready to update (after downloading).
*
* This form is an intermediary step in the automated update workflow. It is
* presented to the site administrator after all the required updates have
* been downloaded and verified. The point of this page is to encourage the
* user to backup their site, gives them the opportunity to put the site
* offline, and then asks them to confirm that the update should continue.
* After this step, the user is redirected to authorize.php to enter their
* file transfer credentials and attempt to complete the update.
* presented to the site administrator after all the required updates have been
* downloaded and verified. The point of this page is to encourage the user to
* backup their site, give them the opportunity to put the site offline, and
* then ask them to confirm that the update should continue. After this step,
* the user is redirected to authorize.php to enter their file transfer
* credentials and attempt to complete the update.
*
* @see update_manager_update_ready_form_submit()
* @see update_menu()
* @ingroup forms
*/
function update_manager_update_ready_form($form, &$form_state) {
if (!_update_manager_check_backends($form, 'update')) {
@ -389,13 +406,13 @@ function update_manager_update_ready_form($form, &$form_state) {
}
/**
* Submit handler for the form to confirm that an update should continue.
* Form submission handler for update_manager_update_ready_form().
*
* If the site administrator requested that the site is put offline during the
* update, do so now. Otherwise, pull information about all the required
* updates out of the SESSION, figure out what Updater class is needed for
* each one, generate an array of update operations to perform, and hand it
* all off to system_authorized_init(), then redirect to authorize.php.
* update, do so now. Otherwise, pull information about all the required updates
* out of the SESSION, figure out what Drupal\Core\Updater\Updater class is
* needed for each one, generate an array of update operations to perform, and
* hand it all off to system_authorized_init(), then redirect to authorize.php.
*
* @see update_authorize_run_update()
* @see system_authorized_init()
@ -454,26 +471,27 @@ function update_manager_update_ready_form_submit($form, &$form_state) {
*/
/**
* @defgroup update_manager_install Update manager: install
* @defgroup update_manager_install Update Manager module: install
* @{
* Update manager for installing new code.
* Update Manager module functionality for installing new code.
*
* Provides a user interface to install new code.
*/
/**
* Build the form for the update manager page to install new projects.
* Form constructor for the install form of the Update Manager module.
*
* This presents a place to enter a URL or upload an archive file to use to
* install a new module or theme.
*
* @param $form
* @param $form_state
* @param $context
* String representing the context from which we're trying to install, can
* be: 'module', 'theme' or 'report'.
* @return
* The form array for selecting which project to install.
* String representing the context from which we're trying to install.
* Allowed values are 'module', 'theme', and 'report'.
*
* @see update_manager_install_form_validate()
* @see update_manager_install_form_submit()
* @see update_menu()
* @ingroup forms
*/
function update_manager_install_form($form, &$form_state, $context) {
if (!_update_manager_check_backends($form, 'install')) {
@ -524,11 +542,11 @@ function update_manager_install_form($form, &$form_state, $context) {
* @param array $form
* Reference to the form array we're building.
* @param string $operation
* The Update manager operation we're in the middle of. Can be either
* 'update' or 'install'. Use to provide operation-specific interface text.
* The update manager operation we're in the middle of. Can be either 'update'
* or 'install'. Use to provide operation-specific interface text.
*
* @return
* TRUE if the Update manager should continue to the next step in the
* TRUE if the update manager should continue to the next step in the
* workflow, or FALSE if we've hit a fatal configuration and must halt the
* workflow.
*/
@ -586,7 +604,9 @@ function _update_manager_check_backends(&$form, $operation) {
}
/**
* Validate the form for installing a new project via the update manager.
* Form validation handler for update_manager_install_form().
*
* @see update_manager_install_form_submit()
*/
function update_manager_install_form_validate($form, &$form_state) {
if (!($form_state['values']['project_url'] XOR !empty($_FILES['files']['name']['project_upload']))) {
@ -601,7 +621,7 @@ function update_manager_install_form_validate($form, &$form_state) {
}
/**
* Handle form submission when installing new projects via the update manager.
* Form submission handler for update_manager_install_form().
*
* Either downloads the file specified in the URL to a temporary cache, or
* uploads the file attached to the form, then attempts to extract the archive
@ -611,6 +631,7 @@ function update_manager_install_form_validate($form, &$form_state) {
* via authorize.php which will copy the extracted files from the temporary
* location into the live site.
*
* @see update_manager_install_form_validate()
* @see update_authorize_run_install()
* @see system_authorized_init()
* @see system_authorized_get_url()
@ -728,26 +749,26 @@ function update_manager_install_form_submit($form, &$form_state) {
*/
/**
* @defgroup update_manager_file Update manager: file management
* @defgroup update_manager_file Update Manager module: file management
* @{
* Update manager file management functions.
* Update Manager module file management functions.
*
* These functions are used by the update manager to copy, extract
* and verify archive files.
* These functions are used by the update manager to copy, extract, and verify
* archive files.
*/
/**
* Unpack a downloaded archive file.
* Unpacks a downloaded archive file.
*
* @param string $project
* The short name of the project to download.
* @param string $file
* The filename of the archive you wish to extract.
* @param string $directory
* The directory you wish to extract the archive into.
*
* @return Archiver
* The Archiver object used to extract the archive.
* @throws Exception on failure.
*
* @throws Exception
*/
function update_manager_archive_extract($file, $directory) {
$archiver = archiver_get_archiver($file);
@ -775,7 +796,7 @@ function update_manager_archive_extract($file, $directory) {
}
/**
* Verify an archive after it has been downloaded and extracted.
* Verifies an archive after it has been downloaded and extracted.
*
* This function is responsible for invoking hook_verify_update_archive().
*
@ -787,18 +808,17 @@ function update_manager_archive_extract($file, $directory) {
* The directory that the archive was extracted into.
*
* @return array
* An array of error messages to display if the archive was invalid. If
* there are no errors, it will be an empty array.
*
* An array of error messages to display if the archive was invalid. If there
* are no errors, it will be an empty array.
*/
function update_manager_archive_verify($project, $archive_file, $directory) {
return module_invoke_all('verify_update_archive', $project, $archive_file, $directory);
}
/**
* Copies a file from $url to the temporary directory for updates.
* Copies a file from the specified URL to the temporary directory for updates.
*
* If the file has already been downloaded, returns the the local path.
* Returns the local path if the file has already been downloaded.
*
* @param $url
* The URL of the file on the server.
@ -827,18 +847,18 @@ function update_manager_file_get($url) {
}
/**
* Batch operation: download, unpack, and verify a project.
* Batch callback: Downloads, unpacks, and verifies a project.
*
* This function assumes that the provided URL points to a file archive of
* some sort. The URL can have any scheme that we have a file stream wrapper
* to support. The file is downloaded to a local cache.
* This function assumes that the provided URL points to a file archive of some
* sort. The URL can have any scheme that we have a file stream wrapper to
* support. The file is downloaded to a local cache.
*
* @param string $project
* The short name of the project to download.
* @param string $url
* The URL to download a specific project release archive file.
* @param array $context
* Reference to an array used for BatchAPI storage.
* Reference to an array used for Batch API storage.
*
* @see update_manager_download_page()
*/
@ -887,8 +907,8 @@ function update_manager_batch_project_get($project, $url, &$context) {
* Determines if file transfers will be performed locally.
*
* If the server is configured such that webserver-created files have the same
* owner as the configuration directory (e.g. sites/default) where new code
* will eventually be installed, the Update manager can transfer files entirely
* owner as the configuration directory (e.g., sites/default) where new code
* will eventually be installed, the update manager can transfer files entirely
* locally, without changing their ownership (in other words, without prompting
* the user for FTP, SSH or other credentials).
*

View File

@ -2,10 +2,13 @@
/**
* @file
* The "Update status" module checks for available updates of Drupal core and
* any installed contributed modules and themes. It warns site administrators
* if newer releases are available via the system status report
* (admin/reports/status), the module and theme pages, and optionally via email.
* Handles updates of Drupal core and contributed projects.
*
* The module checks for available updates of Drupal core and any installed
* contributed modules and themes. It warns site administrators if newer
* releases are available via the system status report (admin/reports/status),
* the module and theme pages, and optionally via e-mail. It also provides the
* ability to install contributed modules and themes via an user interface.
*/
/**
@ -246,11 +249,14 @@ function update_menu() {
}
/**
* Determine if the current user can access the updater menu items.
* Access callback: Resolves if the current user can access updater menu items.
*
* This is used as a menu system access callback. It both enforces the
* 'administer software updates' permission and the global killswitch for the
* authorize.php script.
* It both enforces the 'administer software updates' permission and the global
* kill switch for the authorize.php script.
*
* @return
* TRUE if the current user can access the updater menu items; FALSE
* otherwise.
*
* @see update_menu()
*/
@ -327,10 +333,10 @@ function update_themes_disabled($themes) {
}
/**
* Implements hook_form_FORM_ID_alter().
* Implements hook_form_FORM_ID_alter() for system_modules().
*
* Adds a submit handler to the system modules form, so that if a site admin
* saves the form, we invalidate the cache of available updates.
* Adds a form submission handler to the system modules form, so that if a site
* admin saves the form, we invalidate the cache of available updates.
*
* @see _update_cache_clear()
*/
@ -339,7 +345,9 @@ function update_form_system_modules_alter(&$form, $form_state) {
}
/**
* Helper function for use as a form submit callback.
* Form submission handler for system_modules().
*
* @see update_form_system_modules_alter()
*/
function update_cache_clear_submit($form, &$form_state) {
// Clear all update module caches.
@ -347,7 +355,7 @@ function update_cache_clear_submit($form, &$form_state) {
}
/**
* Prints a warning message when there is no data about available updates.
* Returns a warning message when there is no data about available updates.
*/
function _update_no_data() {
$destination = drupal_get_destination();
@ -358,20 +366,22 @@ function _update_no_data() {
}
/**
* Internal helper to try to get the update information from the cache
* if possible, and to refresh the cache when necessary.
* Tries to get update information from cache and refreshes it when necessary.
*
* In addition to checking the cache lifetime, this function also ensures that
* there are no .info files for enabled modules or themes that have a newer
* modification timestamp than the last time we checked for available update
* data. If any .info file was modified, it almost certainly means a new
* version of something was installed. Without fresh available update data,
* the logic in update_calculate_project_data() will be wrong and produce
* confusing, bogus results.
* data. If any .info file was modified, it almost certainly means a new version
* of something was installed. Without fresh available update data, the logic in
* update_calculate_project_data() will be wrong and produce confusing, bogus
* results.
*
* @param $refresh
* Boolean to indicate if this method should refresh the cache automatically
* if there's no data.
* (optional) Boolean to indicate if this method should refresh the cache
* automatically if there's no data. Defaults to FALSE.
*
* @return
* Array of data about available releases, keyed by project shortname.
*
* @see update_refresh()
* @see update_get_projects()
@ -428,7 +438,11 @@ function update_get_available($refresh = FALSE) {
}
/**
* Wrapper to load the include file and then create a new fetch task.
* Creates a new fetch task after loading the necessary include file.
*
* @param $project
* Associative array of information about a project. See update_get_projects()
* for the keys used.
*
* @see _update_create_fetch_task()
*/
@ -438,7 +452,7 @@ function update_create_fetch_task($project) {
}
/**
* Wrapper to load the include file and then refresh the release data.
* Refreshes the release data after loading the necessary include file.
*
* @see _update_refresh()
*/
@ -448,7 +462,9 @@ function update_refresh() {
}
/**
* Wrapper to load the include file and then attempt to fetch update data.
* Attempts to fetch update data after loading the necessary include file.
*
* @see _update_fetch_data()
*/
function update_fetch_data() {
module_load_include('inc', 'update', 'update.fetch');
@ -456,7 +472,7 @@ function update_fetch_data() {
}
/**
* Return all currently cached data about available releases for all projects.
* Returns all currently cached data about available releases for all projects.
*
* @return
* Array of data about available releases, keyed by project shortname.
@ -481,17 +497,17 @@ function _update_get_cached_available_releases() {
/**
* Implements hook_mail().
*
* Constructs the email notification message when the site is out of date.
* Constructs the e-mail notification message when the site is out of date.
*
* @param $key
* Unique key to indicate what message to build, always 'status_notify'.
* @param $message
* Reference to the message array being built.
* @param $params
* Array of parameters to indicate what kind of text to include in the
* message body. This is a keyed array of message type ('core' or 'contrib')
* as the keys, and the status reason constant (UPDATE_NOT_SECURE, etc) for
* the values.
* Array of parameters to indicate what kind of text to include in the message
* body. This is a keyed array of message type ('core' or 'contrib') as the
* keys, and the status reason constant (UPDATE_NOT_SECURE, etc) for the
* values.
*
* @see drupal_mail()
* @see _update_cron_notify()
@ -518,22 +534,23 @@ function update_mail($key, &$message, $params) {
}
/**
* Helper function to return the appropriate message text when the site is out
* of date or missing a security update.
* Returns the appropriate message text when site is out of date or not secure.
*
* These error messages are shared by both update_requirements() for the
* site-wide status report at admin/reports/status and in the body of the
* notification emails generated by update_cron().
* notification e-mail messages generated by update_cron().
*
* @param $msg_type
* String to indicate what kind of message to generate. Can be either
* 'core' or 'contrib'.
* String to indicate what kind of message to generate. Can be either 'core'
* or 'contrib'.
* @param $msg_reason
* Integer constant specifying why message is generated.
* @param $report_link
* Boolean that controls if a link to the updates report should be added.
* (optional) Boolean that controls if a link to the updates report should be
* added. Defaults to FALSE.
* @param $language
* An optional language object to use.
* (optional) A language object to use. Defaults to NULL.
*
* @return
* The properly translated error message for the given key.
*/
@ -603,10 +620,9 @@ function _update_message_text($msg_type, $msg_reason, $report_link = FALSE, $lan
}
/**
* Private sort function to order projects based on their status.
* Orders projects based on their status.
*
* @see update_requirements()
* @see uasort()
* Callback for uasort() within update_requirements().
*/
function _update_project_status_sort($a, $b) {
// The status constants are numerically in the right order, so we can
@ -621,17 +637,16 @@ function _update_project_status_sort($a, $b) {
/**
* Returns HTML for the last time we checked for update data.
*
* In addition to properly formating the given timestamp, this function also
* In addition to properly formatting the given timestamp, this function also
* provides a "Check manually" link that refreshes the available update and
* redirects back to the same page.
*
* @param $variables
* An associative array containing:
* - 'last': The timestamp when the site last checked for available updates.
* - last: The timestamp when the site last checked for available updates.
*
* @see theme_update_report()
* @see theme_update_available_updates_form()
*
* @ingroup themeable
*/
function theme_update_last_check($variables) {
@ -647,7 +662,7 @@ function theme_update_last_check($variables) {
* Implements hook_verify_update_archive().
*
* First, we ensure that the archive isn't a copy of Drupal core, which the
* Update manager does not yet support. @see http://drupal.org/node/606592
* update manager does not yet support. See http://drupal.org/node/606592
*
* Then, we make sure that at least one module included in the archive file has
* an .info file which claims that the code is compatible with the current
@ -719,19 +734,19 @@ function update_verify_update_archive($project, $archive_file, $directory) {
* cleared when we're populating it after successfully fetching new available
* update data. Usage of the core cache API results in all sorts of potential
* problems that would result in attempting to fetch available update data all
* the time, including if a site has a "minimum cache lifetime" (which is both
* a minimum and a maximum) defined, or if a site uses memcache or another
* plug-able cache system that assumes volatile caches.
* the time, including if a site has a "minimum cache lifetime" (which is both a
* minimum and a maximum) defined, or if a site uses memcache or another
* pluggable cache system that assumes volatile caches.
*
* Update module still uses the {cache_update} table, but instead of using
* cache_set(), cache_get(), and cache_clear_all(), there are private helper
* functions that implement these same basic tasks but ensure that the cache
* is not prematurely cleared, and that the data is always stored in the
* The Update Manager module still uses the {cache_update} table, but instead of
* using cache_set(), cache_get(), and cache_clear_all(), there are private
* helper functions that implement these same basic tasks but ensure that the
* cache is not prematurely cleared, and that the data is always stored in the
* database, even if memcache or another cache backend is in use.
*/
/**
* Store data in the private update status cache table.
* Stores data in the private update status cache table.
*
* @param $cid
* The cache ID to save the data with.
@ -743,6 +758,8 @@ function update_verify_update_archive($project, $archive_file, $directory) {
* by explicitly using _update_cache_clear().
* - A Unix timestamp: Indicates that the item should be kept at least until
* the given time, after which it will be invalidated.
*
* @see _update_cache_get()
*/
function _update_cache_set($cid, $data, $expire) {
$fields = array(
@ -764,12 +781,15 @@ function _update_cache_set($cid, $data, $expire) {
}
/**
* Retrieve data from the private update status cache table.
* Retrieves data from the private update status cache table.
*
* @param $cid
* The cache ID to retrieve.
*
* @return
* The data for the given cache ID, or NULL if the ID was not found.
* An array of data for the given cache ID, or NULL if the ID was not found.
*
* @see _update_cache_set()
*/
function _update_cache_get($cid) {
$cache = db_query("SELECT data, created, expire, serialized FROM {cache_update} WHERE cid = :cid", array(':cid' => $cid))->fetchObject();
@ -782,7 +802,10 @@ function _update_cache_get($cid) {
}
/**
* Return an array of cache items with a given cache ID prefix.
* Returns an array of cache items with a given cache ID prefix.
*
* @param string $cid_prefix
* The cache ID prefix.
*
* @return
* Associative array of cache items, keyed by cache ID.
@ -808,12 +831,12 @@ function _update_get_cache_multiple($cid_prefix) {
* Invalidates cached data relating to update status.
*
* @param $cid
* Optional cache ID of the record to clear from the private update module
* cache. If empty, all records will be cleared from the table except
* fetch tasks.
* (optional) Cache ID of the record to clear from the private update module
* cache. If empty, all records will be cleared from the table except fetch
* tasks. Defaults to NULL.
* @param $wildcard
* If $wildcard is TRUE, cache IDs starting with $cid are deleted in
* addition to the exact cache ID specified by $cid.
* (optional) If TRUE, cache IDs starting with $cid are deleted in addition to
* the exact cache ID specified by $cid. Defaults to FALSE.
*/
function _update_cache_clear($cid = NULL, $wildcard = FALSE) {
if (empty($cid)) {
@ -838,18 +861,18 @@ function _update_cache_clear($cid = NULL, $wildcard = FALSE) {
/**
* Implements hook_flush_caches().
*
* Called from update.php (among others) to flush the caches.
* Since we're running update.php, we are likely to install a new version of
* something, in which case, we want to check for available update data again.
* However, because we have our own caching system, we need to directly clear
* the database table ourselves at this point and return nothing, for example,
* on sites that use memcache where cache_clear_all() won't know how to purge
* this data.
* Called from update.php (among others) to flush the caches. Since we're
* running update.php, we are likely to install a new version of something, in
* which case, we want to check for available update data again. However,
* because we have our own caching system, we need to directly clear the
* database table ourselves at this point and return nothing, for example, on
* sites that use memcache where cache_clear_all() won't know how to purge this
* data.
*
* However, we only want to do this from update.php, since otherwise, we'd
* lose all the available update data on every cron run. So, we specifically
* check if the site is in MAINTENANCE_MODE == 'update' (which indicates
* update.php is running, not update module... alas for overloaded names).
* However, we only want to do this from update.php, since otherwise, we'd lose
* all the available update data on every cron run. So, we specifically check if
* the site is in MAINTENANCE_MODE == 'update' (which indicates update.php is
* running, not update module... alas for overloaded names).
*/
function update_flush_caches() {
if (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'update') {
@ -863,7 +886,7 @@ function update_flush_caches() {
*/
/**
* Return a short unique identifier for this Drupal installation.
* Returns a short unique identifier for this Drupal installation.
*
* @return
* An eight character string uniquely identifying this Drupal installation.
@ -877,14 +900,15 @@ function _update_manager_unique_identifier() {
}
/**
* Return the directory where update archive files should be extracted.
* Returns the directory where update archive files should be extracted.
*
* @param $create
* If TRUE, attempt to create the directory if it does not already exist.
* (optional) Whether to attempt to create the directory if it does not
* already exist. Defaults to TRUE.
*
* @return
* The full path to the temporary directory where update file archives
* should be extracted.
* The full path to the temporary directory where update file archives should
* be extracted.
*/
function _update_manager_extract_directory($create = TRUE) {
$directory = &drupal_static(__FUNCTION__, '');
@ -898,14 +922,15 @@ function _update_manager_extract_directory($create = TRUE) {
}
/**
* Return the directory where update archive files should be cached.
* Returns the directory where update archive files should be cached.
*
* @param $create
* If TRUE, attempt to create the directory if it does not already exist.
* (optional) Whether to attempt to create the directory if it does not
* already exist. Defaults to TRUE.
*
* @return
* The full path to the temporary directory where update file archives
* should be cached.
* The full path to the temporary directory where update file archives should
* be cached.
*/
function _update_manager_cache_directory($create = TRUE) {
$directory = &drupal_static(__FUNCTION__, '');
@ -919,7 +944,7 @@ function _update_manager_cache_directory($create = TRUE) {
}
/**
* Clear the temporary files and directories based on file age from disk.
* Clears the temporary files and directories based on file age from disk.
*/
function update_clear_update_disk_cache() {
// List of update module cache directories. Do not create the directories if
@ -936,19 +961,19 @@ function update_clear_update_disk_cache() {
}
/**
* Delete stale files and directories from the Update manager disk cache.
* Deletes stale files and directories from the update manager disk cache.
*
* Files and directories older than 6 hours and development snapshots older
* than 5 minutes are considered stale. We only cache development snapshots
* for 5 minutes since otherwise updated snapshots might not be downloaded as
* Files and directories older than 6 hours and development snapshots older than
* 5 minutes are considered stale. We only cache development snapshots for 5
* minutes since otherwise updated snapshots might not be downloaded as
* expected.
*
* When checking file ages, we need to use the ctime, not the mtime
* (modification time) since many (all?) tar implementations go out of their
* way to set the mtime on the files they create to the timestamps recorded
* in the tarball. We want to see the last time the file was changed on disk,
* which is left alone by tar and correctly set to the time the archive file
* was unpacked.
* (modification time) since many (all?) tar implementations go out of their way
* to set the mtime on the files they create to the timestamps recorded in the
* tarball. We want to see the last time the file was changed on disk, which is
* left alone by tar and correctly set to the time the archive file was
* unpacked.
*
* @param $path
* A string containing a file path or (streamwrapper) URI.

View File

@ -6,7 +6,9 @@
*/
/**
* Menu callback. Generate a page about the update status of projects.
* Page callback: Generates a page about the update status of projects.
*
* @see update_menu()
*/
function update_status() {
if ($available = update_get_available(TRUE)) {
@ -257,6 +259,7 @@ function theme_update_report($variables) {
* - status: The integer code for a project's current update status.
*
* @see update_calculate_project_data()
* @ingroup themeable
*/
function theme_update_status_label($variables) {
switch ($variables['status']) {

View File

@ -6,7 +6,11 @@
*/
/**
* Form builder for the update settings tab.
* Form constructor for the update settings form.
*
* @see update_settings_validate()
* @see update_settings_submit()
* @ingroup forms
*/
function update_settings($form) {
$form['update_check_frequency'] = array(
@ -57,9 +61,11 @@ function update_settings($form) {
}
/**
* Validation callback for the settings form.
* Form validation handler for update_settings().
*
* Validates the email addresses and ensures the field is formatted correctly.
* Validates the e-mail addresses and ensures the field is formatted correctly.
*
* @see update_settings_submit()
*/
function update_settings_validate($form, &$form_state) {
if (!empty($form_state['values']['update_notify_emails'])) {
@ -89,13 +95,15 @@ function update_settings_validate($form, &$form_state) {
}
/**
* Submit handler for the settings tab.
* Form submission handler for update_settings().
*
* Also invalidates the cache of available updates if the "Check for updates
* of disabled modules and themes" setting is being changed. The available
* updates report need to refetch available update data after this setting
* changes or it would show misleading things (e.g. listing the disabled
* projects on the site with the "No available releases found" warning).
* Also invalidates the cache of available updates if the "Check for updates of
* disabled modules and themes" setting is being changed. The available updates
* report needs to refetch available update data after this setting changes or
* it would show misleading things (e.g., listing the disabled projects on the
* site with the "No available releases found" warning).
*
* @see update_settings_validate()
*/
function update_settings_submit($form, $form_state) {
$op = $form_state['values']['op'];

View File

@ -2,38 +2,43 @@
/**
* @file
* Tests for update.module.
* This file contains tests for the Update Manager module.
*
* This file contains tests for the update module. The overarching methodology
* of these tests is we need to compare a given state of installed modules and
* themes (e.g. version, project grouping, timestamps, etc) vs. a current
* state of what the release history XML files we fetch say is available. We
* have dummy XML files (in the 'tests' subdirectory) that describe various
* scenarios of what's available for different test projects, and we have
* dummy .info file data (specified via hook_system_info_alter() in the
* update_test helper module) describing what's currently installed. Each
* test case defines a set of projects to install, their current state (via
* the 'update_test_system_info' variable) and the desired available update
* data (via the 'update_test_xml_map' variable), and then performs a series
* of assertions that the report matches our expectations given the specific
* initial state and availability scenario.
* The overarching methodology of these tests is we need to compare a given
* state of installed modules and themes (e.g., version, project grouping,
* timestamps, etc) against a current state of what the release history XML
* files we fetch say is available. We have dummy XML files (in the
* modules/update/tests directory) that describe various scenarios of what's
* available for different test projects, and we have dummy .info file data
* (specified via hook_system_info_alter() in the update_test helper module)
* describing what's currently installed. Each test case defines a set of
* projects to install, their current state (via the 'update_test_system_info'
* variable) and the desired available update data (via the
* 'update_test_xml_map' variable), and then performs a series of assertions
* that the report matches our expectations given the specific initial state and
* availability scenario.
*/
/**
* Base class to define some shared functions used by all update tests.
* Defines some shared functions used by all update tests.
*/
class UpdateTestHelper extends DrupalWebTestCase {
/**
* Refresh the update status based on the desired available update scenario.
* Refreshes the update status based on the desired available update scenario.
*
* @param $xml_map
* Array that maps project names to availability scenarios to fetch.
* The key '#all' is used if a project-specific mapping is not defined.
* Array that maps project names to availability scenarios to fetch. The key
* '#all' is used if a project-specific mapping is not defined.
* @param $url
* (optional) A string containing the URL to fetch update data from.
* Defaults to 'update-test'.
*
* @see update_test_mock_page()
*/
protected function refreshUpdateStatus($xml_map, $url = 'update-test') {
// Tell update module to fetch from the URL provided by update_test module.
// Tell the Update Manager module to fetch from the URL provided by
// update_test module.
variable_set('update_fetch_url', url($url, array('absolute' => TRUE)));
// Save the map for update_test_mock_page() to use.
variable_set('update_test_xml_map', $xml_map);
@ -42,7 +47,7 @@ class UpdateTestHelper extends DrupalWebTestCase {
}
/**
* Run a series of assertions that are applicable for all update statuses.
* Runs a series of assertions that are applicable to all update statuses.
*/
protected function standardTests() {
$this->assertRaw('<h3>' . t('Drupal core') . '</h3>');
@ -52,12 +57,15 @@ class UpdateTestHelper extends DrupalWebTestCase {
}
/**
* Tests behavior related to discovering and listing updates to Drupal core.
*/
class UpdateCoreTestCase extends UpdateTestHelper {
public static function getInfo() {
return array(
'name' => 'Update core functionality',
'description' => 'Tests the update module through a series of functional tests using mock XML data.',
'description' => 'Tests the Update Manager module through a series of functional tests using mock XML data.',
'group' => 'Update',
);
}
@ -69,7 +77,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
}
/**
* Tests the update module when no updates are available.
* Tests the Update Manager module when no updates are available.
*/
function testNoUpdatesAvailable() {
$this->setSystemInfo7_0();
@ -81,7 +89,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
}
/**
* Tests the update module when one normal update ("7.1") is available.
* Tests the Update Manager module when one normal update is available.
*/
function testNormalUpdateAvailable() {
$this->setSystemInfo7_0();
@ -96,7 +104,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
}
/**
* Tests the update module when a security update ("7.2") is available.
* Tests the Update Manager module when a security update is available.
*/
function testSecurityUpdateAvailable() {
$this->setSystemInfo7_0();
@ -111,7 +119,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
}
/**
* Ensure proper results where there are date mismatches among modules.
* Ensures proper results where there are date mismatches among modules.
*/
function testDatestampMismatch() {
$system_info = array(
@ -134,7 +142,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
}
/**
* Check that running cron updates the list of available updates.
* Checks that running cron updates the list of available updates.
*/
function testModulePageRunCron() {
$this->setSystemInfo7_0();
@ -147,7 +155,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
}
/**
* Check the messages at admin/modules when the site is up to date.
* Checks the messages at admin/modules when the site is up to date.
*/
function testModulePageUpToDate() {
$this->setSystemInfo7_0();
@ -164,7 +172,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
}
/**
* Check the messages at admin/modules when missing an update.
* Checks the messages at admin/modules when an update is missing.
*/
function testModulePageRegularUpdate() {
$this->setSystemInfo7_0();
@ -181,7 +189,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
}
/**
* Check the messages at admin/modules when missing a security update.
* Checks the messages at admin/modules when a security update is missing.
*/
function testModulePageSecurityUpdate() {
$this->setSystemInfo7_0();
@ -216,7 +224,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
}
/**
* Tests the update module when the update server returns 503 (Service unavailable) errors.
* Tests the Update Manager module when the update server returns 503 errors.
*/
function testServiceUnavailable() {
$this->refreshUpdateStatus(array(), '503-error');
@ -252,6 +260,9 @@ class UpdateCoreTestCase extends UpdateTestHelper {
$this->assertEqual($queue->numberOfItems(), 2, 'Queue contains two items');
}
/**
* Sets the version to 7.0 when no project-specific mapping is defined.
*/
protected function setSystemInfo7_0() {
$setting = array(
'#all' => array(
@ -263,12 +274,15 @@ class UpdateCoreTestCase extends UpdateTestHelper {
}
/**
* Tests behavior related to handling updates to contributed modules and themes.
*/
class UpdateTestContribCase extends UpdateTestHelper {
public static function getInfo() {
return array(
'name' => 'Update contrib functionality',
'description' => 'Tests how the update module handles contributed modules and themes in a series of functional tests using mock XML data.',
'description' => 'Tests how the Update Manager module handles contributed modules and themes in a series of functional tests using mock XML data.',
'group' => 'Update',
);
}
@ -308,7 +322,7 @@ class UpdateTestContribCase extends UpdateTestHelper {
}
/**
* Test the basic functionality of a contrib module on the status report.
* Tests the basic functionality of a contrib module on the status report.
*/
function testUpdateContribBasic() {
$system_info = array(
@ -336,17 +350,17 @@ class UpdateTestContribCase extends UpdateTestHelper {
}
/**
* Test that contrib projects are ordered by project name.
* Tests that contrib projects are ordered by project name.
*
* If a project contains multiple modules, we want to make sure that the
* available updates report is sorted by the parent project names, not by
* the names of the modules included in each project. In this test case, we
* have 2 contrib projects, "BBB Update test" and "CCC Update test".
* However, we have a module called "aaa_update_test" that's part of the
* "CCC Update test" project. We need to make sure that we see the "BBB"
* project before the "CCC" project, even though "CCC" includes a module
* that's processed first if you sort alphabetically by module name (which
* is the order we see things inside system_rebuild_module_data() for example).
* available updates report is sorted by the parent project names, not by the
* names of the modules included in each project. In this test case, we have
* two contrib projects, "BBB Update test" and "CCC Update test". However, we
* have a module called "aaa_update_test" that's part of the "CCC Update test"
* project. We need to make sure that we see the "BBB" project before the
* "CCC" project, even though "CCC" includes a module that's processed first
* if you sort alphabetically by module name (which is the order we see things
* inside system_rebuild_module_data() for example).
*/
function testUpdateContribOrder() {
// We want core to be version 7.0.
@ -408,7 +422,7 @@ class UpdateTestContribCase extends UpdateTestHelper {
}
/**
* Test that subthemes are notified about security updates for base themes.
* Tests that subthemes are notified about security updates for base themes.
*/
function testUpdateBaseThemeSecurityUpdate() {
// Only enable the subtheme, not the base theme.
@ -449,7 +463,7 @@ class UpdateTestContribCase extends UpdateTestHelper {
}
/**
* Test that disabled themes are only shown when desired.
* Tests that disabled themes are only shown when desired.
*/
function testUpdateShowDisabledThemes() {
// Make sure all the update_test_* themes are disabled.
@ -510,7 +524,7 @@ class UpdateTestContribCase extends UpdateTestHelper {
}
/**
* Make sure that if we fetch from a broken URL, sane things happen.
* Makes sure that if we fetch from a broken URL, sane things happen.
*/
function testUpdateBrokenFetchURL() {
$system_info = array(
@ -566,13 +580,12 @@ class UpdateTestContribCase extends UpdateTestHelper {
}
/**
* Check that hook_update_status_alter() works to change a status.
* Checks that hook_update_status_alter() works to change a status.
*
* We provide the same external data as if aaa_update_test 7.x-1.0 were
* installed and that was the latest release. Then we use
* hook_update_status_alter() to try to mark this as missing a security
* update, then assert if we see the appropriate warnings on the right
* pages.
* update, then assert if we see the appropriate warnings on the right pages.
*/
function testHookUpdateStatusAlter() {
variable_set('allow_authorize_operations', TRUE);
@ -628,11 +641,15 @@ class UpdateTestContribCase extends UpdateTestHelper {
}
/**
* Tests project upload and extract functionality.
*/
class UpdateTestUploadCase extends UpdateTestHelper {
public static function getInfo() {
return array(
'name' => 'Upload and extract module functionality',
'description' => 'Tests the update module\'s upload and extraction functionality.',
'description' => 'Tests the Update Manager module\'s upload and extraction functionality.',
'group' => 'Update',
);
}
@ -673,7 +690,7 @@ class UpdateTestUploadCase extends UpdateTestHelper {
}
/**
* Ensure that archiver extensions are properly merged in the UI.
* Ensures that archiver extensions are properly merged in the UI.
*/
function testFileNameExtensionMerging() {
$this->drupalGet('admin/modules/install');
@ -684,7 +701,7 @@ class UpdateTestUploadCase extends UpdateTestHelper {
}
/**
* Check the messages on Update manager pages when missing a security update.
* Checks the messages on update manager pages when missing a security update.
*/
function testUpdateManagerCoreSecurityUpdateMessages() {
$setting = array(
@ -725,6 +742,9 @@ class UpdateTestUploadCase extends UpdateTestHelper {
}
/**
* Tests update functionality unrelated to the database.
*/
class UpdateCoreUnitTestCase extends DrupalUnitTestCase {
public static function getInfo() {
@ -741,7 +761,7 @@ class UpdateCoreUnitTestCase extends DrupalUnitTestCase {
}
/**
* Tests _update_build_fetch_url according to issue 1481156
* Tests that _update_build_fetch_url() builds the URL correctly.
*/
function testUpdateBuildFetchUrl() {
//first test that we didn't break the trivial case