diff options
43 files changed, 1355 insertions, 465 deletions
@@ -56,6 +56,13 @@ DirectoryIndex index.php index.html index.htm <IfModule mod_rewrite.c> RewriteEngine on + # Set "protossl" to "s" if we were accessed via https://. This is used later + # if you enable "www." stripping or enforcement, in order to ensure that + # you don't bounce between http and https. + RewriteRule ^ - [E=protossl] + RewriteCond %{HTTPS} on + RewriteRule ^ - [E=protossl:s] + # Block access to "hidden" directories whose names begin with a period. This # includes directories used by version control systems such as Subversion or # Git to store control files. Files whose names begin with a period, as well @@ -78,14 +85,15 @@ DirectoryIndex index.php index.html index.htm # To redirect all users to access the site WITH the 'www.' prefix, # (http://example.com/... will be redirected to http://www.example.com/...) # uncomment the following: + # RewriteCond %{HTTP_HOST} . # RewriteCond %{HTTP_HOST} !^www\. [NC] - # RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301] + # RewriteRule ^ http%{ENV:protossl}://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # # To redirect all users to access the site WITHOUT the 'www.' prefix, # (http://www.example.com/... will be redirected to http://example.com/...) # uncomment the following: # RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] - # RewriteRule ^ http://%1%{REQUEST_URI} [L,R=301] + # RewriteRule ^ http%{ENV:protossl}://%1%{REQUEST_URI} [L,R=301] # Modify the RewriteBase if you are using Drupal in a subdirectory or in a # VirtualDocumentRoot and the rewrite rules are not working properly. diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 7f4f0ffe1..ba4a4ac9f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,22 @@ + +Drupal 7.19, xxxx-xx-xx (development version) +----------------------- +- Added an assertThemeOutput() method to Simpletest to allow tests to check + that themed output matches an expected HTML string (API addition). +- Added a link to "Install another module" after a module has been successfully + downloaded via the Update Manager (UI change). +- Added an optional "exclusive" flag to installation profile .info files which + allows Drupal distributions to force a profile to be selected during + installation (API addition). +- Fixed a bug which caused the database API to not properly close database + connections. +- Added link to the URL for running cron from outside the site to the Cron + settings page (UI change). +- Fixed a bug which prevented image styles from being reverted on PHP 5.4. +- Made the default .htaccess rules protocol sensitive to improve security for + sites which use HTTPS and redirect between "www" and non-"www" versions of + the page. + Drupal 7.18, 2012-12-19 ----------------------- - Fixed security issues (multiple vulnerabilities). See SA-CORE-2012-004. diff --git a/authorize.php b/authorize.php index d14fa6e59..3ea2b20ac 100644 --- a/authorize.php +++ b/authorize.php @@ -4,16 +4,16 @@ * @file * Administrative script for running authorized file operations. * - * Using this script, the site owner (the user actually owning the files on - * the webserver) can authorize certain file-related operations to proceed - * with elevated privileges, for example to deploy and upgrade modules or - * themes. Users should not visit this page directly, but instead use an - * administrative user interface which knows how to redirect the user to this - * script as part of a multistep process. This script actually performs the - * selected operations without loading all of Drupal, to be able to more - * gracefully recover from errors. Access to the script is controlled by a - * global killswitch in settings.php ('allow_authorize_operations') and via - * the 'administer software updates' permission. + * Using this script, the site owner (the user actually owning the files on the + * webserver) can authorize certain file-related operations to proceed with + * elevated privileges, for example to deploy and upgrade modules or themes. + * Users should not visit this page directly, but instead use an administrative + * user interface which knows how to redirect the user to this script as part of + * a multistep process. This script actually performs the selected operations + * without loading all of Drupal, to be able to more gracefully recover from + * errors. Access to the script is controlled by a global killswitch in + * settings.php ('allow_authorize_operations') and via the 'administer software + * updates' permission. * * There are helper functions for setting up an operation to run via this * system in modules/system/system.module. For more information, see: @@ -21,16 +21,17 @@ */ /** - * Root directory of Drupal installation. + * Defines the root directory of the Drupal installation. */ define('DRUPAL_ROOT', getcwd()); /** - * Global flag to identify update.php and authorize.php runs, and so - * avoid various unwanted operations, such as hook_init() and - * hook_exit() invokes, css/js preprocessing and translation, and - * solve some theming issues. This flag is checked on several places - * in Drupal code (not just authorize.php). + * Global flag to identify update.php and authorize.php runs. + * + * Identifies update.php and authorize.php runs, avoiding unwanted operations + * such as hook_init() and hook_exit() invokes, css/js preprocessing and + * translation, and solves some theming issues. The flag is checked in other + * places in Drupal code (not just authorize.php). */ define('MAINTENANCE_MODE', 'update'); @@ -51,7 +52,7 @@ function authorize_access_denied_page() { * have access to the 'administer software updates' permission. * * @return - * TRUE if the current user can run authorize.php, otherwise FALSE. + * TRUE if the current user can run authorize.php, and FALSE if not. */ function authorize_access_allowed() { return variable_get('allow_authorize_operations', TRUE) && user_access('administer software updates'); diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc index 1b48217bc..dcab7df07 100644 --- a/includes/bootstrap.inc +++ b/includes/bootstrap.inc @@ -8,7 +8,7 @@ /** * The current system version. */ -define('VERSION', '7.18'); +define('VERSION', '7.19-dev'); /** * Core API compatibility. @@ -716,7 +716,6 @@ function drupal_settings_initialize() { if (isset($base_url)) { // Parse fixed base URL from settings.php. $parts = parse_url($base_url); - $http_protocol = $parts['scheme']; if (!isset($parts['path'])) { $parts['path'] = ''; } @@ -1186,10 +1185,11 @@ function _drupal_set_preferred_header_name($name = NULL) { * Headers are set in drupal_add_http_header(). Default headers are not set * if they have been replaced or unset using drupal_add_http_header(). * - * @param $default_headers - * An array of headers as name/value pairs. - * @param $single - * If TRUE and headers have already be sent, send only the specified header. + * @param array $default_headers + * (optional) An array of headers as name/value pairs. + * @param bool $only_default + * (optional) If TRUE and headers have already been sent, send only the + * specified headers. */ function drupal_send_headers($default_headers = array(), $only_default = FALSE) { $headers_sent = &drupal_static(__FUNCTION__, FALSE); diff --git a/includes/cache.inc b/includes/cache.inc index a19d3c38c..f76164b91 100644 --- a/includes/cache.inc +++ b/includes/cache.inc @@ -80,43 +80,15 @@ function cache_get_multiple(array &$cids, $bin = 'cache') { * same name. Other implementations might want to store several bins in data * structures that get flushed together. While it is not a problem for most * cache bins if the entries in them are flushed before their expire time, some - * might break functionality or are extremely expensive to recalculate. These - * will be marked with a (*). The other bins expired automatically by core. - * Contributed modules can add additional bins and get them expired - * automatically by implementing hook_flush_caches(). - * - * - cache: Generic cache storage bin (used for variables, theme registry, - * locale date, list of simpletest tests etc). - * - * - cache_block: Stores the content of various blocks. - * - * - cache field: Stores the field data belonging to a given object. - * - * - cache_filter: Stores filtered pieces of content. - * - * - cache_form(*): Stores multistep forms. Flushing this bin means that some - * forms displayed to users lose their state and the data already submitted - * to them. - * - * - cache_menu: Stores the structure of visible navigation menus per page. - * - * - cache_page: Stores generated pages for anonymous users. It is flushed - * very often, whenever a page changes, at least for every ode and comment - * submission. This is the only bin affected by the page cache setting on - * the administrator panel. - * - * - cache path: Stores the system paths that have an alias. - * - * - cache update(*): Stores available releases. The update server (for - * example, drupal.org) needs to produce the relevant XML for every project - * installed on the current site. As this is different for (almost) every - * site, it's very expensive to recalculate for the update server. + * might break functionality or are extremely expensive to recalculate. The + * other bins are expired automatically by core. Contributed modules can add + * additional bins and get them expired automatically by implementing + * hook_flush_caches(). * * The reasons for having several bins are as follows: - * - * - smaller bins mean smaller database tables and allow for faster selects and - * inserts - * - we try to put fast changing cache items and rather static ones into + * - Smaller bins mean smaller database tables and allow for faster selects and + * inserts. + * - We try to put fast changing cache items and rather static ones into * different bins. The effect is that only the fast changing bins will need a * lot of writes to disk. The more static bins will also be better cacheable * with MySQL's query cache. @@ -125,13 +97,27 @@ function cache_get_multiple(array &$cids, $bin = 'cache') { * The cache ID of the data to store. * @param $data * The data to store in the cache. Complex data types will be automatically - * serialized before insertion. - * Strings will be stored as plain text and not serialized. + * serialized before insertion. Strings will be stored as plain text and are + * not serialized. * @param $bin - * The cache bin to store the data in. Valid core values are 'cache_block', - * 'cache_bootstrap', 'cache_field', 'cache_filter', 'cache_form', - * 'cache_menu', 'cache_page', 'cache_update' or 'cache' for the default - * cache. + * The cache bin to store the data in. Valid core values are: + * - cache: (default) Generic cache storage bin (used for theme registry, + * locale date, list of simpletest tests, etc.). + * - cache_block: Stores the content of various blocks. + * - cache_bootstrap: Stores the class registry, the system list of modules, + * the list of which modules implement which hooks, and the Drupal variable + * list. + * - cache_field: Stores the field data belonging to a given object. + * - cache_filter: Stores filtered pieces of content. + * - cache_form: Stores multistep forms. Flushing this bin means that some + * forms displayed to users lose their state and the data already submitted + * to them. This bin should not be flushed before its expired time. + * - cache_menu: Stores the structure of visible navigation menus per page. + * - cache_page: Stores generated pages for anonymous users. It is flushed + * very often, whenever a page changes, at least for every node and comment + * submission. This is the only bin affected by the page cache setting on + * the administrator panel. + * - cache_path: Stores the system paths that have an alias. * @param $expire * One of the following values: * - CACHE_PERMANENT: Indicates that the item should never be removed unless @@ -141,6 +127,7 @@ function cache_get_multiple(array &$cids, $bin = 'cache') { * - A Unix timestamp: Indicates that the item should be kept at least until * the given time, after which it behaves like CACHE_TEMPORARY. * + * @see _update_cache_set() * @see cache_get() */ function cache_set($cid, $data, $bin = 'cache', $expire = CACHE_PERMANENT) { diff --git a/includes/common.inc b/includes/common.inc index 8276576e0..39836589f 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -2379,6 +2379,14 @@ function drupal_attributes(array $attributes = array()) { * internal links output by modules should be generated by this function if * possible. * + * However, for links enclosed in translatable text you should use t() and + * embed the HTML anchor tag directly in the translated string. For example: + * @code + * t('Visit the <a href="@url">settings</a> page', array('@url' => url('admin'))); + * @endcode + * This keeps the context of the link title ('settings' in the example) for + * translators. + * * @param string $text * The translated link text for the anchor tag. * @param string $path @@ -5038,6 +5046,11 @@ function drupal_get_private_key() { * * @param $value * An additional value to base the token on. + * + * @return string + * A 43-character URL-safe token for validation, based on the user session ID, + * the global $drupal_hash_salt variable from settings.php, and the + * 'drupal_private_key' configuration variable. */ function drupal_get_token($value = '') { return drupal_hmac_base64($value, session_id() . drupal_get_private_key() . drupal_get_hash_salt()); diff --git a/includes/database/database.inc b/includes/database/database.inc index cae50fb87..26ce6fcf4 100644 --- a/includes/database/database.inc +++ b/includes/database/database.inc @@ -194,7 +194,7 @@ abstract class DatabaseConnection extends PDO { /** * The key representing this connection. - * + * * The key is a unique string which identifies a database connection. A * connection can be a single server or a cluster of master and slaves (use * target to pick between master and slave). @@ -303,13 +303,29 @@ abstract class DatabaseConnection extends PDO { // Call PDO::__construct and PDO::setAttribute. parent::__construct($dsn, $username, $password, $driver_options); - // Set a specific PDOStatement class if the driver requires that. + // Set a Statement class, unless the driver opted out. if (!empty($this->statementClass)) { $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array($this->statementClass, array($this))); } } /** + * Destroys this Connection object. + * + * PHP does not destruct an object if it is still referenced in other + * variables. In case of PDO database connection objects, PHP only closes the + * connection when the PDO object is destructed, so any references to this + * object may cause the number of maximum allowed connections to be exceeded. + */ + public function destroy() { + // Destroy all references to this connection by setting them to NULL. + // The Statement class attribute only accepts a new value that presents a + // proper callable, so we reset it to PDOStatement. + $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('PDOStatement', array())); + $this->schema = NULL; + } + + /** * Returns the default query options for any given query. * * A given query can be customized with a number of option flags in an @@ -1627,8 +1643,8 @@ abstract class Database { */ final public static function removeConnection($key) { if (isset(self::$databaseInfo[$key])) { + self::closeConnection(NULL, $key); unset(self::$databaseInfo[$key]); - unset(self::$connections[$key]); return TRUE; } else { @@ -1694,11 +1710,24 @@ abstract class Database { if (!isset($key)) { $key = self::$activeKey; } - // To close the connection, we need to unset the static variable. + // To close a connection, it needs to be set to NULL and removed from the + // static variable. In all cases, closeConnection() might be called for a + // connection that was not opened yet, in which case the key is not defined + // yet and we just ensure that the connection key is undefined. if (isset($target)) { + if (isset(self::$connections[$key][$target])) { + self::$connections[$key][$target]->destroy(); + self::$connections[$key][$target] = NULL; + } unset(self::$connections[$key][$target]); } else { + if (isset(self::$connections[$key])) { + foreach (self::$connections[$key] as $target => $connection) { + self::$connections[$key][$target]->destroy(); + self::$connections[$key][$target] = NULL; + } + } unset(self::$connections[$key]); } } @@ -1852,8 +1881,8 @@ class DatabaseTransaction { */ protected $name; - public function __construct(DatabaseConnection &$connection, $name = NULL) { - $this->connection = &$connection; + public function __construct(DatabaseConnection $connection, $name = NULL) { + $this->connection = $connection; // If there is no transaction depth, then no transaction has started. Name // the transaction 'drupal_transaction'. if (!$depth = $connection->transactionDepth()) { diff --git a/includes/database/mysql/database.inc b/includes/database/mysql/database.inc index 7ad019e58..00d81f473 100644 --- a/includes/database/mysql/database.inc +++ b/includes/database/mysql/database.inc @@ -13,11 +13,11 @@ class DatabaseConnection_mysql extends DatabaseConnection { /** - * Flag to indicate if we have registered the nextID cleanup function. + * Flag to indicate if the cleanup function in __destruct() should run. * * @var boolean */ - protected $shutdownRegistered = FALSE; + protected $needsCleanup = FALSE; public function __construct(array $connection_options = array()) { // This driver defaults to transaction support, except if explicitly passed FALSE. @@ -78,6 +78,12 @@ class DatabaseConnection_mysql extends DatabaseConnection { $this->exec(implode('; ', $connection_options['init_commands'])); } + public function __destruct() { + if ($this->needsCleanup) { + $this->nextIdDelete(); + } + } + public function queryRange($query, $from, $count, array $args = array(), array $options = array()) { return $this->query($query . ' LIMIT ' . (int) $from . ', ' . (int) $count, $args, $options); } @@ -115,12 +121,7 @@ class DatabaseConnection_mysql extends DatabaseConnection { $this->query('INSERT INTO {sequences} (value) VALUES (:value) ON DUPLICATE KEY UPDATE value = value', array(':value' => $existing_id)); $new_id = $this->query('INSERT INTO {sequences} () VALUES ()', array(), array('return' => Database::RETURN_INSERT_ID)); } - if (!$this->shutdownRegistered) { - // Use register_shutdown_function() here to keep the database system - // independent of Drupal. - register_shutdown_function(array($this, 'nextIdDelete')); - $shutdownRegistered = TRUE; - } + $this->needsCleanup = TRUE; return $new_id; } diff --git a/includes/form.inc b/includes/form.inc index aa90eca69..9121a35a8 100644 --- a/includes/form.inc +++ b/includes/form.inc @@ -3685,6 +3685,8 @@ function form_pre_render_fieldset($element) { * array_shift($args); * array_shift($args); * // We store the user's original input in $keywords, including any slashes. + * // Note: A prepended or trailing slash will be removed. For example, if the + * // user enters '/a/few/words/' then $keywords will contain 'a/few/words'. * $keywords = implode('/', $args); * * // Your code here. diff --git a/includes/install.core.inc b/includes/install.core.inc index 9805e1c88..7a694e9bb 100644 --- a/includes/install.core.inc +++ b/includes/install.core.inc @@ -1041,7 +1041,21 @@ function install_select_profile(&$install_state) { } /** - * Selects an installation profile from a list or from a $_POST submission. + * Selects an installation profile. + * + * A profile will be selected if: + * - Only one profile is available, + * - A profile was submitted through $_POST, + * - Exactly one of the profiles is marked as "exclusive". + * If multiple profiles are marked as "exclusive" then no profile will be + * selected. + * + * @param array $profiles + * An associative array of profiles with the machine-readable names as keys. + * + * @return + * The machine-readable name of the selected profile or NULL if no profile was + * selected. */ function _install_select_profile($profiles) { if (sizeof($profiles) == 0) { @@ -1061,6 +1075,23 @@ function _install_select_profile($profiles) { } } } + // Check for a profile marked as "exclusive" and ensure that only one + // profile is marked as such. + $exclusive_profile = NULL; + foreach ($profiles as $profile) { + $profile_info = install_profile_info($profile->name); + if (!empty($profile_info['exclusive'])) { + if (empty($exclusive_profile)) { + $exclusive_profile = $profile->name; + } + else { + // We found a second "exclusive" profile. There's no way to choose + // between them, so we ignore the property. + return; + } + } + } + return $exclusive_profile; } /** diff --git a/includes/install.inc b/includes/install.inc index 0372483b6..c4bcb88b2 100644 --- a/includes/install.inc +++ b/includes/install.inc @@ -1244,6 +1244,12 @@ function drupal_check_module($module) { * - distribution_name: The name of the Drupal distribution that is being * installed, to be shown throughout the installation process. Defaults to * 'Drupal'. + * - exclusive: If the install profile is intended to be the only eligible + * choice in a distribution, setting exclusive = TRUE will auto-select it + * during installation, and the install profile selection screen will be + * skipped. If more than one profile is found where exclusive = TRUE then + * this property will have no effect and the profile selection screen will + * be shown as normal with all available profiles shown. * * Note that this function does an expensive file system scan to get info file * information for dependencies. If you only need information from the info diff --git a/includes/mail.inc b/includes/mail.inc index 8479d8e9b..630494ae5 100644 --- a/includes/mail.inc +++ b/includes/mail.inc @@ -212,9 +212,9 @@ function drupal_mail($module, $key, $to, $language, $params = array(), $from = N * 'mail_system', which is a keyed array. The default implementation * is the class whose name is the value of 'default-system' key. A more specific * match first to key and then to module will be used in preference to the - * default. To specificy a different class for all mail sent by one module, set + * default. To specify a different class for all mail sent by one module, set * the class name as the value for the key corresponding to the module name. To - * specificy a class for a particular message sent by one module, set the class + * specify a class for a particular message sent by one module, set the class * name as the value for the array key that is the message id, which is * "${module}_${key}". * diff --git a/includes/menu.inc b/includes/menu.inc index 0cb9d23b8..2be090327 100644 --- a/includes/menu.inc +++ b/includes/menu.inc @@ -618,6 +618,7 @@ function _menu_load_objects(&$item, &$map) { * $item['access'] becomes TRUE if the item is accessible, FALSE otherwise. */ function _menu_check_access(&$item, $map) { + $item['access'] = FALSE; // Determine access callback, which will decide whether or not the current // user has access to this path. $callback = empty($item['access_callback']) ? 0 : trim($item['access_callback']); diff --git a/install.php b/install.php index 881ca5a82..467027259 100644 --- a/install.php +++ b/install.php @@ -6,12 +6,16 @@ */ /** - * Root directory of Drupal installation. + * Defines the root directory of the Drupal installation. */ define('DRUPAL_ROOT', getcwd()); /** - * Global flag to indicate that site is in installation mode. + * Global flag to indicate the site is in installation mode. + * + * The constant is defined using define() instead of const so that PHP + * versions prior to 5.3 can display proper PHP requirements instead of causing + * a fatal error. */ define('MAINTENANCE_MODE', 'install'); diff --git a/modules/dblog/dblog-rtl.css b/modules/dblog/dblog-rtl.css index 282fe971d..0fab8d065 100644 --- a/modules/dblog/dblog-rtl.css +++ b/modules/dblog/dblog-rtl.css @@ -1,3 +1,7 @@ +/** + * @file + * Right-to-Left styling for the Database Logging module. + */ .form-item-type, .form-item-severity { diff --git a/modules/dblog/dblog.admin.inc b/modules/dblog/dblog.admin.inc index 0655e7564..7c1c0e20f 100644 --- a/modules/dblog/dblog.admin.inc +++ b/modules/dblog/dblog.admin.inc @@ -2,14 +2,19 @@ /** * @file - * Administrative page callbacks for the dblog module. + * Administrative page callbacks for the Database Logging module. */ /** - * Menu callback; displays a listing of log messages. + * Page callback: Displays a listing of database log messages. * - * Messages are truncated at 56 chars. Full-length message could be viewed at - * the message details page. + * Messages are truncated at 56 chars. Full-length messages can be viewed on the + * message details page. + * + * @see dblog_clear_log_form() + * @see dblog_event() + * @see dblog_filter_form() + * @see dblog_menu() * * @ingroup logging_severity_levels */ @@ -81,12 +86,18 @@ function dblog_overview() { } /** - * Menu callback; generic function to display a page of the most frequent events. + * Page callback: Shows the most frequent log messages of a given event type. + * + * Messages are not truncated on this page because events detailed herein do not + * have links to a detailed view. + * + * @param string $type + * Type of database log events to display (e.g., 'search'). * - * Messages are not truncated because events from this page have no detail view. + * @return array + * A build array in the format expected by drupal_render(). * - * @param $type - * type of dblog events to display. + * @see dblog_menu() */ function dblog_top($type) { @@ -127,7 +138,16 @@ function dblog_top($type) { } /** - * Menu callback; displays details about a log message. + * Page callback: Displays details about a specific database log message. + * + * @param int $id + * Unique ID of the database log message. + * + * @return array|string + * If the ID is located in the Database Logging table, a build array in the + * format expected by drupal_render(); otherwise, an empty string. + * + * @see dblog_menu() */ function dblog_event($id) { $severity = watchdog_severity_levels(); @@ -184,7 +204,10 @@ function dblog_event($id) { } /** - * Build query for dblog administration filters based on session. + * Builds a query for database log administration filters based on session. + * + * @return array + * An associative array with keys 'where' and 'args'. */ function dblog_build_filter_query() { if (empty($_SESSION['dblog_overview_filter'])) { @@ -213,9 +236,16 @@ function dblog_build_filter_query() { ); } - /** - * List dblog administration filters that can be applied. + * Creates a list of database log administration filters that can be applied. + * + * @return array + * Associative array of filters. The top-level keys are used as the form + * element names for the filters, and the values are arrays with the following + * elements: + * - title: Title of the filter. + * - where: The filter condition. + * - options: Array of options for the select list for the filter. */ function dblog_filters() { $filters = array(); @@ -244,7 +274,7 @@ function dblog_filters() { /** * Returns HTML for a log message. * - * @param $variables + * @param array $variables * An associative array containing: * - event: An object with at least the message and variables properties. * - link: (optional) Format message as link, event->wid is required. @@ -274,11 +304,13 @@ function theme_dblog_message($variables) { } /** - * Return form for dblog administration filters. + * Form constructor for the database logging filter form. * - * @ingroup forms - * @see dblog_filter_form_submit() * @see dblog_filter_form_validate() + * @see dblog_filter_form_submit() + * @see dblog_overview() + * + * @ingroup forms */ function dblog_filter_form($form) { $filters = dblog_filters(); @@ -316,12 +348,13 @@ function dblog_filter_form($form) { '#value' => t('Reset') ); } - return $form; } /** - * Validate result from dblog administration filter form. + * Form validation handler for dblog_filter_form(). + * + * @see dblog_filter_form_submit() */ function dblog_filter_form_validate($form, &$form_state) { if ($form_state['values']['op'] == t('Filter') && empty($form_state['values']['type']) && empty($form_state['values']['severity'])) { @@ -330,7 +363,9 @@ function dblog_filter_form_validate($form, &$form_state) { } /** - * Process result from dblog administration filter form. + * Form submission handler for dblog_filter_form(). + * + * @see dblog_filter_form_validate() */ function dblog_filter_form_submit($form, &$form_state) { $op = $form_state['values']['op']; @@ -351,10 +386,10 @@ function dblog_filter_form_submit($form, &$form_state) { } /** - * Return form for dblog clear button. + * Form constructor for the form that clears out the log. * - * @ingroup forms * @see dblog_clear_log_submit() + * @ingroup forms */ function dblog_clear_log_form($form) { $form['dblog_clear'] = array( @@ -374,7 +409,7 @@ function dblog_clear_log_form($form) { } /** - * Submit callback: clear database with log messages. + * Form submission handler for dblog_clear_log_form(). */ function dblog_clear_log_submit() { $_SESSION['dblog_overview_filter'] = array(); diff --git a/modules/dblog/dblog.css b/modules/dblog/dblog.css index 88f4ba01b..b1278862a 100644 --- a/modules/dblog/dblog.css +++ b/modules/dblog/dblog.css @@ -1,3 +1,8 @@ +/** + * @file + * Admin styles for the Database Logging module. + */ + .form-item-type, .form-item-severity { float: left; /* LTR */ diff --git a/modules/dblog/dblog.module b/modules/dblog/dblog.module index d831548c9..9183eed69 100644 --- a/modules/dblog/dblog.module +++ b/modules/dblog/dblog.module @@ -4,9 +4,9 @@ * @file * System monitoring and logging for administrators. * - * The dblog module monitors your site and keeps a list of - * recorded events containing usage and performance data, errors, - * warnings, and similar operational information. + * The Database Logging module monitors your site and keeps a list of recorded + * events containing usage and performance data, errors, warnings, and similar + * operational information. * * @see watchdog() */ @@ -96,7 +96,7 @@ function dblog_init() { /** * Implements hook_cron(). * - * Remove expired log messages. + * Controls the size of the log table, paring it to 'dblog_row_limit' messages. */ function dblog_cron() { // Cleanup the watchdog table. @@ -121,6 +121,12 @@ function dblog_cron() { } } +/** + * Gathers a list of uniquely defined database log message types. + * + * @return array + * List of uniquely defined database log message types. + */ function _dblog_get_message_types() { $types = array(); @@ -135,7 +141,7 @@ function _dblog_get_message_types() { /** * Implements hook_watchdog(). * - * Note some values may be truncated for database column size restrictions. + * Note: Some values may be truncated to meet database column size restrictions. */ function dblog_watchdog(array $log_entry) { Database::getConnection('default', 'default')->insert('watchdog') @@ -155,7 +161,7 @@ function dblog_watchdog(array $log_entry) { } /** - * Implements hook_form_FORM_ID_alter(). + * Implements hook_form_FORM_ID_alter() for system_logging_settings(). */ function dblog_form_system_logging_settings_alter(&$form, $form_state) { $form['dblog_row_limit'] = array( diff --git a/modules/dblog/dblog.test b/modules/dblog/dblog.test index ad01e97f5..cd101930d 100644 --- a/modules/dblog/dblog.test +++ b/modules/dblog/dblog.test @@ -5,8 +5,23 @@ * Tests for dblog.module. */ +/** + * Tests logging messages to the database. + */ class DBLogTestCase extends DrupalWebTestCase { + + /** + * A user with some relevent administrative permissions. + * + * @var object + */ protected $big_user; + + /** + * A user without any permissions. + * + * @var object + */ protected $any_user; public static function getInfo() { @@ -28,7 +43,11 @@ class DBLogTestCase extends DrupalWebTestCase { } /** - * Login users, create dblog events, and test dblog functionality through the admin and user interfaces. + * Tests Database Logging module functionality through interfaces. + * + * First logs in users, then creates database log events, and finally tests + * Database Logging module functionality through both the admin and user + * interfaces. */ function testDBLog() { // Login the admin user. @@ -46,12 +65,13 @@ class DBLogTestCase extends DrupalWebTestCase { } /** - * Verify setting of the dblog row limit. + * Verifies setting of the database log row limit. * - * @param integer $count Log row limit. + * @param int $row_limit + * The row limit. */ private function verifyRowLimit($row_limit) { - // Change the dblog row limit. + // Change the database log row limit. $edit = array(); $edit['dblog_row_limit'] = $row_limit; $this->drupalPost('admin/config/development/logging', $edit, t('Save configuration')); @@ -66,33 +86,35 @@ class DBLogTestCase extends DrupalWebTestCase { } /** - * Verify cron applies the dblog row limit. + * Verifies that cron correctly applies the database log row limit. * - * @param integer $count Log row limit. + * @param int $row_limit + * The row limit. */ private function verifyCron($row_limit) { // Generate additional log entries. $this->generateLogEntries($row_limit + 10); - // Verify dblog row count exceeds row limit. + // Verify that the database log row count exceeds the row limit. $count = db_query('SELECT COUNT(wid) FROM {watchdog}')->fetchField(); $this->assertTrue($count > $row_limit, t('Dblog row count of @count exceeds row limit of @limit', array('@count' => $count, '@limit' => $row_limit))); - // Run cron job. + // Run a cron job. $this->cronRun(); - // Verify dblog row count equals row limit plus one because cron adds a record after it runs. + // Verify that the database log row count equals the row limit plus one + // because cron adds a record after it runs. $count = db_query('SELECT COUNT(wid) FROM {watchdog}')->fetchField(); $this->assertTrue($count == $row_limit + 1, t('Dblog row count of @count equals row limit of @limit plus one', array('@count' => $count, '@limit' => $row_limit))); } /** - * Generate dblog entries. + * Generates a number of random database log events. * - * @param integer $count - * Number of log entries to generate. - * @param $type - * The type of watchdog entry. - * @param $severity - * The severity of the watchdog entry. + * @param int $count + * Number of watchdog entries to generate. + * @param string $type + * (optional) The type of watchdog entry. Defaults to 'custom'. + * @param int $severity + * (optional) The severity of the watchdog entry. Defaults to WATCHDOG_NOTICE. */ private function generateLogEntries($count, $type = 'custom', $severity = WATCHDOG_NOTICE) { global $base_root; @@ -119,42 +141,43 @@ class DBLogTestCase extends DrupalWebTestCase { } /** - * Verify the logged in user has the desired access to the various dblog nodes. + * Confirms that database log reports are displayed at the correct paths. * - * @param integer $response HTTP response code. + * @param int $response + * (optional) HTTP response code. Defaults to 200. */ private function verifyReports($response = 200) { $quote = '''; - // View dblog help node. + // View the database log help page. $this->drupalGet('admin/help/dblog'); $this->assertResponse($response); if ($response == 200) { $this->assertText(t('Database logging'), t('DBLog help was displayed')); } - // View dblog report node. + // View the database log report page. $this->drupalGet('admin/reports/dblog'); $this->assertResponse($response); if ($response == 200) { $this->assertText(t('Recent log messages'), t('DBLog report was displayed')); } - // View dblog page-not-found report node. + // View the database log page-not-found report page. $this->drupalGet('admin/reports/page-not-found'); $this->assertResponse($response); if ($response == 200) { $this->assertText(t('Top ' . $quote . 'page not found' . $quote . ' errors'), t('DBLog page-not-found report was displayed')); } - // View dblog access-denied report node. + // View the database log access-denied report page. $this->drupalGet('admin/reports/access-denied'); $this->assertResponse($response); if ($response == 200) { $this->assertText(t('Top ' . $quote . 'access denied' . $quote . ' errors'), t('DBLog access-denied report was displayed')); } - // View dblog event node. + // View the database log event page. $this->drupalGet('admin/reports/event/1'); $this->assertResponse($response); if ($response == 200) { @@ -163,7 +186,7 @@ class DBLogTestCase extends DrupalWebTestCase { } /** - * Verify events. + * Generates and then verifies various types of events. */ private function verifyEvents() { // Invoke events. @@ -179,14 +202,14 @@ class DBLogTestCase extends DrupalWebTestCase { } /** - * Generate and verify user events. - * + * Generates and then verifies some user events. */ private function doUser() { // Set user variables. $name = $this->randomName(); $pass = user_password(); - // Add user using form to generate add user event (which is not triggered by drupalCreateUser). + // Add a user using the form to generate an add user event (which is not + // triggered by drupalCreateUser). $edit = array(); $edit['name'] = $name; $edit['mail'] = $name . '@example.com'; @@ -195,15 +218,16 @@ class DBLogTestCase extends DrupalWebTestCase { $edit['status'] = 1; $this->drupalPost('admin/people/create', $edit, t('Create new account')); $this->assertResponse(200); - // Retrieve user object. + // Retrieve the user object. $user = user_load_by_name($name); $this->assertTrue($user != NULL, t('User @name was loaded', array('@name' => $name))); - $user->pass_raw = $pass; // Needed by drupalLogin. + // pass_raw property is needed by drupalLogin. + $user->pass_raw = $pass; // Login user. $this->drupalLogin($user); // Logout user. $this->drupalLogout(); - // Fetch row ids in watchdog that relate to the user. + // Fetch the row IDs in watchdog that relate to the user. $result = db_query('SELECT wid FROM {watchdog} WHERE uid = :uid', array(':uid' => $user->uid)); foreach ($result as $row) { $ids[] = $row->wid; @@ -213,17 +237,18 @@ class DBLogTestCase extends DrupalWebTestCase { // Login the admin user. $this->drupalLogin($this->big_user); - // Delete user. + // Delete the user created at the start of this test. // We need to POST here to invoke batch_process() in the internal browser. $this->drupalPost('user/' . $user->uid . '/cancel', array('user_cancel_method' => 'user_cancel_reassign'), t('Cancel account')); - // View the dblog report. + // View the database log report. $this->drupalGet('admin/reports/dblog'); $this->assertResponse(200); - // Verify events were recorded. + // Verify that the expected events were recorded. // Add user. - // Default display includes name and email address; if too long then email is replaced by three periods. + // Default display includes name and email address; if too long, the email + // address is replaced by three periods. $this->assertLogMessage(t('New user: %name (%email).', array('%name' => $name, '%email' => $user->mail)), t('DBLog event was recorded: [add user]')); // Login user. $this->assertLogMessage(t('Session opened for %name.', array('%name' => $name)), t('DBLog event was recorded: [login user]')); @@ -232,7 +257,7 @@ class DBLogTestCase extends DrupalWebTestCase { // Delete user. $message = t('Deleted user: %name %email.', array('%name' => $name, '%email' => '<' . $user->mail . '>')); $message_text = truncate_utf8(filter_xss($message, array()), 56, TRUE, TRUE); - // Verify full message on details page. + // Verify that the full message displays on the details page. $link = FALSE; if ($links = $this->xpath('//a[text()="' . html_entity_decode($message_text) . '"]')) { // Found link with the message text. @@ -253,7 +278,7 @@ class DBLogTestCase extends DrupalWebTestCase { $not_found_url = $this->randomName(60); $this->drupalGet($not_found_url); $this->assertResponse(404); - // View dblog page-not-found report page. + // View the database log page-not-found report page. $this->drupalGet('admin/reports/page-not-found'); $this->assertResponse(200); // Check that full-length URL displayed. @@ -261,9 +286,10 @@ class DBLogTestCase extends DrupalWebTestCase { } /** - * Generate and verify node events. + * Generates and then verifies some node events. * - * @param string $type Content type. + * @param string $type + * A node type (e.g., 'article', 'page' or 'poll'). */ private function doNode($type) { // Create user. @@ -272,61 +298,65 @@ class DBLogTestCase extends DrupalWebTestCase { // Login user. $this->drupalLogin($user); - // Create node using form to generate add content event (which is not triggered by drupalCreateNode). + // Create a node using the form in order to generate an add content event + // (which is not triggered by drupalCreateNode). $edit = $this->getContent($type); $langcode = LANGUAGE_NONE; $title = $edit["title"]; $this->drupalPost('node/add/' . $type, $edit, t('Save')); $this->assertResponse(200); - // Retrieve node object. + // Retrieve the node object. $node = $this->drupalGetNodeByTitle($title); $this->assertTrue($node != NULL, t('Node @title was loaded', array('@title' => $title))); - // Edit node. + // Edit the node. $edit = $this->getContentUpdate($type); $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save')); $this->assertResponse(200); - // Delete node. + // Delete the node. $this->drupalPost('node/' . $node->nid . '/delete', array(), t('Delete')); $this->assertResponse(200); - // View node (to generate page not found event). + // View the node (to generate page not found event). $this->drupalGet('node/' . $node->nid); $this->assertResponse(404); - // View the dblog report (to generate access denied event). + // View the database log report (to generate access denied event). $this->drupalGet('admin/reports/dblog'); $this->assertResponse(403); // Login the admin user. $this->drupalLogin($this->big_user); - // View the dblog report. + // View the database log report. $this->drupalGet('admin/reports/dblog'); $this->assertResponse(200); - // Verify events were recorded. - // Content added. + // Verify that node events were recorded. + // Was node content added? $this->assertLogMessage(t('@type: added %title.', array('@type' => $type, '%title' => $title)), t('DBLog event was recorded: [content added]')); - // Content updated. + // Was node content updated? $this->assertLogMessage(t('@type: updated %title.', array('@type' => $type, '%title' => $title)), t('DBLog event was recorded: [content updated]')); - // Content deleted. + // Was node content deleted? $this->assertLogMessage(t('@type: deleted %title.', array('@type' => $type, '%title' => $title)), t('DBLog event was recorded: [content deleted]')); - // View dblog access-denied report node. + // View the database log access-denied report page. $this->drupalGet('admin/reports/access-denied'); $this->assertResponse(200); - // Access denied. + // Verify that the 'access denied' event was recorded. $this->assertText(t('admin/reports/dblog'), t('DBLog event was recorded: [access denied]')); - // View dblog page-not-found report node. + // View the database log page-not-found report page. $this->drupalGet('admin/reports/page-not-found'); $this->assertResponse(200); - // Page not found. + // Verify that the 'page not found' event was recorded. $this->assertText(t('node/@nid', array('@nid' => $node->nid)), t('DBLog event was recorded: [page not found]')); } /** - * Create content based on content type. + * Creates random content based on node content type. * - * @param string $type Content type. - * @return array Content. + * @param string $type + * Node content type (e.g., 'article'). + * + * @return array + * Random content needed by various node types. */ private function getContent($type) { $langcode = LANGUAGE_NONE; @@ -350,10 +380,13 @@ class DBLogTestCase extends DrupalWebTestCase { } /** - * Create content update based on content type. + * Creates random content as an update based on node content type. + * + * @param string $type + * Node content type (e.g., 'article'). * - * @param string $type Content type. - * @return array Content. + * @return array + * Random content needed by various node types. */ private function getContentUpdate($type) { switch ($type) { @@ -375,11 +408,14 @@ class DBLogTestCase extends DrupalWebTestCase { } /** - * Login an admin user, create dblog event, and test clearing dblog functionality through the admin interface. + * Tests the addition and clearing of log events through the admin interface. + * + * Logs in the admin user, creates a database log event, and tests the + * functionality of clearing the database log through the admin interface. */ protected function testDBLogAddAndClear() { global $base_root; - // Get a count of how many watchdog entries there are. + // Get a count of how many watchdog entries already exist. $count = db_query('SELECT COUNT(*) FROM {watchdog}')->fetchField(); $log = array( 'type' => 'custom', @@ -396,27 +432,27 @@ class DBLogTestCase extends DrupalWebTestCase { ); // Add a watchdog entry. dblog_watchdog($log); - // Make sure the table count has actually incremented. + // Make sure the table count has actually been incremented. $this->assertEqual($count + 1, db_query('SELECT COUNT(*) FROM {watchdog}')->fetchField(), t('dblog_watchdog() added an entry to the dblog :count', array(':count' => $count))); // Login the admin user. $this->drupalLogin($this->big_user); - // Now post to clear the db table. + // Post in order to clear the database table. $this->drupalPost('admin/reports/dblog', array(), t('Clear log messages')); - // Count rows in watchdog that previously related to the deleted user. + // Count the rows in watchdog that previously related to the deleted user. $count = db_query('SELECT COUNT(*) FROM {watchdog}')->fetchField(); $this->assertEqual($count, 0, t('DBLog contains :count records after a clear.', array(':count' => $count))); } /** - * Test the dblog filter on admin/reports/dblog. + * Tests the database log filter functionality at admin/reports/dblog. */ protected function testFilter() { $this->drupalLogin($this->big_user); - // Clear log to ensure that only generated entries are found. + // Clear the log to ensure that only generated entries will be found. db_delete('watchdog')->execute(); - // Generate watchdog entries. + // Generate 9 random watchdog entries. $type_names = array(); $types = array(); for ($i = 0; $i < 3; $i++) { @@ -432,10 +468,10 @@ class DBLogTestCase extends DrupalWebTestCase { } } - // View the dblog. + // View the database log page. $this->drupalGet('admin/reports/dblog'); - // Confirm all the entries are displayed. + // Confirm that all the entries are displayed. $count = $this->getTypeCount($types); foreach ($types as $key => $type) { $this->assertEqual($count[$key], $type['count'], 'Count matched'); @@ -461,8 +497,8 @@ class DBLogTestCase extends DrupalWebTestCase { $this->assertEqual(array_sum($count), $type_count, 'Count matched'); } - // Set filter to match each of the three type attributes and confirm the - // number of entries displayed. + // Set the filter to match each of the two filter-type attributes and + // confirm the correct number of entries are displayed. foreach ($types as $key => $type) { $edit = array( 'type[]' => array($type['type']), @@ -480,10 +516,14 @@ class DBLogTestCase extends DrupalWebTestCase { } /** - * Get the log entry information form the page. + * Gets the database log event information from the browser page. * - * @return - * List of entries and their information. + * @return array + * List of log events where each event is an array with following keys: + * - severity: (int) A database log severity constant. + * - type: (string) The type of database log event. + * - message: (string) The message for this database log event. + * - user: (string) The user associated with this database log event. */ protected function getLogEntries() { $entries = array(); @@ -502,11 +542,12 @@ class DBLogTestCase extends DrupalWebTestCase { } /** - * Get the count of entries per type. + * Gets the count of database log entries by database log event type. * - * @param $types + * @param array $types * The type information to compare against. - * @return + * + * @return array * The count of each type keyed by the key of the $types array. */ protected function getTypeCount(array $types) { @@ -524,11 +565,12 @@ class DBLogTestCase extends DrupalWebTestCase { } /** - * Get the watchdog severity constant corresponding to the CSS class. + * Gets the watchdog severity constant corresponding to the CSS class. * - * @param $class + * @param string $class * CSS class attribute. - * @return + * + * @return int|null * The watchdog severity constant or NULL if not found. * * @ingroup logging_severity_levels @@ -557,11 +599,12 @@ class DBLogTestCase extends DrupalWebTestCase { } /** - * Extract the text contained by the element. + * Extracts the text contained by the XHTML element. * - * @param $element + * @param SimpleXMLElement $element * Element to extract text from. - * @return + * + * @return string * Extracted text. */ protected function asText(SimpleXMLElement $element) { @@ -572,21 +615,22 @@ class DBLogTestCase extends DrupalWebTestCase { } /** - * Assert messages appear on the log overview screen. + * Confirms that a log message appears on the database log overview screen. * - * This function should be used only for admin/reports/dblog page, because it - * check for the message link text truncated to 56 characters. Other dblog - * pages have no detail links so contains a full message text. + * This function should only be used for the admin/reports/dblog page, because + * it checks for the message link text truncated to 56 characters. Other log + * pages have no detail links so they contain the full message text. * - * @param $log_message - * The message to check. - * @param $message + * @param string $log_message + * The database log message to check. + * @param string $message * The message to pass to simpletest. */ protected function assertLogMessage($log_message, $message) { $message_text = truncate_utf8(filter_xss($log_message, array()), 56, TRUE, TRUE); - // After filter_xss() HTML entities should be converted to their characters - // because assertLink() uses this string in xpath() to query DOM. + // After filter_xss(), HTML entities should be converted to their character + // equivalents because assertLink() uses this string in xpath() to query the + // Document Object Model (DOM). $this->assertLink(html_entity_decode($message_text), 0, $message); } } diff --git a/modules/field/field.api.php b/modules/field/field.api.php index 5f641173e..90a09fef8 100644 --- a/modules/field/field.api.php +++ b/modules/field/field.api.php @@ -873,7 +873,7 @@ function hook_field_widget_form(&$form, &$form_state, $field, $instance, $langco '#type' => $instance['widget']['type'], '#default_value' => isset($items[$delta]) ? $items[$delta] : '', ); - return $element; + return array('value' => $element); } /** diff --git a/modules/field/field.attach.inc b/modules/field/field.attach.inc index 868d7bd75..5bebe9b35 100644 --- a/modules/field/field.attach.inc +++ b/modules/field/field.attach.inc @@ -709,7 +709,7 @@ function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $ _field_invoke_multiple('load', $entity_type, $queried_entities, $age, $null, $options); // Invoke hook_field_attach_load(): let other modules act on loading the - // entitiy. + // entity. module_invoke_all('field_attach_load', $entity_type, $queried_entities, $age, $options); // Build cache data. diff --git a/modules/field/field.module b/modules/field/field.module index b6cf05c9b..65dd48cfd 100644 --- a/modules/field/field.module +++ b/modules/field/field.module @@ -1197,7 +1197,7 @@ function _element_validate_integer($element, &$form_state) { * Use element_validate_integer_positive() instead. * * @deprecated - * @see element_validate_number_positive() + * @see element_validate_integer_positive() */ function _element_validate_integer_positive($element, &$form_state) { element_validate_integer_positive($element, $form_state); diff --git a/modules/field_ui/field_ui.admin.inc b/modules/field_ui/field_ui.admin.inc index 44770acb9..43bb20276 100644 --- a/modules/field_ui/field_ui.admin.inc +++ b/modules/field_ui/field_ui.admin.inc @@ -1534,7 +1534,7 @@ function field_ui_existing_field_options($entity_type, $bundle) { // - locked fields, // - fields already in the current bundle, // - fields that cannot be added to the entity type, - // - fields that that shoud not be added via user interface. + // - fields that should not be added via user interface. if (empty($field['locked']) && !field_info_instance($entity_type, $field['field_name'], $bundle) @@ -1544,7 +1544,7 @@ function field_ui_existing_field_options($entity_type, $bundle) { 'type' => $field['type'], 'type_label' => $field_types[$field['type']]['label'], 'field' => $field['field_name'], - 'label' => t($instance['label']), + 'label' => $instance['label'], 'widget_type' => $instance['widget']['type'], ); } diff --git a/modules/image/image.admin.inc b/modules/image/image.admin.inc index ab99a49e8..9f0fab254 100644 --- a/modules/image/image.admin.inc +++ b/modules/image/image.admin.inc @@ -326,7 +326,7 @@ function image_style_delete_form_submit($form, &$form_state) { /** * Confirmation form to revert a database style to its default. */ -function image_style_revert_form($form, $form_state, $style) { +function image_style_revert_form($form, &$form_state, $style) { $form_state['image_style'] = $style; return confirm_form( diff --git a/modules/image/image.install b/modules/image/image.install index b7aac7152..1d7bd4ef4 100644 --- a/modules/image/image.install +++ b/modules/image/image.install @@ -391,7 +391,8 @@ function image_update_7002(array &$sandbox) { } // Process the table at the top of the list. - $table = reset(array_keys($sandbox['tables'])); + $keys = array_keys($sandbox['tables']); + $table = reset($keys); $sandbox['processed'] += _image_update_7002_populate_dimensions($table, $sandbox['tables'][$table], $sandbox['last_fid']); // Has the table been fully processed? diff --git a/modules/node/content_types.inc b/modules/node/content_types.inc index 72adc3491..4b722ee02 100644 --- a/modules/node/content_types.inc +++ b/modules/node/content_types.inc @@ -2,7 +2,7 @@ /** * @file - * Content type editing UI. + * Content type editing user interface. */ /** @@ -388,8 +388,7 @@ function node_node_type_update($info) { } /** - * Resets all of the relevant fields of a module-defined node type to their - * default values. + * Resets relevant fields of a module-defined node type to their default values. * * @param $type * The node type to reset. The node type is passed back by reference with its @@ -410,6 +409,8 @@ function node_type_reset($type) { /** * Menu callback; delete a single content type. + * + * @ingroup forms */ function node_type_delete_confirm($form, &$form_state, $type) { $form['type'] = array('#type' => 'value', '#value' => $type->type); @@ -430,6 +431,8 @@ function node_type_delete_confirm($form, &$form_state, $type) { /** * Process content type delete confirm submissions. + * + * @see node_type_delete_confirm() */ function node_type_delete_confirm_submit($form, &$form_state) { node_type_delete($form_state['values']['type']); diff --git a/modules/node/node.admin.inc b/modules/node/node.admin.inc index 1508bc054..be09b37cc 100644 --- a/modules/node/node.admin.inc +++ b/modules/node/node.admin.inc @@ -7,6 +7,10 @@ /** * Menu callback: confirm rebuilding of permissions. + * + * @see node_configure_rebuild_confirm_submit() + * @see node_menu() + * @ingroup forms */ function node_configure_rebuild_confirm() { return confirm_form(array(), t('Are you sure you want to rebuild the permissions on site content?'), @@ -15,6 +19,8 @@ function node_configure_rebuild_confirm() { /** * Handler for wipe confirmation + * + * @see node_configure_rebuild_confirm() */ function node_configure_rebuild_confirm_submit($form, &$form_state) { node_access_rebuild(TRUE); @@ -66,6 +72,9 @@ function node_node_operations() { /** * List node administration filters that can be applied. + * + * @return + * An associative array of filters. */ function node_filters() { // Regular filters @@ -110,7 +119,7 @@ function node_filters() { } /** - * Apply filters for node administration filters based on session. + * Applies filters for node administration filters based on session. * * @param $query * A SelectQuery to which the filters should be applied. @@ -133,7 +142,16 @@ function node_build_filter_query(SelectQueryInterface $query) { } /** - * Return form for node administration filters. + * Returns the node administration filters form array to node_admin_content(). + * + * @see node_admin_nodes() + * @see node_admin_nodes_submit() + * @see node_admin_nodes_validate() + * @see node_filter_form_submit() + * @see node_multiple_delete_confirm() + * @see node_multiple_delete_confirm_submit() + * + * @ingroup forms */ function node_filter_form() { $session = isset($_SESSION['node_overview_filter']) ? $_SESSION['node_overview_filter'] : array(); @@ -208,7 +226,15 @@ function node_filter_form() { } /** - * Process result from node administration filter form. + * Form submission handler for node_filter_form(). + * + * @see node_admin_content() + * @see node_admin_nodes() + * @see node_admin_nodes_submit() + * @see node_admin_nodes_validate() + * @see node_filter_form() + * @see node_multiple_delete_confirm() + * @see node_multiple_delete_confirm_submit() */ function node_filter_form_submit($form, &$form_state) { $filters = node_filters(); @@ -240,15 +266,15 @@ function node_filter_form_submit($form, &$form_state) { * Make mass update of nodes, changing all nodes in the $nodes array * to update them with the field values in $updates. * - * IMPORTANT NOTE: This function is intended to work when called - * from a form submit handler. Calling it outside of the form submission - * process may not work correctly. + * IMPORTANT NOTE: This function is intended to work when called from a form + * submission handler. Calling it outside of the form submission process may not + * work correctly. * * @param array $nodes * Array of node nids to update. * @param array $updates - * Array of key/value pairs with node field names and the - * value to update that field to. + * Array of key/value pairs with node field names and the value to update that + * field to. */ function node_mass_update($nodes, $updates) { // We use batch processing to prevent timeout when updating a large number @@ -279,7 +305,17 @@ function node_mass_update($nodes, $updates) { } /** - * Node Mass Update - helper function. + * Updates individual nodes when fewer than 10 are queued. + * + * @param $nid + * ID of node to update. + * @param $updates + * Associative array of updates. + * + * @return object + * An updated node object. + * + * @see node_mass_update() */ function _node_mass_update_helper($nid, $updates) { $node = node_load($nid, NULL, TRUE); @@ -293,7 +329,14 @@ function _node_mass_update_helper($nid, $updates) { } /** - * Node Mass Update Batch operation + * Executes a batch operation for node_mass_update(). + * + * @param array $nodes + * An array of node IDs. + * @param array $updates + * Associative array of updates. + * @param array $context + * An array of contextual key/values. */ function _node_mass_update_batch_process($nodes, $updates, &$context) { if (!isset($context['sandbox']['progress'])) { @@ -324,7 +367,15 @@ function _node_mass_update_batch_process($nodes, $updates, &$context) { } /** - * Node Mass Update Batch 'finished' callback. + * Menu callback: Reports the status of batch operation for node_mass_update(). + * + * @param bool $success + * A boolean indicating whether the batch mass update operation successfully + * concluded. + * @param int $results + * The number of nodes updated via the batch mode process. + * @param array $operations + * An array of function calls (not used in this function). */ function _node_mass_update_batch_finished($success, $results, $operations) { if ($success) { @@ -339,7 +390,17 @@ function _node_mass_update_batch_finished($success, $results, $operations) { } /** - * Menu callback: content administration. + * Page callback: Form constructor for the content administration form. + * + * @see node_admin_nodes() + * @see node_admin_nodes_submit() + * @see node_admin_nodes_validate() + * @see node_filter_form() + * @see node_filter_form_submit() + * @see node_menu() + * @see node_multiple_delete_confirm() + * @see node_multiple_delete_confirm_submit() + * @ingroup forms */ function node_admin_content($form, $form_state) { if (isset($form_state['values']['operation']) && $form_state['values']['operation'] == 'delete') { @@ -354,6 +415,15 @@ function node_admin_content($form, $form_state) { /** * Form builder: Builds the node administration overview. + * + * @see node_admin_nodes_submit() + * @see node_admin_nodes_validate() + * @see node_filter_form() + * @see node_filter_form_submit() + * @see node_multiple_delete_confirm() + * @see node_multiple_delete_confirm_submit() + * + * @ingroup forms */ function node_admin_nodes() { $admin_access = user_access('administer nodes'); @@ -525,8 +595,15 @@ function node_admin_nodes() { /** * Validate node_admin_nodes form submissions. * - * Check if any nodes have been selected to perform the chosen - * 'Update option' on. + * Checks whether any nodes have been selected to perform the chosen 'Update + * option' on. + * + * @see node_admin_nodes() + * @see node_admin_nodes_submit() + * @see node_filter_form() + * @see node_filter_form_submit() + * @see node_multiple_delete_confirm() + * @see node_multiple_delete_confirm_submit() */ function node_admin_nodes_validate($form, &$form_state) { // Error if there are no items to select. @@ -538,7 +615,14 @@ function node_admin_nodes_validate($form, &$form_state) { /** * Process node_admin_nodes form submissions. * - * Execute the chosen 'Update option' on the selected nodes. + * Executes the chosen 'Update option' on the selected nodes. + * + * @see node_admin_nodes() + * @see node_admin_nodes_validate() + * @see node_filter_form() + * @see node_filter_form_submit() + * @see node_multiple_delete_confirm() + * @see node_multiple_delete_confirm_submit() */ function node_admin_nodes_submit($form, &$form_state) { $operations = module_invoke_all('node_operations'); @@ -564,6 +648,17 @@ function node_admin_nodes_submit($form, &$form_state) { } } +/** + * Multiple node deletion confirmation form for node_admin_content(). + * + * @see node_admin_nodes() + * @see node_admin_nodes_submit() + * @see node_admin_nodes_validate() + * @see node_filter_form() + * @see node_filter_form_submit() + * @see node_multiple_delete_confirm_submit() + * @ingroup forms + */ function node_multiple_delete_confirm($form, &$form_state, $nodes) { $form['nodes'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE); // array_filter returns only elements with TRUE values @@ -587,6 +682,16 @@ function node_multiple_delete_confirm($form, &$form_state, $nodes) { t('Delete'), t('Cancel')); } +/** + * Form submission handler for node_multiple_delete_confirm(). + * + * @see node_admin_nodes() + * @see node_admin_nodes_submit() + * @see node_admin_nodes_validate() + * @see node_filter_form() + * @see node_filter_form_submit() + * @see node_multiple_delete_confirm() + */ function node_multiple_delete_confirm_submit($form, &$form_state) { if ($form_state['values']['confirm']) { node_delete_multiple(array_keys($form_state['values']['nodes'])); diff --git a/modules/node/node.api.php b/modules/node/node.api.php index 052effc9b..f8dcfdeff 100644 --- a/modules/node/node.api.php +++ b/modules/node/node.api.php @@ -11,8 +11,8 @@ * Functions to define and modify content types. * * Each content type is maintained by a primary module, which is either - * node.module (for content types created in the user interface) or the - * module that implements hook_node_info() to define the content type. + * node.module (for content types created in the user interface) or the module + * that implements hook_node_info() to define the content type. * * During node operations (create, update, view, delete, etc.), there are * several sets of hooks that get invoked to allow modules to modify the base @@ -22,10 +22,10 @@ * function prefix. For example, poll.module defines the base for the Poll * content type as "poll", so during creation of a poll node, hook_insert() is * only invoked by calling poll_insert(). - * - All-module hooks: This set of hooks is invoked on all implementing - * modules, to allow other modules to modify what the primary node module is - * doing. For example, hook_node_insert() is invoked on all modules when - * creating a poll node. + * - All-module hooks: This set of hooks is invoked on all implementing modules, + * to allow other modules to modify what the primary node module is doing. For + * example, hook_node_insert() is invoked on all modules when creating a poll + * node. * - Field hooks: Hooks related to the fields attached to the node. These are * invoked from the field operations functions described below, and can be * either field-type-specific or all-module hooks. @@ -56,16 +56,15 @@ * - hook_entity_update() (all) * - hook_node_access_records() (all) * - hook_node_access_records_alter() (all) - * - Loading a node (calling node_load(), node_load_multiple(), or - * entity_load() with $entity_type of 'node'): + * - Loading a node (calling node_load(), node_load_multiple() or entity_load() + * with $entity_type of 'node'): * - Node and revision information is read from database. * - hook_load() (node-type-specific) * - field_attach_load_revision() and field_attach_load() * - hook_entity_load() (all) * - hook_node_load() (all) * - Viewing a single node (calling node_view() - note that the input to - * node_view() is a loaded node, so the Loading steps above are already - * done): + * node_view() is a loaded node, so the Loading steps above are already done): * - hook_view() (node-type-specific) * - field_attach_prepare_view() * - hook_entity_prepare_view() (all) @@ -97,9 +96,8 @@ * - Revision information is deleted from database * - hook_node_revision_delete() (all) * - field_attach_delete_revision() - * - Preparing a node for editing (calling node_form() - note that if it's - * an existing node, it will already be loaded; see the Loading section - * above): + * - Preparing a node for editing (calling node_form() - note that if it is an + * existing node, it will already be loaded; see the Loading section above): * - hook_prepare() (node-type-specific) * - hook_node_prepare() (all) * - hook_form() (node-type-specific) @@ -137,16 +135,16 @@ * associated with permission to view, edit, and delete individual nodes. * * The realms and grant IDs can be arbitrarily defined by your node access - * module; it is common to use role IDs as grant IDs, but that is not - * required. Your module could instead maintain its own list of users, where - * each list has an ID. In that case, the return value of this hook would be - * an array of the list IDs that this user is a member of. + * module; it is common to use role IDs as grant IDs, but that is not required. + * Your module could instead maintain its own list of users, where each list has + * an ID. In that case, the return value of this hook would be an array of the + * list IDs that this user is a member of. * - * A node access module may implement as many realms as necessary to - * properly define the access privileges for the nodes. Note that the system - * makes no distinction between published and unpublished nodes. It is the - * module's responsibility to provide appropriate realms to limit access to - * unpublished content. + * A node access module may implement as many realms as necessary to properly + * define the access privileges for the nodes. Note that the system makes no + * distinction between published and unpublished nodes. It is the module's + * responsibility to provide appropriate realms to limit access to unpublished + * content. * * Node access records are stored in the {node_access} table and define which * grants are required to access a node. There is a special case for the view @@ -183,7 +181,7 @@ * @param $account * The user object whose grants are requested. * @param $op - * The node operation to be performed, such as "view", "update", or "delete". + * The node operation to be performed, such as 'view', 'update', or 'delete'. * * @return * An array whose keys are "realms" of grants, and whose values are arrays of @@ -264,6 +262,7 @@ function hook_node_grants($account, $op) { * @return * An array of grants as defined above. * + * @see hook_node_access_records_alter() * @ingroup node_access */ function hook_node_access_records($node) { @@ -350,12 +349,11 @@ function hook_node_access_records_alter(&$grants, $node) { * Alter user access rules when trying to view, edit or delete a node. * * Node access modules establish rules for user access to content. - * hook_node_grants() defines permissions for a user to view, edit or - * delete nodes by building a $grants array that indicates the permissions - * assigned to the user by each node access module. This hook is called to allow - * modules to modify the $grants array by reference, so the interaction of - * multiple node access modules can be altered or advanced business logic can be - * applied. + * hook_node_grants() defines permissions for a user to view, edit or delete + * nodes by building a $grants array that indicates the permissions assigned to + * the user by each node access module. This hook is called to allow modules to + * modify the $grants array by reference, so the interaction of multiple node + * access modules can be altered or advanced business logic can be applied. * * @see hook_node_grants() * @@ -374,8 +372,8 @@ function hook_node_access_records_alter(&$grants, $node) { * @param $op * The operation being performed, 'view', 'update' or 'delete'. * - * Developers may use this hook to either add additional grants to a user - * or to remove existing grants. These rules are typically based on either the + * Developers may use this hook to either add additional grants to a user or to + * remove existing grants. These rules are typically based on either the * permissions assigned to a user role, or specific attributes of a user * account. * @@ -412,10 +410,10 @@ function hook_node_grants_alter(&$grants, $account, $op) { * @return * An array of operations. Each operation is an associative array that may * contain the following key-value pairs: - * - 'label': Required. The label for the operation, displayed in the dropdown + * - label: (required) The label for the operation, displayed in the dropdown * menu. - * - 'callback': Required. The function to call for the operation. - * - 'callback arguments': Optional. An array of additional arguments to pass + * - callback: (required) The function to call for the operation. + * - callback arguments: (optional) An array of additional arguments to pass * to the callback function. */ function hook_node_operations() { @@ -528,11 +526,10 @@ function hook_node_insert($node) { /** * Act on arbitrary nodes being loaded from the database. * - * This hook should be used to add information that is not in the node or - * node revisions table, not to replace information that is in these tables - * (which could interfere with the entity cache). For performance reasons, - * information for all available nodes should be loaded in a single query where - * possible. + * This hook should be used to add information that is not in the node or node + * revisions table, not to replace information that is in these tables (which + * could interfere with the entity cache). For performance reasons, information + * for all available nodes should be loaded in a single query where possible. * * This hook is invoked during node loading, which is handled by entity_load(), * via classes NodeController and DrupalDefaultEntityController. After the node @@ -572,15 +569,15 @@ function hook_node_load($nodes, $types) { * Modules may implement this hook if they want to have a say in whether or not * a given user has access to perform a given operation on a node. * - * The administrative account (user ID #1) always passes any access check, - * so this hook is not called in that case. Users with the "bypass node access" + * The administrative account (user ID #1) always passes any access check, so + * this hook is not called in that case. Users with the "bypass node access" * permission may always view and edit content through the administrative * interface. * - * Note that not all modules will want to influence access on all - * node types. If your module does not want to actively grant or - * block access, return NODE_ACCESS_IGNORE or simply return nothing. - * Blindly returning FALSE will break other node access modules. + * Note that not all modules will want to influence access on all node types. If + * your module does not want to actively grant or block access, return + * NODE_ACCESS_IGNORE or simply return nothing. Blindly returning FALSE will + * break other node access modules. * * Also note that this function isn't called for node listings (e.g., RSS feeds, * the default home page at path 'node', a recent content block, etc.) See @@ -651,17 +648,17 @@ function hook_node_prepare($node) { /** * Act on a node being displayed as a search result. * - * This hook is invoked from node_search_execute(), after node_load() - * and node_view() have been called. + * This hook is invoked from node_search_execute(), after node_load() and + * node_view() have been called. * * @param $node * The node being displayed in a search result. * * @return array * Extra information to be displayed with search result. This information - * should be presented as an associative array. It will be concatenated - * with the post information (last updated, author) in the default search - * result theming. + * should be presented as an associative array. It will be concatenated with + * the post information (last updated, author) in the default search result + * theming. * * @see template_preprocess_search_result() * @see search-result.tpl.php @@ -724,8 +721,8 @@ function hook_node_update($node) { /** * Act on a node being indexed for searching. * - * This hook is invoked during search indexing, after node_load(), and after - * the result of node_view() is added as $node->rendered to the node object. + * This hook is invoked during search indexing, after node_load(), and after the + * result of node_view() is added as $node->rendered to the node object. * * @param $node * The node being indexed. @@ -756,8 +753,8 @@ function hook_node_update_index($node) { * * Note: Changes made to the $node object within your hook implementation will * have no effect. The preferred method to change a node's content is to use - * hook_node_presave() instead. If it is really necessary to change - * the node at the validate stage, you can use form_set_value(). + * hook_node_presave() instead. If it is really necessary to change the node at + * the validate stage, you can use form_set_value(). * * @param $node * The node being validated. @@ -874,8 +871,8 @@ function hook_node_view_alter(&$build) { * * This hook allows a module to define one or more of its own node types. For * example, the blog module uses it to define a blog node-type named "Blog - * entry." The name and attributes of each desired node type are specified in - * an array returned by the hook. + * entry." The name and attributes of each desired node type are specified in an + * array returned by the hook. * * Only module-provided node types should be defined through this hook. User- * provided (or 'custom') node types should be defined only in the 'node_type' @@ -887,22 +884,22 @@ function hook_node_view_alter(&$build) { * contains a sub-array for each node type, with the machine-readable type * name as the key. Each sub-array has up to 10 attributes. Possible * attributes: - * - "name": the human-readable name of the node type. Required. - * - "base": the base string used to construct callbacks corresponding to - * this node type. - * (i.e. if base is defined as example_foo, then example_foo_insert will - * be called when inserting a node of that type). This string is usually - * the name of the module, but not always. Required. - * - "description": a brief description of the node type. Required. - * - "help": help information shown to the user when creating a node of - * this type.. Optional (defaults to ''). - * - "has_title": boolean indicating whether or not this node type has a title - * field. Optional (defaults to TRUE). - * - "title_label": the label for the title field of this content type. - * Optional (defaults to 'Title'). - * - "locked": boolean indicating whether the administrator can change the - * machine name of this type. FALSE = changeable (not locked), - * TRUE = unchangeable (locked). Optional (defaults to TRUE). + * - name: (required) The human-readable name of the node type. + * - base: (required) The base string used to construct callbacks + * corresponding to this node type (for example, if base is defined as + * example_foo, then example_foo_insert will be called when inserting a node + * of that type). This string is usually the name of the module, but not + * always. + * - description: (required) A brief description of the node type. + * - help: (optional) Help information shown to the user when creating a node + * of this type. + * - has_title: (optional) A Boolean indicating whether or not this node type + * has a title field. + * - title_label: (optional) The label for the title field of this content + * type. + * - locked: (optional) A Boolean indicating whether the administrator can + * change the machine name of this type. FALSE = changeable (not locked), + * TRUE = unchangeable (locked). * * The machine name of a node type should contain only letters, numbers, and * underscores. Underscores will be converted into hyphens for the purpose of @@ -950,20 +947,20 @@ function hook_node_info() { * corresponding to the internal name of the ranking mechanism, such as * 'recent', or 'comments'. The values should be arrays themselves, with the * following keys available: - * - "title": the human readable name of the ranking mechanism. Required. - * - "join": part of a query string to join to any additional necessary - * table. This is not necessary if the table required is already joined to - * by the base query, such as for the {node} table. Other tables should use - * the full table name as an alias to avoid naming collisions. Optional. - * - "score": part of a query string to calculate the score for the ranking - * mechanism based on values in the database. This does not need to be - * wrapped in parentheses, as it will be done automatically; it also does - * not need to take the weighted system into account, as it will be done - * automatically. It does, however, need to calculate a decimal between + * - title: (required) The human readable name of the ranking mechanism. + * - join: (optional) The part of a query string to join to any additional + * necessary table. This is not necessary if the table required is already + * joined to by the base query, such as for the {node} table. Other tables + * should use the full table name as an alias to avoid naming collisions. + * - score: (required) The part of a query string to calculate the score for + * the ranking mechanism based on values in the database. This does not need + * to be wrapped in parentheses, as it will be done automatically; it also + * does not need to take the weighted system into account, as it will be + * done automatically. It does, however, need to calculate a decimal between * 0 and 1; be careful not to cast the entire score to an integer by - * inadvertently introducing a variable argument. Required. - * - "arguments": if any arguments are required for the score, they can be - * specified in an array here. + * inadvertently introducing a variable argument. + * - arguments: (optional) If any arguments are required for the score, they + * can be specified in an array here. * * @ingroup node_api_hooks */ @@ -990,8 +987,8 @@ function hook_ranking() { /** * Respond to node type creation. * - * This hook is invoked from node_type_save() after the node type is added - * to the database. + * This hook is invoked from node_type_save() after the node type is added to + * the database. * * @param $info * The node type object that is being created. @@ -1003,8 +1000,8 @@ function hook_node_type_insert($info) { /** * Respond to node type updates. * - * This hook is invoked from node_type_save() after the node type is updated - * in the database. + * This hook is invoked from node_type_save() after the node type is updated in + * the database. * * @param $info * The node type object that is being updated. @@ -1258,25 +1255,24 @@ function hook_validate($node, $form, &$form_state) { * This hook is invoked only on the module that defines the node's content type * (use hook_node_view() to act on all node views). * - * This hook is invoked during node viewing after the node is fully loaded, - * so that the node type module can define a custom method for display, or - * add to the default display. + * This hook is invoked during node viewing after the node is fully loaded, so + * that the node type module can define a custom method for display, or add to + * the default display. * * @param $node * The node to be displayed, as returned by node_load(). * @param $view_mode * View mode, e.g. 'full', 'teaser', ... * @return - * $node. The passed $node parameter should be modified as necessary and - * returned so it can be properly presented. Nodes are prepared for display - * by assembling a structured array, formatted as in the Form API, in - * $node->content. As with Form API arrays, the #weight property can be - * used to control the relative positions of added elements. After this - * hook is invoked, node_view() calls field_attach_view() to add field - * views to $node->content, and then invokes hook_node_view() and - * hook_node_view_alter(), so if you want to affect the final - * view of the node, you might consider implementing one of these hooks - * instead. + * The passed $node parameter should be modified as necessary and returned so + * it can be properly presented. Nodes are prepared for display by assembling + * a structured array, formatted as in the Form API, in $node->content. As + * with Form API arrays, the #weight property can be used to control the + * relative positions of added elements. After this hook is invoked, + * node_view() calls field_attach_view() to add field views to $node->content, + * and then invokes hook_node_view() and hook_node_view_alter(), so if you + * want to affect the final view of the node, you might consider implementing + * one of these hooks instead. * * @ingroup node_api_hooks */ diff --git a/modules/node/node.module b/modules/node/node.module index d86c74d2d..4ab02614c 100644 --- a/modules/node/node.module +++ b/modules/node/node.module @@ -244,6 +244,12 @@ function node_field_display_node_alter(&$display, $context) { /** * Entity URI callback. + * + * @param $node + * A node entity. + * + * @return array + * An array with 'path' as the key and the path to the node as its value. */ function node_uri($node) { return array( @@ -315,8 +321,14 @@ function node_tag_new($node) { } /** - * Retrieves the timestamp at which the current user last viewed the - * specified node. + * Retrieves the timestamp for the current user's last view of a specified node. + * + * @param $nid + * A node ID. + * + * @return + * If a node has been previously viewed by the user, the timestamp in seconds + * of when the last view occurred; otherwise, zero. */ function node_last_viewed($nid) { global $user; @@ -461,6 +473,8 @@ function node_type_get_name($node) { * node_type_save(), and obsolete ones are deleted via a call to * node_type_delete(). See _node_types_build() for an explanation of the new * and obsolete types. + * + * @see _node_types_build() */ function node_types_rebuild() { _node_types_build(TRUE); @@ -761,8 +775,9 @@ function node_type_cache_reset() { * which prevents users from changing the machine name of the type. * * @param $info - * An object or array containing values to override the defaults. See - * hook_node_info() for details on what the array elements mean. + * (optional) An object or array containing values to override the defaults. + * See hook_node_info() for details on what the array elements mean. Defaults + * to an empty array. * * @return * A node type object, with missing values in $info set to their defaults. @@ -851,6 +866,7 @@ function node_rdf_mapping() { * A node object or a string containing the node type. * @param $hook * A string containing the name of the hook. + * * @return * TRUE if the $hook exists in the node type of $node. */ @@ -868,6 +884,7 @@ function node_hook($node, $hook) { * A string containing the name of the hook. * @param $a2, $a3, $a4 * Arguments to pass on to the hook, after the $node argument. + * * @return * The returned value of the invoked hook. */ @@ -883,8 +900,8 @@ function node_invoke($node, $hook, $a2 = NULL, $a3 = NULL, $a4 = NULL) { * Load node entities from the database. * * This function should be used whenever you need to load more than one node - * from the database. Nodes are loaded into memory and will not require - * database access if loaded again during the same page request. + * from the database. Nodes are loaded into memory and will not require database + * access if loaded again during the same page request. * * @see entity_load() * @see EntityFieldQuery @@ -934,6 +951,9 @@ function node_load($nid = NULL, $vid = NULL, $reset = FALSE) { * * Fills in a few default values, and then invokes hook_prepare() on the node * type module, and hook_node_prepare() on all modules. + * + * @param $node + * A node object. */ function node_object_prepare($node) { // Set up default values, if required. @@ -1159,6 +1179,13 @@ function node_save($node) { * Helper function to save a revision with the uid of the current user. * * The resulting revision ID is available afterward in $node->vid. + * + * @param $node + * A node object. + * @param $uid + * The current user's UID. + * @param $update + * (optional) An array of primary keys' field names to update. */ function _node_save_revision($node, $uid, $update = NULL) { $temp_uid = $node->uid; @@ -1406,6 +1433,7 @@ function node_build_content($node, $view_mode = 'full', $langcode = NULL) { * A node object. * @param $message * A flag which sets a page title relevant to the revision being viewed. + * * @return * A $page element suitable for use by drupal_render(). */ @@ -1428,6 +1456,9 @@ function node_show($node, $message = FALSE) { * * @param $node * A node object. + * + * @return + * The ID of the node if this is a full page view, otherwise FALSE. */ function node_is_page($node) { $page_node = menu_get_object(); @@ -1893,6 +1924,14 @@ function _node_revision_access($node, $op = 'view', $account = NULL) { return $access[$cid]; } +/** + * Access callback: Checks whether the user has permission to add a node. + * + * @return + * TRUE if the user has add permission, otherwise FALSE. + * + * @see node_menu() + */ function _node_add_access() { $types = node_type_get_types(); foreach ($types as $type) { @@ -2111,6 +2150,14 @@ function node_menu_local_tasks_alter(&$data, $router_item, $root_path) { /** * Title callback for a node type. + * + * @param $type + * The node type object. + * + * @return string + * An unsanitized string that is the title of the node type edit form. + * + * @see node_menu() */ function node_type_page_title($type) { return $type->name; @@ -2118,6 +2165,14 @@ function node_type_page_title($type) { /** * Title callback. + * + * @param $node + * The node object. + * + * @return + * An unsanitized string that is the title of the node. + * + * @see node_menu() */ function node_page_title($node) { return $node->title; @@ -2138,6 +2193,12 @@ function node_last_changed($nid) { /** * Return a list of all the existing revision numbers. + * + * @param Drupal\node\Node $node + * The node entity. + * + * @return + * An associative array keyed by node revision number. */ function node_revision_list($node) { $revisions = array(); @@ -2223,8 +2284,8 @@ function node_block_save($delta = '', $edit = array()) { * (optional) The maximum number of nodes to find. Defaults to 10. * * @return - * An array of partial node objects or an empty array if there are no recent - * nodes visible to the current user. + * An array of node entities or an empty array if there are no recent nodes + * visible to the current user. */ function node_get_recent($number = 10) { $query = db_select('node', 'n'); @@ -2568,8 +2629,8 @@ function node_feed($nids = FALSE, $channel = array()) { * @param $weight * An integer representing the weight of the first node in the list. * @param $langcode - * (optional) A language code to use for rendering. Defaults to the global - * content language of the current request. + * (optional) A language code to use for rendering. Defaults to NULL which is + * the global content language of the current request. * * @return * An array in the format expected by drupal_render(). @@ -2589,6 +2650,11 @@ function node_view_multiple($nodes, $view_mode = 'teaser', $weight = 0, $langcod /** * Menu callback; Generate a listing of promoted nodes. + * + * @return array + * An array in the format expected by drupal_render(). + * + * @see node_menu() */ function node_page_default() { $select = db_select('node', 'n') @@ -2639,6 +2705,14 @@ function node_page_default() { /** * Menu callback; view a single node. + * + * @param $node + * The node object. + * + * @return + * A page array suitable for use by drupal_render(). + * + * @see node_menu() */ function node_page_view($node) { // If there is a menu link to this node, the link becomes the last part @@ -2819,8 +2893,8 @@ function node_search_validate($form, &$form_state) { * @{ * The node access system determines who can do what to which nodes. * - * In determining access rights for a node, node_access() first checks - * whether the user has the "bypass node access" permission. Such users have + * In determining access rights for a node, node_access() first checks whether + * the user has the "bypass node access" permission. Such users have * unrestricted access to all nodes. user 1 will always pass this check. * * Next, all implementations of hook_node_access() will be called. Each @@ -3005,6 +3079,7 @@ function node_node_access($node, $op, $account) { * * @param $type * The machine-readable name of the node type. + * * @return array * An array of permission names and descriptions. */ @@ -3038,11 +3113,11 @@ function node_list_permissions($type) { * * By default, this will include all node types in the system. To exclude a * specific node from getting permissions defined for it, set the - * node_permissions_$type variable to 0. Core does not provide an interface - * for doing so, however, contrib modules may exclude their own nodes in + * node_permissions_$type variable to 0. Core does not provide an interface for + * doing so. However, contrib modules may exclude their own nodes in * hook_install(). Alternatively, contrib modules may configure all node types - * at once, or decide to apply some other hook_node_access() implementation - * to some or all node types. + * at once, or decide to apply some other hook_node_access() implementation to + * some or all node types. * * @return * An array of node types managed by this module. @@ -3064,18 +3139,19 @@ function node_permissions_get_configured_types() { * Fetch an array of permission IDs granted to the given user ID. * * The implementation here provides only the universal "all" grant. A node - * access module should implement hook_node_grants() to provide a grant - * list for the user. + * access module should implement hook_node_grants() to provide a grant list for + * the user. * - * After the default grants have been loaded, we allow modules to alter - * the grants array by reference. This hook allows for complex business - * logic to be applied when integrating multiple node access modules. + * After the default grants have been loaded, we allow modules to alter the + * grants array by reference. This hook allows for complex business logic to be + * applied when integrating multiple node access modules. * * @param $op * The operation that the user is trying to perform. * @param $account * The user object for the user performing the operation. If omitted, the * current user is used. + * * @return * An associative array in which the keys are realms, and the values are * arrays of grants for those realms. @@ -3163,11 +3239,10 @@ function node_access_view_all_nodes($account = NULL) { /** * Implements hook_query_TAG_alter(). * - * This is the hook_query_alter() for queries tagged with 'node_access'. - * It adds node access checks for the user account given by the 'account' - * meta-data (or global $user if not provided), for an operation given by - * the 'op' meta-data (or 'view' if not provided; other possible values are - * 'update' and 'delete'). + * This is the hook_query_alter() for queries tagged with 'node_access'. It adds + * node access checks for the user account given by the 'account' meta-data (or + * global $user if not provided), for an operation given by the 'op' meta-data + * (or 'view' if not provided; other possible values are 'update' and 'delete'). */ function node_query_node_access_alter(QueryAlterableInterface $query) { _node_query_node_access_alter($query, 'node'); @@ -3206,8 +3281,8 @@ function _node_query_node_access_alter($query, $type) { } // If $account can bypass node access, or there are no node access modules, - // or the operation is 'view' and the $acount has a global view grant (i.e., - // a view grant for node ID 0), we don't need to alter the query. + // or the operation is 'view' and the $account has a global view grant + // (such as a view grant for node ID 0), we don't need to alter the query. if (user_access('bypass node access', $account)) { return; } @@ -3394,15 +3469,14 @@ function node_access_acquire_grants($node, $delete = TRUE) { * * If a realm is provided, it will only delete grants from that realm, but it * will always delete a grant from the 'all' realm. Modules that utilize - * node_access can use this function when doing mass updates due to widespread + * node_access() can use this function when doing mass updates due to widespread * permission changes. * * Note: Don't call this function directly from a contributed module. Call * node_access_acquire_grants() instead. * * @param $node - * The $node being written to. All that is necessary is that it contains a - * nid. + * The node whose grants are being written. * @param $grants * A list of grants to write. Each grant is an array that must contain the * following keys: realm, gid, grant_view, grant_update, grant_delete. @@ -3410,10 +3484,14 @@ function node_access_acquire_grants($node, $delete = TRUE) { * is a module-defined id to define grant privileges. each grant_* field * is a boolean value. * @param $realm - * If provided, only read/write grants for that realm. + * (optional) If provided, read/write grants for that realm only. Defaults to + * NULL. * @param $delete - * If false, do not delete records. This is only for optimization purposes, - * and assumes the caller has already performed a mass delete of some form. + * (optional) If false, does not delete records. This is only for optimization + * purposes, and assumes the caller has already performed a mass delete of + * some form. Defaults to TRUE. + * + * @see node_access_acquire_grants() */ function node_access_write_grants($node, $grants, $realm = NULL, $delete = TRUE) { if ($delete) { @@ -3450,13 +3528,16 @@ function node_access_write_grants($node, $grants, $realm = NULL, $delete = TRUE) * This can be used as an alternative to direct node_access_rebuild calls, * allowing administrators to decide when they want to perform the actual * (possibly time consuming) rebuild. - * When unsure the current user is an administrator, node_access_rebuild + * When unsure if the current user is an administrator, node_access_rebuild() * should be used instead. * * @param $rebuild * (Optional) The boolean value to be written. - * @return - * (If no value was provided for $rebuild) The current value of the flag. + * + * @return + * The current value of the flag if no value was provided for $rebuild. + * + * @see node_access_rebuild() */ function node_access_needs_rebuild($rebuild = NULL) { if (!isset($rebuild)) { @@ -3543,11 +3624,14 @@ function node_access_rebuild($batch_mode = FALSE) { } /** - * Batch operation for node_access_rebuild_batch. + * Performs batch operation for node_access_rebuild(). * - * This is a multistep operation : we go through all nodes by packs of 20. - * The batch processing engine interrupts processing and sends progress - * feedback after 1 second execution time. + * This is a multistep operation: we go through all nodes by packs of 20. The + * batch processing engine interrupts processing and sends progress feedback + * after 1 second execution time. + * + * @param array $context + * An array of contextual key/value information for rebuild batch process. */ function _node_access_rebuild_batch_operation(&$context) { if (empty($context['sandbox'])) { @@ -3578,7 +3662,14 @@ function _node_access_rebuild_batch_operation(&$context) { } /** - * Post-processing for node_access_rebuild_batch. + * Performs post-processing for node_access_rebuild(). + * + * @param bool $success + * A boolean indicating whether the re-build process has completed. + * @param array $results + * An array of results information. + * @param array $operations + * An array of function calls (not used in this function). */ function _node_access_rebuild_batch_finished($success, $results, $operations) { if ($success) { @@ -3631,6 +3722,7 @@ function node_content_form($node, $form_state) { /** * Implements hook_forms(). + * * All node forms share the same form handler. */ function node_forms() { @@ -3715,6 +3807,12 @@ function node_action_info() { /** * Sets the status of a node to 1 (published). * + * @param $node + * A node object. + * @param $context + * (optional) Array of additional information about what triggered the action. + * Not used for this action. + * * @ingroup actions */ function node_publish_action($node, $context = array()) { @@ -3725,6 +3823,12 @@ function node_publish_action($node, $context = array()) { /** * Sets the status of a node to 0 (unpublished). * + * @param $node + * A node object. + * @param $context + * (optional) Array of additional information about what triggered the action. + * Not used for this action. + * * @ingroup actions */ function node_unpublish_action($node, $context = array()) { @@ -3735,6 +3839,12 @@ function node_unpublish_action($node, $context = array()) { /** * Sets the sticky-at-top-of-list property of a node to 1. * + * @param $node + * A node object. + * @param $context + * (optional) Array of additional information about what triggered the action. + * Not used for this action. + * * @ingroup actions */ function node_make_sticky_action($node, $context = array()) { @@ -3745,6 +3855,12 @@ function node_make_sticky_action($node, $context = array()) { /** * Sets the sticky-at-top-of-list property of a node to 0. * + * @param $node + * A node object. + * @param $context + * (optional) Array of additional information about what triggered the action. + * Not used for this action. + * * @ingroup actions */ function node_make_unsticky_action($node, $context = array()) { @@ -3755,6 +3871,12 @@ function node_make_unsticky_action($node, $context = array()) { /** * Sets the promote property of a node to 1. * + * @param $node + * A node object. + * @param $context + * (optional) Array of additional information about what triggered the action. + * Not used for this action. + * * @ingroup actions */ function node_promote_action($node, $context = array()) { @@ -3765,6 +3887,12 @@ function node_promote_action($node, $context = array()) { /** * Sets the promote property of a node to 0. * + * @param $node + * A node object. + * @param $context + * (optional) Array of additional information about what triggered the action. + * Not used for this action. + * * @ingroup actions */ function node_unpromote_action($node, $context = array()) { @@ -3775,6 +3903,9 @@ function node_unpromote_action($node, $context = array()) { /** * Saves a node. * + * @param $node + * The node to be saved. + * * @ingroup actions */ function node_save_action($node) { @@ -3791,6 +3922,9 @@ function node_save_action($node) { * Array with the following elements: * - 'owner_uid': User ID to assign to the node. * + * @see node_assign_owner_action_form() + * @see node_assign_owner_action_validate() + * @see node_assign_owner_action_submit() * @ingroup actions */ function node_assign_owner_action($node, $context) { @@ -3801,6 +3935,16 @@ function node_assign_owner_action($node, $context) { /** * Generates the settings form for node_assign_owner_action(). + * + * @param $context + * Array of additional information about what triggered the action. Includes + * the following elements: + * - 'owner_uid': User ID to assign to the node. + * + * @see node_assign_owner_action_submit() + * @see node_assign_owner_action_validate() + * + * @ingroup forms */ function node_assign_owner_action_form($context) { $description = t('The username of the user to which you would like to assign ownership.'); @@ -3841,6 +3985,8 @@ function node_assign_owner_action_form($context) { /** * Validates settings form for node_assign_owner_action(). + * + * @see node_assign_owner_action_submit() */ function node_assign_owner_action_validate($form, $form_state) { $exists = (bool) db_query_range('SELECT 1 FROM {users} WHERE name = :name', 0, 1, array(':name' => $form_state['values']['owner_name']))->fetchField(); @@ -3851,6 +3997,8 @@ function node_assign_owner_action_validate($form, $form_state) { /** * Saves settings form for node_assign_owner_action(). + * + * @see node_assign_owner_action_validate() */ function node_assign_owner_action_submit($form, $form_state) { // Username can change, so we need to store the ID, not the username. @@ -3860,6 +4008,14 @@ function node_assign_owner_action_submit($form, $form_state) { /** * Generates settings form for node_unpublish_by_keyword_action(). + * + * @param array $context + * Array of additional information about what triggered this action. + * + * @return array + * A form array. + * + * @see node_unpublish_by_keyword_action_submit() */ function node_unpublish_by_keyword_action_form($context) { $form['keywords'] = array( diff --git a/modules/node/node.pages.inc b/modules/node/node.pages.inc index c6cb1bcc2..dee92e16c 100644 --- a/modules/node/node.pages.inc +++ b/modules/node/node.pages.inc @@ -5,7 +5,6 @@ * Page callbacks for adding, editing, deleting, and revisions management for content. */ - /** * Menu callback; presents the node editing form. */ @@ -63,6 +62,12 @@ function theme_node_add_list($variables) { /** * Returns a node submission form. + * + * @param $type + * The node type for the submitted node. + * + * @return + * The themed form. */ function node_add($type) { global $user; @@ -75,6 +80,12 @@ function node_add($type) { return $output; } +/** + * Form validation handler for node_form(). + * + * @see node_form() + * @see node_form_submit() + */ function node_form_validate($form, &$form_state) { // $form_state['node'] contains the actual entity being edited, but we must // not update it with form values that have not yet been validated, so we @@ -85,7 +96,13 @@ function node_form_validate($form, &$form_state) { } /** - * Generate the node add/edit form array. + * Form constructor for the node add/edit form. + * + * @see node_form_validate() + * @see node_form_submit() + * @see node_form_build_preview() + * @see node_form_delete_submit() + * @ingroup forms */ function node_form($form, &$form_state, $node) { global $user; @@ -311,7 +328,12 @@ function node_form($form, &$form_state, $node) { } /** - * Button submit function: handle the 'Delete' button on the node form. + * Form submission handler for node_form(). + * + * Handles the 'Delete' button on the node form. + * + * @see node_form() + * @see node_form_validate() */ function node_form_delete_submit($form, &$form_state) { $destination = array(); @@ -323,7 +345,14 @@ function node_form_delete_submit($form, &$form_state) { $form_state['redirect'] = array('node/' . $node->nid . '/delete', array('query' => $destination)); } - +/** + * Form submission handler for node_form(). + * + * Handles the 'Preview' button on the node form. + * + * @see node_form() + * @see node_form_validate() + */ function node_form_build_preview($form, &$form_state) { $node = node_form_submit_build_node($form, $form_state); $form_state['node_preview'] = node_preview($node); @@ -331,7 +360,15 @@ function node_form_build_preview($form, &$form_state) { } /** - * Generate a node preview. + * Generates a node preview. + * + * @param $node + * The node to preview. + * + * @return + * An HTML-formatted string of a node preview. + * + * @see node_form_build_preview() */ function node_preview($node) { if (node_access('create', $node) || node_access('update', $node)) { @@ -377,6 +414,7 @@ function node_preview($node) { * An associative array containing: * - node: The node object which is being previewed. * + * @see node_preview() * @ingroup themeable */ function theme_node_preview($variables) { @@ -407,6 +445,12 @@ function theme_node_preview($variables) { return $output; } +/** + * Form submission handler for node_form(). + * + * @see node_form() + * @see node_form_validate() + */ function node_form_submit($form, &$form_state) { $node = node_form_submit_build_node($form, $form_state); $insert = empty($node->nid); @@ -472,7 +516,9 @@ function node_form_submit_build_node($form, &$form_state) { } /** - * Menu callback -- ask for confirmation of node deletion + * Form constructor for the node deletion confirmation form. + * + * @see node_delete_confirm_submit() */ function node_delete_confirm($form, &$form_state, $node) { $form['#node'] = $node; @@ -488,7 +534,9 @@ function node_delete_confirm($form, &$form_state, $node) { } /** - * Execute node deletion + * Executes node deletion. + * + * @see node_delete_confirm() */ function node_delete_confirm_submit($form, &$form_state) { if ($form_state['values']['confirm']) { @@ -502,7 +550,15 @@ function node_delete_confirm_submit($form, &$form_state) { } /** - * Generate an overview table of older revisions of a node. + * Generates an overview table of older revisions of a node. + * + * @param $node + * A node object. + * + * @return array + * An array as expected by drupal_render(). + * + * @see node_menu() */ function node_revision_overview($node) { drupal_set_title(t('Revisions for %title', array('%title' => $node->title)), PASS_THROUGH); @@ -553,13 +609,26 @@ function node_revision_overview($node) { } /** - * Ask for confirmation of the reversion to prevent against CSRF attacks. + * Asks for confirmation of the reversion to prevent against CSRF attacks. + * + * @param int $node_revision + * The node revision ID. + * + * @return array + * An array as expected by drupal_render(). + * + * @see node_menu() + * @see node_revision_revert_confirm_submit() + * @ingroup forms */ function node_revision_revert_confirm($form, $form_state, $node_revision) { $form['#node_revision'] = $node_revision; return confirm_form($form, t('Are you sure you want to revert to the revision from %revision-date?', array('%revision-date' => format_date($node_revision->revision_timestamp))), 'node/' . $node_revision->nid . '/revisions', '', t('Revert'), t('Cancel')); } +/** + * Form submission handler for node_revision_revert_confirm(). + */ function node_revision_revert_confirm_submit($form, &$form_state) { $node_revision = $form['#node_revision']; $node_revision->revision = 1; @@ -572,11 +641,29 @@ function node_revision_revert_confirm_submit($form, &$form_state) { $form_state['redirect'] = 'node/' . $node_revision->nid . '/revisions'; } +/** + * Form constructor for the revision deletion confirmation form. + * + * This form prevents against CSRF attacks. + * + * @param $node_revision + * The node revision ID. + * + * @return + * An array as expected by drupal_render(). + * + * @see node_menu() + * @see node_revision_delete_confirm_submit() + * @ingroup forms + */ function node_revision_delete_confirm($form, $form_state, $node_revision) { $form['#node_revision'] = $node_revision; return confirm_form($form, t('Are you sure you want to delete the revision from %revision-date?', array('%revision-date' => format_date($node_revision->revision_timestamp))), 'node/' . $node_revision->nid . '/revisions', t('This action cannot be undone.'), t('Delete'), t('Cancel')); } +/** + * Form submission handler for node_revision_delete_confirm(). + */ function node_revision_delete_confirm_submit($form, &$form_state) { $node_revision = $form['#node_revision']; node_revision_delete($node_revision->vid); diff --git a/modules/node/node.test b/modules/node/node.test index d789d3c0e..2180f5838 100644 --- a/modules/node/node.test +++ b/modules/node/node.test @@ -149,6 +149,9 @@ class NodeLoadHooksTestCase extends DrupalWebTestCase { } } +/** + * Tests the node revision functionality. + */ class NodeRevisionsTestCase extends DrupalWebTestCase { protected $nodes; protected $logs; @@ -198,7 +201,7 @@ class NodeRevisionsTestCase extends DrupalWebTestCase { } /** - * Check node revision related operations. + * Checks node revision related operations. */ function testRevisions() { $nodes = $this->nodes; @@ -282,6 +285,9 @@ class NodeRevisionsTestCase extends DrupalWebTestCase { } } +/** + * Tests the node edit functionality. + */ class PageEditTestCase extends DrupalWebTestCase { protected $web_user; protected $admin_user; @@ -302,7 +308,7 @@ class PageEditTestCase extends DrupalWebTestCase { } /** - * Check node edit functionality. + * Checks node edit functionality. */ function testPageEdit() { $this->drupalLogin($this->web_user); @@ -369,7 +375,7 @@ class PageEditTestCase extends DrupalWebTestCase { } /** - * Check changing node authored by fields. + * Tests changing a node's "authored by" field. */ function testPageAuthoredBy() { $this->drupalLogin($this->admin_user); @@ -414,6 +420,9 @@ class PageEditTestCase extends DrupalWebTestCase { } } +/** + * Tests the node entity preview functionality. + */ class PagePreviewTestCase extends DrupalWebTestCase { public static function getInfo() { return array( @@ -431,7 +440,7 @@ class PagePreviewTestCase extends DrupalWebTestCase { } /** - * Check the node preview functionality. + * Checks the node preview functionality. */ function testPagePreview() { $langcode = LANGUAGE_NONE; @@ -455,7 +464,7 @@ class PagePreviewTestCase extends DrupalWebTestCase { } /** - * Check the node preview functionality, when using revisions. + * Checks the node preview functionality, when using revisions. */ function testPagePreviewWithRevisions() { $langcode = LANGUAGE_NONE; @@ -485,6 +494,9 @@ class PagePreviewTestCase extends DrupalWebTestCase { } } +/** + * Tests creating and saving a node. + */ class NodeCreationTestCase extends DrupalWebTestCase { public static function getInfo() { return array( @@ -503,7 +515,7 @@ class NodeCreationTestCase extends DrupalWebTestCase { } /** - * Create a "Basic page" node and verify its consistency in the database. + * Creates a "Basic page" node and verifies its consistency in the database. */ function testNodeCreation() { // Create a node. @@ -522,7 +534,7 @@ class NodeCreationTestCase extends DrupalWebTestCase { } /** - * Create a page node and verify that a transaction rolls back the failed creation + * Verifies that a transaction rolls back the failed creation. */ function testFailedPageCreation() { // Create a node. @@ -563,6 +575,9 @@ class NodeCreationTestCase extends DrupalWebTestCase { } } +/** + * Tests the functionality of node entity edit permissions. + */ class PageViewTestCase extends DrupalWebTestCase { public static function getInfo() { return array( @@ -573,7 +588,7 @@ class PageViewTestCase extends DrupalWebTestCase { } /** - * Creates a node and then an anonymous and unpermissioned user attempt to edit the node. + * Tests an anonymous and unpermissioned user attempting to edit the node. */ function testPageView() { // Create a node to view. @@ -602,6 +617,9 @@ class PageViewTestCase extends DrupalWebTestCase { } } +/** + * Tests the summary length functionality. + */ class SummaryLengthTestCase extends DrupalWebTestCase { public static function getInfo() { return array( @@ -612,7 +630,7 @@ class SummaryLengthTestCase extends DrupalWebTestCase { } /** - * Creates a node and then an anonymous and unpermissioned user attempt to edit the node. + * Tests the node summary length functionality. */ function testSummaryLength() { // Create a node to view. @@ -644,6 +662,9 @@ class SummaryLengthTestCase extends DrupalWebTestCase { } } +/** + * Tests XSS functionality with a node entity. + */ class NodeTitleXSSTestCase extends DrupalWebTestCase { public static function getInfo() { return array( @@ -653,6 +674,9 @@ class NodeTitleXSSTestCase extends DrupalWebTestCase { ); } + /** + * Tests XSS functionality with a node entity. + */ function testNodeTitleXSS() { // Prepare a user to do the stuff. $web_user = $this->drupalCreateUser(array('create page content', 'edit any page content')); @@ -678,6 +702,9 @@ class NodeTitleXSSTestCase extends DrupalWebTestCase { } } +/** + * Tests the availability of the syndicate block. + */ class NodeBlockTestCase extends DrupalWebTestCase { public static function getInfo() { return array( @@ -709,7 +736,7 @@ class NodeBlockTestCase extends DrupalWebTestCase { } /** - * Check that the post information displays when enabled for a content type. + * Checks that the post information displays when enabled for a content type. */ class NodePostSettingsTestCase extends DrupalWebTestCase { public static function getInfo() { @@ -728,7 +755,7 @@ class NodePostSettingsTestCase extends DrupalWebTestCase { } /** - * Set "Basic page" content type to display post information and confirm its presence on a new node. + * Confirms "Basic page" content type and post information is on a new node. */ function testPagePostInfo() { @@ -751,7 +778,7 @@ class NodePostSettingsTestCase extends DrupalWebTestCase { } /** - * Set "Basic page" content type to not display post information and confirm its absence on a new node. + * Confirms absence of post information on a new node. */ function testPageNotPostInfo() { @@ -774,7 +801,7 @@ class NodePostSettingsTestCase extends DrupalWebTestCase { } /** - * Ensure that data added to nodes by other modules appears in RSS feeds. + * Ensures that data added to nodes by other modules appears in RSS feeds. * * Create a node, enable the node_test module to ensure that extra data is * added to the node->content array, then verify that the data appears on the @@ -801,8 +828,7 @@ class NodeRSSContentTestCase extends DrupalWebTestCase { } /** - * Create a new node and ensure that it includes the custom data when added - * to an RSS feed. + * Ensures that a new node includes the custom data when added to an RSS feed. */ function testNodeRSSContent() { // Create a node. @@ -841,9 +867,11 @@ class NodeRSSContentTestCase extends DrupalWebTestCase { } /** - * Test case to verify basic node_access functionality. + * Tests basic node_access functionality. + * + * Note that hook_node_access_records() is covered in another test class. + * * @todo Cover hook_node_access in a separate test class. - * hook_node_access_records is covered in another test class. */ class NodeAccessTestCase extends DrupalWebTestCase { public static function getInfo() { @@ -855,7 +883,7 @@ class NodeAccessTestCase extends DrupalWebTestCase { } /** - * Asserts node_access correctly grants or denies access. + * Asserts node_access() correctly grants or denies access. */ function assertNodeAccess($ops, $node, $account) { foreach ($ops as $op => $result) { @@ -910,7 +938,7 @@ class NodeAccessTestCase extends DrupalWebTestCase { } /** - * Test case to verify hook_node_access_records functionality. + * Tests hook_node_access_records() functionality. */ class NodeAccessRecordsTestCase extends DrupalWebTestCase { public static function getInfo() { @@ -929,7 +957,7 @@ class NodeAccessRecordsTestCase extends DrupalWebTestCase { } /** - * Create a node and test the creation of node access rules. + * Creates a node and tests the creation of node access rules. */ function testNodeAccessRecords() { // Create an article node. @@ -1005,9 +1033,6 @@ class NodeAccessBaseTableTestCase extends DrupalWebTestCase { ); } - /** - * Enable modules and create user with specific permissions. - */ public function setUp() { parent::setUp('node_access_test'); node_access_rebuild(); @@ -1015,7 +1040,7 @@ class NodeAccessBaseTableTestCase extends DrupalWebTestCase { } /** - * Test the "private" node access. + * Tests the "private" node access functionality. * * - Create 2 users with "access content" and "create article" permissions. * - Each user creates one private and one not private article. @@ -1152,7 +1177,7 @@ class NodeAccessBaseTableTestCase extends DrupalWebTestCase { } /** - * Test case to check node save related functionality, including import-save + * Tests node save related functionality, including import-save. */ class NodeSaveTestCase extends DrupalWebTestCase { @@ -1173,7 +1198,8 @@ class NodeSaveTestCase extends DrupalWebTestCase { } /** - * Import test, to check if custom node ids are saved properly. + * Checks whether custom node IDs are saved properly during an import operation. + * * Workflow: * - first create a piece of content * - save the content @@ -1207,8 +1233,7 @@ class NodeSaveTestCase extends DrupalWebTestCase { } /** - * Check that the "created" and "changed" timestamps are set correctly when - * saving a new node or updating an existing node. + * Verifies accuracy of the "created" and "changed" timestamp functionality. */ function testTimestamps() { // Use the default timestamps. @@ -1307,7 +1332,7 @@ class NodeTypeTestCase extends DrupalWebTestCase { } /** - * Ensure that node type functions (node_type_get_*) work correctly. + * Ensures that node type functions (node_type_get_*) work correctly. * * Load available node types and validate the returned data. */ @@ -1326,7 +1351,7 @@ class NodeTypeTestCase extends DrupalWebTestCase { } /** - * Test creating a content type programmatically and via a form. + * Tests creating a content type programmatically and via a form. */ function testNodeTypeCreation() { // Create a content type programmaticaly. @@ -1356,7 +1381,7 @@ class NodeTypeTestCase extends DrupalWebTestCase { } /** - * Test editing a node type using the UI. + * Tests editing a node type using the UI. */ function testNodeTypeEditing() { $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types')); @@ -1409,7 +1434,7 @@ class NodeTypeTestCase extends DrupalWebTestCase { } /** - * Test that node_types_rebuild() correctly handles the 'disabled' flag. + * Tests that node_types_rebuild() correctly handles the 'disabled' flag. */ function testNodeTypeStatus() { // Enable all core node modules, and all types should be active. @@ -1470,7 +1495,7 @@ class NodeTypePersistenceTestCase extends DrupalWebTestCase { } /** - * Test node type customizations persist through disable and uninstall. + * Tests that node type customizations persist through disable and uninstall. */ function testNodeTypeCustomizationPersistence() { $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types', 'administer modules')); @@ -1534,7 +1559,7 @@ class NodeTypePersistenceTestCase extends DrupalWebTestCase { } /** - * Rebuild the node_access table. + * Verifies the rebuild functionality for the node_access table. */ class NodeAccessRebuildTestCase extends DrupalWebTestCase { public static function getInfo() { @@ -1553,6 +1578,9 @@ class NodeAccessRebuildTestCase extends DrupalWebTestCase { $this->web_user = $web_user; } + /** + * Tests rebuilding the node access permissions table. + */ function testNodeAccessRebuild() { $this->drupalGet('admin/reports/status'); $this->clickLink(t('Rebuild permissions')); @@ -1562,7 +1590,7 @@ class NodeAccessRebuildTestCase extends DrupalWebTestCase { } /** - * Test node administration page functionality. + * Tests node administration page functionality. */ class NodeAdminTestCase extends DrupalWebTestCase { public static function getInfo() { @@ -1630,6 +1658,7 @@ class NodeAdminTestCase extends DrupalWebTestCase { * Tests content overview with different user permissions. * * Taxonomy filters are tested separately. + * * @see TaxonomyNodeFilterTestCase */ function testContentAdminPages() { @@ -1727,7 +1756,7 @@ class NodeAdminTestCase extends DrupalWebTestCase { } /** - * Test node title. + * Tests node title functionality. */ class NodeTitleTestCase extends DrupalWebTestCase { protected $admin_user; @@ -1747,7 +1776,7 @@ class NodeTitleTestCase extends DrupalWebTestCase { } /** - * Create one node and test if the node title has the correct value. + * Creates one node and tests if the node title has the correct value. */ function testNodeTitle() { // Create "Basic page" content with title. @@ -1790,7 +1819,7 @@ class NodeFeedTestCase extends DrupalWebTestCase { } /** - * Ensure that node_feed accepts and prints extra channel elements. + * Ensures that node_feed() accepts and prints extra channel elements. */ function testNodeFeedExtraChannelElements() { ob_start(); @@ -1822,7 +1851,7 @@ class NodeBlockFunctionalTest extends DrupalWebTestCase { } /** - * Test the recent comments block. + * Tests the recent comments block. */ function testRecentNodeBlock() { $this->drupalLogin($this->admin_user); @@ -1935,7 +1964,7 @@ class NodeBlockFunctionalTest extends DrupalWebTestCase { } } /** - * Test multistep node forms basic options. + * Tests basic options of multi-step node forms. */ class MultiStepNodeFormBasicOptionsTest extends DrupalWebTestCase { public static function getInfo() { @@ -1953,7 +1982,7 @@ class MultiStepNodeFormBasicOptionsTest extends DrupalWebTestCase { } /** - * Change the default values of basic options to ensure they persist. + * Tests changing the default values of basic options to ensure they persist. */ function testMultiStepNodeFormBasicOptions() { $edit = array( @@ -1985,7 +2014,7 @@ class NodeBuildContent extends DrupalWebTestCase { } /** - * Test to ensure that a node's content array is rebuilt on every call to node_build_content(). + * Ensures that content array is rebuilt on every call to node_build_content(). */ function testNodeRebuildContent() { $node = $this->drupalCreateNode(); @@ -2065,10 +2094,10 @@ class NodeQueryAlter extends DrupalWebTestCase { } /** - * Lower-level test of 'node_access' query alter, for user with access. + * Tests 'node_access' query alter, for user with access. * - * Verifies that a non-standard table alias can be used, and that a - * user with node access can view the nodes. + * Verifies that a non-standard table alias can be used, and that a user with + * node access can view the nodes. */ function testNodeQueryAlterLowLevelWithAccess() { // User with access should be able to view 4 nodes. @@ -2088,10 +2117,10 @@ class NodeQueryAlter extends DrupalWebTestCase { } /** - * Lower-level test of 'node_access' query alter, for user without access. + * Tests 'node_access' query alter, for user without access. * - * Verifies that a non-standard table alias can be used, and that a - * user without node access cannot view the nodes. + * Verifies that a non-standard table alias can be used, and that a user + * without node access cannot view the nodes. */ function testNodeQueryAlterLowLevelNoAccess() { // User without access should be able to view 0 nodes. @@ -2111,10 +2140,10 @@ class NodeQueryAlter extends DrupalWebTestCase { } /** - * Lower-level test of 'node_access' query alter, for edit access. + * Tests 'node_access' query alter, for edit access. * - * Verifies that a non-standard table alias can be used, and that a - * user with view-only node access cannot edit the nodes. + * Verifies that a non-standard table alias can be used, and that a user with + * view-only node access cannot edit the nodes. */ function testNodeQueryAlterLowLevelEditAccess() { // User with view-only access should not be able to edit nodes. @@ -2136,13 +2165,13 @@ class NodeQueryAlter extends DrupalWebTestCase { } /** - * Lower-level test of 'node_access' query alter override. + * Tests 'node_access' query alter override. * * Verifies that node_access_view_all_nodes() is called from - * node_query_node_access_alter(). We do this by checking that - * a user which normally would not have view privileges is able - * to view the nodes when we add a record to {node_access} paired - * with a corresponding privilege in hook_node_grants(). + * node_query_node_access_alter(). We do this by checking that a user who + * normally would not have view privileges is able to view the nodes when we + * add a record to {node_access} paired with a corresponding privilege in + * hook_node_grants(). */ function testNodeQueryAlterOverride() { $record = array( diff --git a/modules/node/tests/node_access_test.module b/modules/node/tests/node_access_test.module index 813bf929b..ec35c41f1 100644 --- a/modules/node/tests/node_access_test.module +++ b/modules/node/tests/node_access_test.module @@ -2,7 +2,9 @@ /** * @file - * Dummy module implementing node access related hooks to test API interaction + * A dummy module implementing node access related hooks for testing purposes. + * + * A dummy module implementing node access related hooks to test API interaction * with the Node module. This module restricts view permission to those with * a special 'node test view' permission. */ @@ -140,6 +142,8 @@ function node_access_test_page() { * database query is shown, and a list of the node IDs, for debugging purposes. * And if there is a query exception, the page says "Exception" and gives the * error. + * + * @see node_access_test_menu() */ function node_access_entity_test_page() { $output = ''; diff --git a/modules/node/tests/node_test.module b/modules/node/tests/node_test.module index a52c1fad0..fb6678521 100644 --- a/modules/node/tests/node_test.module +++ b/modules/node/tests/node_test.module @@ -2,8 +2,10 @@ /** * @file - * Dummy module implementing node related hooks to test API interaction with - * the Node module. + * A dummy module for testing node related hooks. + * + * This is a dummy module that implements node related hooks to test API + * interaction with the Node module. */ /** diff --git a/modules/node/tests/node_test_exception.module b/modules/node/tests/node_test_exception.module index 0fe9f35ea..66bc71747 100644 --- a/modules/node/tests/node_test_exception.module +++ b/modules/node/tests/node_test_exception.module @@ -2,8 +2,7 @@ /** * @file - * Dummy module implementing node related hooks to test API interaction with - * the Node module. + * A module implementing node related hooks to test API interaction. */ /** diff --git a/modules/simpletest/drupal_web_test_case.php b/modules/simpletest/drupal_web_test_case.php index e3cab62a2..694880b91 100644 --- a/modules/simpletest/drupal_web_test_case.php +++ b/modules/simpletest/drupal_web_test_case.php @@ -3149,6 +3149,42 @@ class DrupalWebTestCase extends DrupalTestCase { } /** + * Asserts themed output. + * + * @param $callback + * The name of the theme function to invoke; e.g. 'links' for theme_links(). + * @param $variables + * An array of variables to pass to the theme function. + * @param $expected + * The expected themed output string. + * @param $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return + * TRUE on pass, FALSE on fail. + */ + protected function assertThemeOutput($callback, array $variables = array(), $expected, $message = '', $group = 'Other') { + $output = theme($callback, $variables); + $this->verbose('Variables:' . '<pre>' . check_plain(var_export($variables, TRUE)) . '</pre>' + . '<hr />' . 'Result:' . '<pre>' . check_plain(var_export($output, TRUE)) . '</pre>' + . '<hr />' . 'Expected:' . '<pre>' . check_plain(var_export($expected, TRUE)) . '</pre>' + . '<hr />' . $output + ); + if (!$message) { + $message = '%callback rendered correctly.'; + } + $message = format_string($message, array('%callback' => 'theme_' . $callback . '()')); + return $this->assertIdentical($output, $expected, $message, $group); + } + + /** * Asserts that a field exists in the current page by the given XPath. * * @param $xpath diff --git a/modules/simpletest/tests/database_test.test b/modules/simpletest/tests/database_test.test index 6e1d15979..2c096fb1d 100644 --- a/modules/simpletest/tests/database_test.test +++ b/modules/simpletest/tests/database_test.test @@ -3815,3 +3815,222 @@ class DatabaseEmptyStatementTestCase extends DrupalWebTestCase { $this->assertEqual($result->fetchAll(), array(), t('Empty array returned from empty result set.')); } } + +/** + * Tests management of database connections. + */ +class ConnectionUnitTest extends DrupalUnitTestCase { + + protected $key; + protected $target; + + protected $monitor; + protected $originalCount; + + public static function getInfo() { + return array( + 'name' => 'Connection unit tests', + 'description' => 'Tests management of database connections.', + 'group' => 'Database', + ); + } + + function setUp() { + parent::setUp(); + + $this->key = 'default'; + $this->originalTarget = 'default'; + $this->target = 'DatabaseConnectionUnitTest'; + + // Determine whether the database driver is MySQL. If it is not, the test + // methods will not be executed. + // @todo Make this test driver-agnostic, or find a proper way to skip it. + // @see http://drupal.org/node/1273478 + $connection_info = Database::getConnectionInfo('default'); + $this->skipTest = (bool) $connection_info['default']['driver'] != 'mysql'; + if ($this->skipTest) { + // Insert an assertion to prevent Simpletest from interpreting the test + // as failure. + $this->pass('This test is only compatible with MySQL.'); + } + + // Create an additional connection to monitor the connections being opened + // and closed in this test. + // @see TestBase::changeDatabasePrefix() + $connection_info = Database::getConnectionInfo('default'); + Database::addConnectionInfo('default', 'monitor', $connection_info['default']); + global $databases; + $databases['default']['monitor'] = $connection_info['default']; + $this->monitor = Database::getConnection('monitor'); + } + + /** + * Adds a new database connection info to Database. + */ + protected function addConnection() { + // Add a new target to the connection, by cloning the current connection. + $connection_info = Database::getConnectionInfo($this->key); + Database::addConnectionInfo($this->key, $this->target, $connection_info[$this->originalTarget]); + + // Verify that the new target exists. + $info = Database::getConnectionInfo($this->key); + // Note: Custom assertion message to not expose database credentials. + $this->assertIdentical($info[$this->target], $connection_info[$this->key], 'New connection info found.'); + } + + /** + * Returns the connection ID of the current test connection. + * + * @return integer + */ + protected function getConnectionID() { + return (int) Database::getConnection($this->target, $this->key)->query('SELECT CONNECTION_ID()')->fetchField(); + } + + /** + * Asserts that a connection ID exists. + * + * @param integer $id + * The connection ID to verify. + */ + protected function assertConnection($id) { + $list = $this->monitor->query('SHOW PROCESSLIST')->fetchAllKeyed(0, 0); + return $this->assertTrue(isset($list[$id]), format_string('Connection ID @id found.', array('@id' => $id))); + } + + /** + * Asserts that a connection ID does not exist. + * + * @param integer $id + * The connection ID to verify. + */ + protected function assertNoConnection($id) { + $list = $this->monitor->query('SHOW PROCESSLIST')->fetchAllKeyed(0, 0); + return $this->assertFalse(isset($list[$id]), format_string('Connection ID @id not found.', array('@id' => $id))); + } + + /** + * Tests Database::closeConnection() without query. + * + * @todo getConnectionID() executes a query. + */ + function testOpenClose() { + if ($this->skipTest) { + return; + } + // Add and open a new connection. + $this->addConnection(); + $id = $this->getConnectionID(); + Database::getConnection($this->target, $this->key); + + // Verify that there is a new connection. + $this->assertConnection($id); + + // Close the connection. + Database::closeConnection($this->target, $this->key); + // Wait 20ms to give the database engine sufficient time to react. + usleep(20000); + + // Verify that we are back to the original connection count. + $this->assertNoConnection($id); + } + + /** + * Tests Database::closeConnection() with a query. + */ + function testOpenQueryClose() { + if ($this->skipTest) { + return; + } + // Add and open a new connection. + $this->addConnection(); + $id = $this->getConnectionID(); + Database::getConnection($this->target, $this->key); + + // Verify that there is a new connection. + $this->assertConnection($id); + + // Execute a query. + Database::getConnection($this->target, $this->key)->query('SHOW TABLES'); + + // Close the connection. + Database::closeConnection($this->target, $this->key); + // Wait 20ms to give the database engine sufficient time to react. + usleep(20000); + + // Verify that we are back to the original connection count. + $this->assertNoConnection($id); + } + + /** + * Tests Database::closeConnection() with a query and custom prefetch method. + */ + function testOpenQueryPrefetchClose() { + if ($this->skipTest) { + return; + } + // Add and open a new connection. + $this->addConnection(); + $id = $this->getConnectionID(); + Database::getConnection($this->target, $this->key); + + // Verify that there is a new connection. + $this->assertConnection($id); + + // Execute a query. + Database::getConnection($this->target, $this->key)->query('SHOW TABLES')->fetchCol(); + + // Close the connection. + Database::closeConnection($this->target, $this->key); + // Wait 20ms to give the database engine sufficient time to react. + usleep(20000); + + // Verify that we are back to the original connection count. + $this->assertNoConnection($id); + } + + /** + * Tests Database::closeConnection() with a select query. + */ + function testOpenSelectQueryClose() { + if ($this->skipTest) { + return; + } + // Add and open a new connection. + $this->addConnection(); + $id = $this->getConnectionID(); + Database::getConnection($this->target, $this->key); + + // Verify that there is a new connection. + $this->assertConnection($id); + + // Create a table. + $name = 'foo'; + Database::getConnection($this->target, $this->key)->schema()->createTable($name, array( + 'fields' => array( + 'name' => array( + 'type' => 'varchar', + 'length' => 255, + ), + ), + )); + + // Execute a query. + Database::getConnection($this->target, $this->key)->select('foo', 'f') + ->fields('f', array('name')) + ->execute() + ->fetchAll(); + + // Drop the table. + Database::getConnection($this->target, $this->key)->schema()->dropTable($name); + + // Close the connection. + Database::closeConnection($this->target, $this->key); + // Wait 20ms to give the database engine sufficient time to react. + usleep(20000); + + // Verify that we are back to the original connection count. + $this->assertNoConnection($id); + } + +} diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc index 061898c85..05543be6a 100644 --- a/modules/system/system.admin.inc +++ b/modules/system/system.admin.inc @@ -1594,6 +1594,7 @@ function system_site_information_settings_validate($form, &$form_state) { * @ingroup forms */ function system_cron_settings() { + global $base_url; $form['description'] = array( '#markup' => '<p>' . t('Cron takes care of running periodic tasks like checking for updates and indexing content for search.') . '</p>', ); @@ -1606,6 +1607,11 @@ function system_cron_settings() { $form['status'] = array( '#markup' => $status, ); + + $form['cron_url'] = array( + '#markup' => '<p>' . t('To run cron from outside the site, go to <a href="!cron">!cron</a>', array('!cron' => url($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => variable_get('cron_key', 'drupal')))))) . '</p>', + ); + $form['cron'] = array( '#type' => 'fieldset', ); diff --git a/modules/system/system.api.php b/modules/system/system.api.php index adef26141..db1a91146 100644 --- a/modules/system/system.api.php +++ b/modules/system/system.api.php @@ -2196,6 +2196,8 @@ function hook_permission() { * 'module', 'theme_engine', or 'theme'. * - theme path: (automatically derived) The directory path of the theme or * module, so that it doesn't need to be looked up. + * + * @see hook_theme_registry_alter() */ function hook_theme($existing, $type, $theme, $path) { return array( @@ -3092,44 +3094,48 @@ function hook_schema() { 'description' => 'The primary identifier for a node.', 'type' => 'serial', 'unsigned' => TRUE, - 'not null' => TRUE), + 'not null' => TRUE, + ), 'vid' => array( 'description' => 'The current {node_revision}.vid version identifier.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, - 'default' => 0), + 'default' => 0, + ), 'type' => array( 'description' => 'The {node_type} of this node.', 'type' => 'varchar', 'length' => 32, 'not null' => TRUE, - 'default' => ''), + 'default' => '', + ), 'title' => array( 'description' => 'The title of this node, always treated as non-markup plain text.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, - 'default' => ''), + 'default' => '', ), + ), 'indexes' => array( 'node_changed' => array('changed'), 'node_created' => array('created'), - ), + ), 'unique keys' => array( 'nid_vid' => array('nid', 'vid'), - 'vid' => array('vid') - ), + 'vid' => array('vid'), + ), 'foreign keys' => array( 'node_revision' => array( 'table' => 'node_revision', 'columns' => array('vid' => 'vid'), - ), + ), 'node_author' => array( 'table' => 'users', - 'columns' => array('uid' => 'uid') - ), - ), + 'columns' => array('uid' => 'uid'), + ), + ), 'primary key' => array('nid'), ); return $schema; diff --git a/modules/system/system.updater.inc b/modules/system/system.updater.inc index 0df1ad955..a14d788b1 100644 --- a/modules/system/system.updater.inc +++ b/modules/system/system.updater.inc @@ -73,8 +73,12 @@ class ModuleUpdater extends Updater implements DrupalUpdaterInterface { return array(); } + /** + * Returns a list of post install actions. + */ public function postInstallTasks() { return array( + l(t('Install another module'), 'admin/modules/install'), l(t('Enable newly added modules'), 'admin/modules'), l(t('Administration pages'), 'admin'), ); diff --git a/modules/update/update.module b/modules/update/update.module index 85c0968d5..d5728be3e 100644 --- a/modules/update/update.module +++ b/modules/update/update.module @@ -139,10 +139,10 @@ function update_init() { if (!empty($verbose)) { if (isset($status[$type]['severity'])) { if ($status[$type]['severity'] == REQUIREMENT_ERROR) { - drupal_set_message($status[$type]['description'], 'error'); + drupal_set_message($status[$type]['description'], 'error', FALSE); } elseif ($status[$type]['severity'] == REQUIREMENT_WARNING) { - drupal_set_message($status[$type]['description'], 'warning'); + drupal_set_message($status[$type]['description'], 'warning', FALSE); } } } @@ -152,7 +152,7 @@ function update_init() { if (isset($status[$type]) && isset($status[$type]['reason']) && $status[$type]['reason'] === UPDATE_NOT_SECURE) { - drupal_set_message($status[$type]['description'], 'error'); + drupal_set_message($status[$type]['description'], 'error', FALSE); } } } diff --git a/modules/user/user.admin.inc b/modules/user/user.admin.inc index 1cc2c4a24..932c20593 100644 --- a/modules/user/user.admin.inc +++ b/modules/user/user.admin.inc @@ -5,6 +5,21 @@ * Admin page callback file for the user module. */ +/** + * Page callback: Generates the appropriate user administration form. + * + * This function generates the user registration, multiple user cancellation, + * or filtered user list admin form, depending on the argument and the POST + * form values. + * + * @param string $callback_arg + * (optional) Indicates which form to build. Defaults to '', which will + * trigger the user filter form. If the POST value 'op' is present, this + * function uses that value as the callback argument. + * + * @return string + * A renderable form array for the respective request. + */ function user_admin($callback_arg = '') { $op = isset($_POST['op']) ? $_POST['op'] : $callback_arg; diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php index 2b207f224..40f552e1d 100644 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -147,7 +147,7 @@ * 'authmap' => 'shared_', * ), * @endcode - * You can also use a reference to a schema/database as a prefix. This maybe + * You can also use a reference to a schema/database as a prefix. This may be * useful if your Drupal installation exists in a schema that is not the default * or you want to access several databases from the same code base at the same * time. @@ -435,7 +435,7 @@ ini_set('session.cookie_lifetime', 2000000); /** * String overrides: * - * To override specific strings on your site with or without enabling locale + * To override specific strings on your site with or without enabling the Locale * module, add an entry to this list. This functionality allows you to change * a small number of your site's default English language interface strings. * diff --git a/update.php b/update.php index 0c2aaf850..f9be98edf 100644 --- a/update.php +++ b/update.php @@ -1,7 +1,7 @@ <?php /** - * Root directory of Drupal installation. + * Defines the root directory of the Drupal installation. */ define('DRUPAL_ROOT', getcwd()); @@ -27,6 +27,9 @@ define('DRUPAL_ROOT', getcwd()); */ define('MAINTENANCE_MODE', 'update'); +/** + * Renders a form with a list of available database updates. + */ function update_selection_page() { drupal_set_title('Drupal database update'); $elements = drupal_get_form('update_script_selection_form'); @@ -37,6 +40,9 @@ function update_selection_page() { return $output; } +/** + * Form constructor for the list of available database module updates. + */ function update_script_selection_form($form, &$form_state) { $count = 0; $incompatible_count = 0; @@ -141,6 +147,9 @@ function update_script_selection_form($form, &$form_state) { return $form; } +/** + * Provides links to the homepage and administration pages. + */ function update_helpful_links() { // NOTE: we can't use l() here because the URL would point to // 'update.php?q=admin'. @@ -151,6 +160,9 @@ function update_helpful_links() { return $links; } +/** + * Displays results of the update script with any accompanying errors. + */ function update_results_page() { drupal_set_title('Drupal database update'); $links = update_helpful_links(); @@ -231,6 +243,15 @@ function update_results_page() { return $output; } +/** + * Provides an overview of the Drupal database update. + * + * This page provides cautionary suggestions that should happen before + * proceeding with the update to ensure data integrity. + * + * @return + * Rendered HTML form. + */ function update_info_page() { // Change query-strings on css/js files to enforce reload for all users. _drupal_flush_css_js(); @@ -256,6 +277,12 @@ function update_info_page() { return $output; } +/** + * Renders a 403 access denied page for update.php. + * + * @return + * Rendered HTML warning with 403 status. + */ function update_access_denied_page() { drupal_add_http_header('Status', '403 Forbidden'); watchdog('access denied', 'update.php', NULL, WATCHDOG_WARNING); @@ -294,7 +321,7 @@ function update_access_allowed() { } /** - * Add the update task list to the current page. + * Adds the update task list to the current page. */ function update_task_list($active = NULL) { // Default list of tasks. @@ -310,8 +337,7 @@ function update_task_list($active = NULL) { } /** - * Returns (and optionally stores) extra requirements that only apply during - * particular parts of the update.php process. + * Returns and stores extra requirements that apply during the update process. */ function update_extra_requirements($requirements = NULL) { static $extra_requirements = array(); @@ -322,7 +348,7 @@ function update_extra_requirements($requirements = NULL) { } /** - * Check update requirements and report any errors or (optionally) warnings. + * Checks update requirements and reports errors and (optionally) warnings. * * @param $skip_warnings * (optional) If set to TRUE, requirement warnings will be ignored, and a |