summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.htaccess12
-rw-r--r--CHANGELOG.txt19
-rw-r--r--authorize.php35
-rw-r--r--includes/bootstrap.inc12
-rw-r--r--includes/cache.inc69
-rw-r--r--includes/common.inc13
-rw-r--r--includes/database/database.inc41
-rw-r--r--includes/database/mysql/database.inc17
-rw-r--r--includes/form.inc2
-rw-r--r--includes/install.core.inc33
-rw-r--r--includes/install.inc6
-rw-r--r--includes/mail.inc4
-rw-r--r--includes/menu.inc1
-rw-r--r--install.php8
-rw-r--r--modules/dblog/dblog-rtl.css4
-rw-r--r--modules/dblog/dblog.admin.inc79
-rw-r--r--modules/dblog/dblog.css5
-rw-r--r--modules/dblog/dblog.module18
-rw-r--r--modules/dblog/dblog.test228
-rw-r--r--modules/field/field.api.php2
-rw-r--r--modules/field/field.attach.inc2
-rw-r--r--modules/field/field.module2
-rw-r--r--modules/field_ui/field_ui.admin.inc4
-rw-r--r--modules/image/image.admin.inc2
-rw-r--r--modules/image/image.install3
-rw-r--r--modules/node/content_types.inc9
-rw-r--r--modules/node/node.admin.inc135
-rw-r--r--modules/node/node.api.php200
-rw-r--r--modules/node/node.module240
-rw-r--r--modules/node/node.pages.inc105
-rw-r--r--modules/node/node.test141
-rw-r--r--modules/node/tests/node_access_test.module6
-rw-r--r--modules/node/tests/node_test.module6
-rw-r--r--modules/node/tests/node_test_exception.module3
-rw-r--r--modules/simpletest/drupal_web_test_case.php36
-rw-r--r--modules/simpletest/tests/database_test.test219
-rw-r--r--modules/system/system.admin.inc6
-rw-r--r--modules/system/system.api.php28
-rw-r--r--modules/system/system.updater.inc4
-rw-r--r--modules/update/update.module6
-rw-r--r--modules/user/user.admin.inc15
-rw-r--r--sites/default/default.settings.php4
-rw-r--r--update.php36
43 files changed, 1355 insertions, 465 deletions
diff --git a/.htaccess b/.htaccess
index 246edc2db..5ca1b08bd 100644
--- a/.htaccess
+++ b/.htaccess
@@ -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 = '&#039;';
- // 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