diff options
author | Dries Buytaert <dries@buytaert.net> | 2004-07-13 07:21:14 +0000 |
---|---|---|
committer | Dries Buytaert <dries@buytaert.net> | 2004-07-13 07:21:14 +0000 |
commit | 50d78e9855b529651f3c3ef05419215fcea58e21 (patch) | |
tree | 7129df0697a8eb240e72df6ea77f338ef9c4dd47 | |
parent | 6477705fc86c50541f5ab3bb16cabb03cadb0ce5 (diff) | |
download | brdo-50d78e9855b529651f3c3ef05419215fcea58e21.tar.gz brdo-50d78e9855b529651f3c3ef05419215fcea58e21.tar.bz2 |
- Patch #9238 by JonBob: added code and Doxygen comments to common.inc and
bootstrap.inc.
-rw-r--r-- | includes/bootstrap.inc | 205 | ||||
-rw-r--r-- | includes/common.inc | 1002 |
2 files changed, 873 insertions, 334 deletions
diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc index 03e7755de..77821e41f 100644 --- a/includes/bootstrap.inc +++ b/includes/bootstrap.inc @@ -1,20 +1,26 @@ <?php /* $Id$ */ -function conf_init() { - - /* - ** Try finding a matching configuration file by stripping the website's - ** URI from left to right. If no configuration file is found, return a - ** default value 'conf'. - */ +/** + * @file + * + * Functions that need to be loaded on every Drupal request. + */ +/** + * Locate the appropriate configuration file. + * + * Try finding a matching configuration file by stripping the website's + * URI from left to right. If no configuration file is found, return the + * default value, "conf". + */ +function conf_init() { $uri = $_SERVER['PHP_SELF']; $file = strtolower(strtr($_SERVER['HTTP_HOST'] . substr($uri, 0, strrpos($uri, '/')), '/:', '..')); while (strlen($file) > 4) { - if (file_exists("includes/$file.php")) { + if (file_exists('includes/'. $file .'.php')) { return $file; } else { @@ -25,6 +31,13 @@ function conf_init() { return 'conf'; } +/** + * Load the persistent variable table. + * + * The variable table is composed of values that have been saved in the table + * with variable_set() as well as those explicitly specified in the configuration + * file. + */ function variable_init($conf = array()) { $result = db_query('SELECT * FROM {variable} '); while ($variable = db_fetch_object($result)) { @@ -36,12 +49,31 @@ function variable_init($conf = array()) { return $conf; } +/** + * Return a persistent variable. + * + * @param $name + * The name of the variable to return. + * @param $default + * The default value to use if this variable has never been set. + * @return + * The value of the variable. + */ function variable_get($name, $default) { global $conf; return isset($conf[$name]) ? $conf[$name] : $default; } +/** + * Set a persistent variable. + * + * @param $name + * The name of the variable to set. + * @param $value + * The value to set. This can be any PHP data type; these functions take care + * of serialization as necessary. + */ function variable_set($name, $value) { global $conf; @@ -51,6 +83,12 @@ function variable_set($name, $value) { $conf[$name] = $value; } +/** + * Unset a persistent variable. + * + * @param $name + * The name of the variable to undefine. + */ function variable_del($name) { global $conf; @@ -59,11 +97,30 @@ function variable_del($name) { unset($conf[$name]); } +/** + * Return data from the persistent cache. + * + * @param $key + * The cache ID of the data to retrieve. + */ function cache_get($key) { $cache = db_fetch_object(db_query("SELECT data, created, headers FROM {cache} WHERE cid = '%s'", $key)); return $cache->data ? $cache : 0; } +/** + * Store data in the persistent cache. + * + * @param $cid + * The cache ID of the data to store. + * @param $data + * The data to store in the cache. Complex data types must be serialized first. + * @param $expire + * Whether the data should be removed from the cache when a cache expiration + * is triggered. + * @param $headers + * A string containing HTTP header information for cached pages. + */ function cache_set($cid, $data, $expire = 0, $headers = NULL) { db_query("UPDATE {cache} SET data = '%s', created = %d, expire = %d, headers = '%s' WHERE cid = '%s'", $data, time(), $expire, $headers, $cid); if (!db_affected_rows()) { @@ -71,6 +128,13 @@ function cache_set($cid, $data, $expire = 0, $headers = NULL) { } } +/** + * Expire data from the cache. + * + * @param $cid + * If set, the cache ID to delete. Otherwise, all cache entries that can expire + * are deleted. + */ function cache_clear_all($cid = NULL) { if (empty($cid)) { db_query("DELETE FROM {cache} WHERE expire <> 0"); @@ -80,6 +144,9 @@ function cache_clear_all($cid = NULL) { } } +/** + * Store the current page in the cache. + */ function page_set_cache() { global $user; @@ -99,17 +166,19 @@ function page_set_cache() { } } +/** + * Retrieve the current page from the cache. + * + * Note, we do not serve cached pages when status messages are waiting (from + * a redirected form submission which was completed). + * Because the output handler is not activated, the resulting page will not + * get cached either. + */ function page_get_cache() { global $user; $cache = NULL; - /* - * Note, we do not serve cached pages when status messages are waiting (from - * a redirected form submission which was completed). - * Because the output handler is not activated, the resulting page will not - * get cached either. - */ if (!$user->uid && $_SERVER['REQUEST_METHOD'] == 'GET' && count(drupal_set_message()) == 0) { $cache = cache_get(request_uri()); @@ -121,6 +190,9 @@ function page_get_cache() { return $cache; } +/** + * Set HTTP headers in preparation for a page response. + */ function drupal_page_header() { if (variable_get('dev_timer', 0)) { timer_start(); @@ -153,21 +225,18 @@ function drupal_page_header() { header("Last-Modified: $date"); header("ETag: $etag"); - // Determine if the browser accepts gzipped data + // Determine if the browser accepts gzipped data. if (@strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === false && function_exists('gzencode')) { - // strip the gzip header and run uncompress + // Strip the gzip header and run uncompress. $cache->data = gzinflate(substr(substr($cache->data, 10), 0, -8)); } elseif (function_exists('gzencode')) { header('Content-Encoding: gzip'); } - /* - ** Send the original request's headers. We send them one after - ** another so PHP's header() function can deal with duplicate - ** headers. - */ - + // Send the original request's headers. We send them one after + // another so PHP's header() function can deal with duplicate + // headers. $headers = explode("\n", $cache->headers); foreach ($headers as $header) { header($header); @@ -175,10 +244,8 @@ function drupal_page_header() { print $cache->data; - /* - ** call all init() and exit() hooks without including all modules - ** only use those hooks for critical operations - */ + // Call all init() and exit() hooks without including all modules. + // Only use those hooks for critical operations. foreach (bootstrap_hooks() as $hook) { module_invoke_all($hook); } @@ -187,16 +254,21 @@ function drupal_page_header() { } } -// critical hooks called even when serving a cached page +/** + * Define the critical hooks that force modules to always be loaded. + */ function bootstrap_hooks() { return array('init', 'exit'); } -/* -** Unserializes and appends elements from a serialized string -** $obj is the object to which we shall append -** $field is the element whose value is a serialized string -*/ +/** + * Unserializes and appends elements from a serialized string. + * + * @param $obj + * The object to which the elements are appended. + * @param $field + * The attribute of $obj whose value should be unserialized. + */ function drupal_unpack($obj, $field = 'data') { if ($obj->$field && $data = unserialize($obj->$field)) { foreach ($data as $key => $value) { @@ -208,12 +280,26 @@ function drupal_unpack($obj, $field = 'data') { return $obj; } +/** + * Return the URI of the referring page. + */ function referer_uri() { if (isset($_SERVER['HTTP_REFERER'])) { return check_url($_SERVER['HTTP_REFERER']); } } +/** + * Return a component of the current Drupal path. + * + * When viewing a page at the path "admin/node/configure", for example, arg(0) + * would return "admin", arg(1) would return "node", and arg(2) would return + * "configure". + * + * Avoid use of this function where possible, as resulting code is hard to read. + * Instead, attempt to use named arguments in menu callback functions. See the + * explanation in menu.inc for how to construct callbacks that take arguments. + */ function arg($index) { static $arguments, $q; @@ -226,28 +312,31 @@ function arg($index) { } } +/** + * Prepare user input for use in a database query, preventing SQL injection attacks. + */ function check_query($text) { return addslashes($text); } +/** + * Prepare user input for use in a URI. + * + * We replace ( and ) with their entity equivalents to prevent XSS attacks. + */ function check_url($uri) { $uri = htmlspecialchars($uri, ENT_QUOTES); - /* - ** We replace ( and ) with their entity equivalents to prevent XSS - ** attacks. - */ - $uri = strtr($uri, array('(' => '&040;', ')' => '&041;')); return $uri; } +/** + * Since request_uri() is only available on Apache, we generate an + * equivalent using other environment vars. + */ function request_uri() { - /* - ** Since request_uri() is only available on Apache, we generate - ** equivalent using other environment vars. - */ if (isset($_SERVER['REQUEST_URI'])) { $uri = $_SERVER['REQUEST_URI']; @@ -259,12 +348,25 @@ function request_uri() { return check_url($uri); } +/** + * Begin a global timer, for benchmarking of page execution time. + */ function timer_start() { global $timer; - list($usec, $sec) = explode(" ", microtime()); + list($usec, $sec) = explode(' ', microtime()); $timer = (float)$usec + (float)$sec; } +/** + * Log a system message. + * + * @param $type + * The category to which this message belongs. + * @param $message + * The message to store in the log. + * @param $link + * A link to associate with the message. + */ function watchdog($type, $message, $link = NULL) { global $user; db_query("INSERT INTO {watchdog} (uid, type, message, link, location, hostname, timestamp) VALUES (%d, '%s', '%s', '%s', '%s', '%s', %d)", $user->uid, $type, $message, $link, request_uri(), $_SERVER['REMOTE_ADDR'], time()); @@ -272,12 +374,20 @@ function watchdog($type, $message, $link = NULL) { /** * @name Page messages - * @ingroup common * * Functions to get and set the message of the current page. * @{ */ -function drupal_set_message($message = NULL, $type = "status") { + +/** + * Set a message for the user to see. + * + * The message is stored in the session so that it can persist through a redirect. + * + * If called with no arguments, this function returns all set messages without + * clearing them. + */ +function drupal_set_message($message = NULL, $type = 'status') { if (isset($message)) { if (!isset($_SESSION['messages'])) { $_SESSION['messages'] = array(); @@ -293,6 +403,11 @@ function drupal_set_message($message = NULL, $type = "status") { return $_SESSION['messages']; } +/** + * Return all messages that have been set. + * + * As a side effect, this function clears the message queue. + */ function drupal_get_messages() { $messages = drupal_set_message(); $_SESSION['messages'] = array(); @@ -310,6 +425,6 @@ include_once 'includes/database.inc'; include_once 'includes/session.inc'; include_once 'includes/module.inc'; -// initialize configuration variables, using values from conf.php if available: +// Initialize configuration variables, using values from conf.php if available. $conf = variable_init(isset($conf) ? $conf : array()); ?> diff --git a/includes/common.inc b/includes/common.inc index ac862a6e2..d26f4d790 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -2,8 +2,16 @@ /* $Id$ */ /** + * @file + * + * Common functions that many Drupal modules will need to reference. + * + * The functions that are critical and need to be available even when serving + * a cached page are instead located in bootstrap.inc. + */ + +/** * @name Page title - * @ingroup common * * Functions to get and set the title of the current page. * @{ @@ -30,7 +38,6 @@ function drupal_get_title() { /** * @name Page breadcrumbs - * @ingroup common * * Functions to get and set the breadcrumb trail of the current page. * @{ @@ -62,7 +69,6 @@ function drupal_get_breadcrumb() { /** * @name HTML head contents - * @ingroup common * * Set and get output that should be in the \<head\> tag. * @{ @@ -72,7 +78,7 @@ function drupal_set_html_head($data = NULL) { static $stored_head = ''; if (!is_null($data)) { - $stored_head .= "$data\n"; + $stored_head .= $data ."\n"; } return $stored_head; } @@ -92,20 +98,20 @@ function drupal_get_html_head() { /** * @name URL path alias - * @ingroup common * * Functions to handle path aliases. */ -function drupal_get_path_map($action = "") { + +function drupal_get_path_map($action = '') { static $map = NULL; - if ($action == "rebuild") { + if ($action == 'rebuild') { $map = NULL; } if (is_null($map)) { $map = array(); // make $map non-null in case no aliases are defined - $result = db_query("SELECT * FROM {url_alias}"); + $result = db_query('SELECT * FROM {url_alias}'); while ($data = db_fetch_object($result)) { $map[$data->dst] = $data->src; } @@ -115,17 +121,17 @@ function drupal_get_path_map($action = "") { } function drupal_rebuild_path_map() { - drupal_get_path_map("rebuild"); + drupal_get_path_map('rebuild'); } /** - * Given an old url, return the alias. + * Given an internal Drupal path, return the alias set by the administrator. */ function drupal_get_path_alias($path) { if (($map = drupal_get_path_map()) && ($newpath = array_search($path, $map))) { return $newpath; } - elseif (function_exists("conf_url_rewrite")) { + elseif (function_exists('conf_url_rewrite')) { return conf_url_rewrite($path, 'outgoing'); } else { @@ -135,13 +141,13 @@ function drupal_get_path_alias($path) { } /** - * Given an alias, return the default url. + * Given a path alias, return the internal path it represents. */ function drupal_get_normal_path($path) { if (($map = drupal_get_path_map()) && isset($map[$path])) { return $map[$path]; } - elseif (function_exists("conf_url_rewrite")) { + elseif (function_exists('conf_url_rewrite')) { return conf_url_rewrite($path, 'incoming'); } else { @@ -152,7 +158,6 @@ function drupal_get_normal_path($path) { /** * @name HTTP headers - * @ingroup common * * Functions to get and set the HTTP headers of the current page. * @{ @@ -162,7 +167,7 @@ function drupal_set_header($header = NULL) { if (!is_null($header)) { header($header); - $stored_headers .= "$header\n"; + $stored_headers .= $header ."\n"; } return $stored_headers; } @@ -174,7 +179,6 @@ function drupal_get_headers() { /** * @name HTTP handling - * @ingroup common * * Functions to properly handle HTTP responses. * @{ @@ -231,7 +235,7 @@ function drupal_goto($path = '', $query = NULL, $fragment = NULL) { */ function drupal_not_found() { header('HTTP/1.0 404 Not Found'); - watchdog('httpd', t('404 error: "%page" not found', array('%page' => check_query($_GET["q"])))); + watchdog('httpd', t('404 error: "%page" not found', array('%page' => check_query($_GET['q'])))); $path = drupal_get_normal_path(variable_get('site_404', '')); $status = MENU_NOT_FOUND; @@ -264,62 +268,70 @@ function drupal_access_denied() { } /** - * Flexible and powerful HTTP client implementation. Allows to GET, POST, PUT - * or any other HTTP requests. Handles redirects. + * Perform an HTTP request. * - * @param $url A string containing a fully qualified URI. - * @param $headers An array containing a HTTP header => value pair. - * @param $method A string defining the HTTP request to use. - * @param $data A string containing data to include in the request. - * @param $retry An integer representing how many times to retry the request - * in case of a redirect. - * @return An object containing the HTTP request headers, response code, - * headers, data, and redirect status. + * This is a flexible and powerful HTTP client implementation. Correctly handles + * GET, POST, PUT or any other HTTP requests. Handles redirects. + * + * @param $url + * A string containing a fully qualified URI. + * @param $headers + * An array containing an HTTP header => value pair. + * @param $method + * A string defining the HTTP request to use. + * @param $data + * A string containing data to include in the request. + * @param $retry + * An integer representing how many times to retry the request in case of a + * redirect. + * @return + * An object containing the HTTP request headers, response code, headers, + * data, and redirect status. */ function drupal_http_request($url, $headers = array(), $method = 'GET', $data = NULL, $retry = 3) { - // Parse the URL, and make sure we can handle the schema + // Parse the URL, and make sure we can handle the schema. $uri = parse_url($url); switch ($uri['scheme']) { case 'http': $fp = @fsockopen($uri['host'], ($uri['port'] ? $uri['port'] : 80), $errno, $errstr, 15); break; case 'https': - // Note: only works for PHP 4.3 compiled with openssl - $fp = @fsockopen("ssl://$uri[host]", ($uri['port'] ? $uri['port'] : 443), $errno, $errstr, 20); + // Note: Only works for PHP 4.3 compiled with OpenSSL. + $fp = @fsockopen('ssl://'. $uri['host'], ($uri['port'] ? $uri['port'] : 443), $errno, $errstr, 20); break; default: - $result->error = "invalid schema $uri[scheme]"; + $result->error = 'invalid schema '. $uri['scheme']; return $result; } - // Make sure the socket opened properly + // Make sure the socket opened properly. if (!$fp) { - $result->error = trim("$errno $errstr"); + $result->error = trim($errno .' '. $errstr); return $result; } - // Construct the path to act on + // Construct the path to act on. $path = $uri['path'] ? $uri['path'] : '/'; if ($uri['query']) { - $path .= "?$uri[query]"; + $path .= '?'. $uri['query']; } - // Create http request + // Create http request. $defaults = array( - 'Host' => "Host: $uri[host]", + 'Host' => 'Host: '. $uri['host'], 'User-Agent' => 'User-Agent: Drupal (+http://www.drupal.org/)', 'Content-Length' => 'Content-Length: '. strlen($data) ); foreach ($headers as $header => $value) { - $defaults[$header] = "$header: $value"; + $defaults[$header] = $header .': '. $value; } - $request = "$method $path HTTP/1.0\r\n"; + $request = $method .' '. $path ." HTTP/1.0\r\n"; $request .= implode("\r\n", $defaults); $request .= "\r\n\r\n"; if ($data) { - $request .= "$data\r\n"; + $request .= $data ."\r\n"; } $result->request = $request; @@ -383,14 +395,17 @@ function drupal_http_request($url, $headers = array(), $method = 'GET', $data = } /* @} */ +/** + * Log errors in the database rather than displaying them to the user. + */ function error_handler($errno, $message, $filename, $line, $variables) { - $types = array(1 => "error", 2 => "warning", 4 => "parse error", 8 => "notice", 16 => "core error", 32 => "core warning", 64 => "compile error", 128 => "compile warning", 256 => "user error", 512 => "user warning", 1024 => "user notice"); - $entry = $types[$errno] .": $message in $filename on line $line."; + $types = array(1 => 'error', 2 => 'warning', 4 => 'parse error', 8 => 'notice', 16 => 'core error', 32 => 'core warning', 64 => 'compile error', 128 => 'compile warning', 256 => 'user error', 512 => 'user warning', 1024 => 'user notice'); + $entry = $types[$errno] .': '. $message .' in '. $filename .' on line '. $line .'.'; if ($errno & E_ALL ^ E_NOTICE) { watchdog('error', t('%error: %message in %file on line %line.', array('%error' => $types[$errno], '%message' => $message, '%file' => $filename, '%line' => $line))); if (error_reporting()) { - print "<pre>$entry</pre>"; + print '<pre>'. $entry .'</pre>'; } } } @@ -404,9 +419,13 @@ function _fix_gpc_magic(&$item, $key) { } } +/** + * Correct double-escaping problems caused by "magic quotes" in some PHP + * installations. + */ function fix_gpc_magic() { static $fixed = false; - if (!$fixed && ini_get("magic_quotes_gpc")) { + if (!$fixed && ini_get('magic_quotes_gpc')) { array_walk($_GET, '_fix_gpc_magic'); array_walk($_POST, '_fix_gpc_magic'); array_walk($_COOKIE, '_fix_gpc_magic'); @@ -417,11 +436,14 @@ function fix_gpc_magic() { /** * @name Conversion - * @ingroup common * * Converts data structures to a different type. * @{ */ + +/** + * Convert an associative array to an anonymous object. + */ function array2object($array) { if (is_array($array)) { foreach ($array as $key => $value) { @@ -435,6 +457,9 @@ function array2object($array) { return $object; } +/** + * Convert an object to an associative array. + */ function object2array($object) { if (is_object($object)) { foreach ($object as $key => $value) { @@ -451,21 +476,33 @@ function object2array($object) { /** * @name Messages - * @ingroup common * * Frequently used messages. * @{ */ + +/** + * Return a string with an "access denied" message. + * + * Always consider whether to use drupal_access_denied() instead to return a + * proper (and customizable) 403 error. + */ function message_access() { - return t("You are not authorized to access this page."); + return t('You are not authorized to access this page.'); } +/** + * Return a string with a "not applicable" message. + */ function message_na() { - return t("n/a"); + return t('n/a'); } /* @} */ +/** + * Initialize the localization system. + */ function locale_init() { global $languages, $user; if ($user->uid && $languages[$user->language]) { @@ -477,31 +514,33 @@ function locale_init() { } /** - * @ingroup common - * - * Translates strings to the current locale. + * Translate strings to the current locale. * * When using t(), try to put entire sentences and strings in one t() call. * This makes it easier for translators. We are unafraid of HTML markup within * translation strings if necessary. The suggested syntax for a link embedded * within a translation string is for example: - * @code - * $msg = t("You must login below or \<a href=\"%url\"\>create a new - * account\</a\> before viewing the next page.", array("%url" - * => url("user/register"))); - * @endcode + * @verbatim + * $msg = t('You must log in below or <a href="%url">create a new + * account</a> before viewing the next page.', array('%url' + * => url('user/register'))); + * @endverbatim * We suggest the same syntax for links to other sites. This makes it easy to * change link URLs if needed (which happens often) without requiring updates * to translations. * - * @param $string A string containing the english string to translate. - * @param $args Array of values to replace in the string. - * @return Translated string. + * @param $string + * A string containing the english string to translate. + * @param $args + * An associative array of replacements to make after translation. Incidences + * of any key in this array are replaces with the corresponding value. + * @return + * The translated string. */ function t($string, $args = 0) { global $languages; - $string = ($languages && module_exist("locale") ? locale($string) : $string); + $string = ($languages && module_exist('locale') ? locale($string) : $string); if (!$args) { return $string; @@ -511,32 +550,34 @@ function t($string, $args = 0) { } } +/** + * Encode special characters in a string for display as HTML. + * + * Note that we'd like to use htmlspecialchars($input, $quotes, 'utf-8') + * as outlined in the PHP manual, but we can't because there's a bug in + * PHP < 4.3 that makes it mess up multibyte charsets if we specify the + * charset. This will be changed later once we make PHP 4.3 a requirement. + */ function drupal_specialchars($input, $quotes = ENT_NOQUOTES) { - - /* - ** Note that we'd like to go 'htmlspecialchars($input, $quotes, "utf-8")' - ** like the PHP manual tells us to, but we can't because there's a bug in - ** PHP <4.3 that makes it mess up multibyte charsets if we specify the - ** charset. Change this later once we make PHP 4.3 a requirement. - */ - return htmlspecialchars($input, $quotes); } /** * @name Validation - * @ingroup common * * Functions to validate user input. * @{ */ /** - * Verify the syntax of the given e-mail address. Empty e-mail addresses are - * allowed. See RFC 2822 for details. + * Verify the syntax of the given e-mail address. + * + * Empty e-mail addresses are allowed. See RFC 2822 for details. * - * @param $mail A string containing an email address. + * @param $mail + * A string containing an email address. * @return + * TRUE if the address is in a valid format. */ function valid_email_address($mail) { $user = '[a-zA-Z0-9_\-\.\+\^!#\$%&*+\/\=\?\`\|\{\}~\']+'; @@ -551,11 +592,11 @@ function valid_email_address($mail) { * Verify the syntax of the given URL. * * @param $url - * an URL + * The URL to verify. * @param $absolute - * is the URL to be verified absolute, ie. of the form \<scheme\>://\<hostname\>/...? + * Whether the URL is absolute (beginning with a scheme such as http). * @return - * valid syntax: TRUE; FALSE otherwise + * TRUE if the URL is in a valid format. */ function valid_url($url, $absolute = FALSE) { if ($absolute) { @@ -566,41 +607,46 @@ function valid_url($url, $absolute = FALSE) { } } +/** + * Validate data input by a user. + * + * Ensures that user data cannot be used to perform attacks on the site. + * + * @param $data + * The input to check. + * @return + * TRUE if the input data is acceptable. + */ function valid_input_data($data) { if (is_array($data) || is_object($data)) { - /* - ** Form data can contain a number of nested arrays. - */ - + // Form data can contain a number of nested arrays. foreach ($data as $key => $value) { if (!valid_input_data($key) || !valid_input_data($value)) { - return 0; + return FALSE; } } } else { - /* - ** Detect evil input data. - */ + // Detect dangerous input data. - // check strings: - $match = preg_match("/\Wjavascript\s*:/i", $data); - $match += preg_match("/\Wexpression\s*\(/i", $data); - $match += preg_match("/\Walert\s*\(/i", $data); + // Check strings: + $match = preg_match('/\Wjavascript\s*:/i', $data); + $match += preg_match('/\Wexpression\s*\(/i', $data); + $match += preg_match('/\Walert\s*\(/i', $data); - // check attributes: + // Check attributes: $match += preg_match("/\W(dynsrc|datasrc|data|lowsrc|on[a-z]+)\s*=[^>]+?>/i", $data); - // check tags: + // Check tags: $match += preg_match("/<\s*(applet|script|object|style|embed|form|blink|meta|html|frame|iframe|layer|ilayer|head|frameset|xml)/i", $data); if ($match) { watchdog('warning', t('terminated request because of suspicious input data: %data', array('%data' => drupal_specialchars($data)))); - return 0; + return FALSE; } } - return 1; + return TRUE; } /* @} */ @@ -608,27 +654,28 @@ function valid_input_data($data) { * @defgroup search Search interface * @{ */ + /** * Format a single result entry of a search query: * * @param $item a single search result as returned by <i>module</i>_search of - * type array("count" => ..., "link" => ..., "title" => ..., "user" => ..., - * "date" => ..., "keywords" => ...) + * type array('count' => ..., 'link' => ..., 'title' => ..., 'user' => ..., + * 'date' => ..., 'keywords' => ...) * @param $type module type of this item */ function search_item($item, $type) { /* - ** Modules may implement the "search_item" hook in order to overwrite + ** Modules may implement hook_search_item() hook in order to overwrite ** the default function to display search results. */ - if (module_hook($type, "search_item")) { - $output = module_invoke($type, "search_item", $item); + if (module_hook($type, 'search_item')) { + $output = module_invoke($type, 'search_item', $item); } else { - $output = " <dt class=\"title\"><a href=\"". $item["link"] ."\">". $item["title"] ."</a></dt>"; - $output .= " <dd class=\"small\">" . t($type) . ($item["user"] ? " - ". $item["user"] : "") ."". ($item["date"] ? " - ". format_date($item["date"], "small") : "") ."</dd>"; + $output = ' <dt class="title"><a href="'. $item['link'] .'">'. $item['title'] .'</a></dt>'; + $output .= ' <dd class="small">' . t($type) . ($item['user'] ? ' - '. $item['user'] : '') .''. ($item['date'] ? ' - '. format_date($item['date'], 'small') : '') .'</dd>'; } return $output; @@ -651,45 +698,45 @@ function search_form($action = NULL, $keys = NULL, $options = NULL) { $edit = $_POST['edit']; if (!$action) { - $action = url("search"); + $action = url('search'); } - $output = " <div class=\"search-form\"><br /><input type=\"text\" class=\"form-text\" size=\"50\" value=\"". check_form($keys) ."\" name=\"keys\" />"; - $output .= " <input type=\"submit\" class=\"form-submit\" value=\"". t("Search") ."\" />\n"; + $output = ' <div class="search-form"><br /><input type="text" class="form-text" size="50" value="'. check_form($keys) .'" name="keys" />'; + $output .= ' <input type="submit" class="form-submit" value="'. t('Search') ."\" />\n"; if ($options) { - $output .= "<br />"; - $output .= t("Restrict search to") .": "; + $output .= '<br />'; + $output .= t('Restrict search to') .': '; foreach (module_list() as $name) { - if (module_hook($name, "search")) { - $output .= " <input type=\"checkbox\" name=\"edit[type][$name]\" ". ($edit["type"][$name] ? " checked=\"checked\"" : "") ." /> ". t($name); + if (module_hook($name, 'search')) { + $output .= ' <input type="checkbox" name="edit[type]['. $name .']" '. ($edit['type'][$name] ? ' checked="checked"' : '') .' /> '. t($name); } } - $output .= "</div>"; + $output .= '</div>'; } - return form($output, "post", $action); + return form($output, 'post', $action); } /* * Collect the search results: */ function search_data($keys = NULL) { - $edit = $_POST["edit"]; + $edit = $_POST['edit']; $output = ''; if (isset($keys)) { foreach (module_list() as $name) { - if (module_hook($name, "search") && (!$edit["type"] || $edit["type"][$name])) { - list($title, $results) = module_invoke($name, "search", $keys); + if (module_hook($name, 'search') && (!$edit['type'] || $edit['type'][$name])) { + list($title, $results) = module_invoke($name, 'search', $keys); if ($results) { - $output .= "<h2>$title</h2>"; - $output .= "<dl class=\"search-results\">"; + $output .= '<h2>'. $title .'</h2>'; + $output .= '<dl class="search-results">'; foreach ($results as $entry) { $output .= search_item($entry, $name); } - $output .= "</dl>"; + $output .= '</dl>'; } } } @@ -709,9 +756,9 @@ function search_data($keys = NULL) { * to", help text, etc). */ function search_type($type, $action = NULL, $keys = NULL, $options = NULL) { - $_POST["edit"]["type"][$type] = "on"; + $_POST['edit']['type'][$type] = 'on'; - return search_form($action, $keys, $options) . "<br />". search_data($keys); + return search_form($action, $keys, $options) . '<br />'. search_data($keys); } /* @} */ @@ -725,22 +772,26 @@ function check_file($filename) { /** * @name Formatting - * @ingroup common * * Functions to format numbers, strings, dates, etc. * @{ */ -function format_rss_channel($title, $link, $description, $items, $language = "en", $args = array()) { +/** + * Formats an RSS channel. + * + * Arbitrary elements may be added using the $args associative array. + */ +function format_rss_channel($title, $link, $description, $items, $language = 'en', $args = array()) { // arbitrary elements may be added using the $args associative array $output = "<channel>\n"; - $output .= " <title>". drupal_specialchars(strip_tags($title)) ."</title>\n"; - $output .= " <link>". drupal_specialchars(strip_tags($link)) ."</link>\n"; - $output .= " <description>". drupal_specialchars(strip_tags($description)) ."</description>\n"; - $output .= " <language>". drupal_specialchars(strip_tags($language)) ."</language>\n"; + $output .= ' <title>'. drupal_specialchars(strip_tags($title)) ."</title>\n"; + $output .= ' <link>'. drupal_specialchars(strip_tags($link)) ."</link>\n"; + $output .= ' <description>'. drupal_specialchars(strip_tags($description)) ."</description>\n"; + $output .= ' <language>'. drupal_specialchars(strip_tags($language)) ."</language>\n"; foreach ($args as $key => $value) { - $output .= " <$key>". drupal_specialchars(strip_tags($value)) ."</$key>\n"; + $output .= ' <'. $key .'>'. drupal_specialchars(strip_tags($value)) ."</$key>\n"; } $output .= $items; $output .= "</channel>\n"; @@ -748,15 +799,18 @@ function format_rss_channel($title, $link, $description, $items, $language = "en return $output; } +/** + * Format a single RSS item. + * + * Arbitrary elements may be added using the $args associative array. + */ function format_rss_item($title, $link, $description, $args = array()) { - // arbitrary elements may be added using the $args associative array - $output = "<item>\n"; - $output .= " <title>". drupal_specialchars(strip_tags($title)) ."</title>\n"; - $output .= " <link>". drupal_specialchars(strip_tags($link)) ."</link>\n"; - $output .= " <description>". drupal_specialchars(check_output($description)) ."</description>\n"; + $output .= ' <title>'. drupal_specialchars(strip_tags($title)) ."</title>\n"; + $output .= ' <link>'. drupal_specialchars(strip_tags($link)) ."</link>\n"; + $output .= ' <description>'. drupal_specialchars(check_output($description)) ."</description>\n"; foreach ($args as $key => $value) { - $output .= "<$key>". drupal_specialchars(strip_tags($value)) ."</$key>"; + $output .= ' <'. $key .'>'. drupal_specialchars(strip_tags($value)) ."</$key>\n"; } $output .= "</item>\n"; @@ -764,56 +818,65 @@ function format_rss_item($title, $link, $description, $args = array()) { } /** - * Formats a string with a count of items so that the string is pluralized - * correctly. format_plural calls t() by itself, make sure not to pass already - * localized strings to it. + * Format a string containing a count of items. * - * @param $count The item count to display. - * @param $singular The string for the singular case. Please make sure it's - * clear this is singular, to ease translation. ("1 new comment" instead of "1 - * new"). - * @param $plural The string for the plural case. Please make sure it's clear - * this is plural, to ease translation. Use %count in places of the item - * count, as in "%count new comments". - * @return Translated string + * This function ensures that the string is pluralized correctly. Since t() is + * called by this function, make sure not to pass already-localized strings to it. + * + * @param $count + * The item count to display. + * @param $singular + * The string for the singular case. Please make sure it is clear this is + * singular, to ease translation (e.g. use "1 new comment" instead of "1 new"). + * @param $plural + * The string for the plural case. Please make sure it is clear this is plural, + * to ease translation. Use %count in place of the item count, as in "%count + * new comments". + * @return + * A translated string. */ function format_plural($count, $singular, $plural) { - return t($count == 1 ? $singular : $plural, array("%count" => $count)); + return t($count == 1 ? $singular : $plural, array('%count' => $count)); } /** - * Generates a string representation for the given byte count. + * Generate a string representation for the given byte count. * - * @param $size The size in bytes - * @return Translated string representation of the size + * @param $size + * The size in bytes. + * @return + * A translated string representation of the size. */ function format_size($size) { - $suffix = t("bytes"); + $suffix = t('bytes'); if ($size > 1024) { $size = round($size / 1024, 2); - $suffix = t("KB"); + $suffix = t('KB'); } if ($size > 1024) { $size = round($size / 1024, 2); - $suffix = t("MB"); + $suffix = t('MB'); } - return t("%size %suffix", array("%size" => $size, "%suffix" => $suffix)); + return t('%size %suffix', array('%size' => $size, '%suffix' => $suffix)); } /** - * Formats a time interval with the requested granularity. + * Format a time interval with the requested granularity. * - * @param $timestamp The length of the interval in seconds - * @param $granularity How much units to consider when generating the string - * @return Translated string representation of the interval + * @param $timestamp + * The length of the interval in seconds. + * @param $granularity + * How many different units to display in the string. + * @return + * A translated string representation of the interval. */ function format_interval($timestamp, $granularity = 2) { - $units = array("1 year|%count years" => 31536000, "1 week|%count weeks" => 604800, "1 day|%count days" => 86400, "1 hour|%count hours" => 3600, "1 min|%count min" => 60, "1 sec|%count sec" => 1); + $units = array('1 year|%count years' => 31536000, '1 week|%count weeks' => 604800, '1 day|%count days' => 86400, '1 hour|%count hours' => 3600, '1 min|%count min' => 60, '1 sec|%count sec' => 1); $output = ''; foreach ($units as $key => $value) { - $key = explode("|", $key); + $key = explode('|', $key); if ($timestamp >= $value) { - $output .= ($output ? " " : "") . format_plural(floor($timestamp / $value), $key[0], $key[1]); + $output .= ($output ? ' ' : '') . format_plural(floor($timestamp / $value), $key[0], $key[1]); $timestamp %= $value; $granularity--; } @@ -822,24 +885,27 @@ function format_interval($timestamp, $granularity = 2) { break; } } - return $output ? $output : t("0 sec"); + return $output ? $output : t('0 sec'); } /** - * Formats a date with the given configured format or a custom format string. + * Format a date with the given configured format or a custom format string. + * * Drupal allows administrators to select formatting strings for 'small', * 'medium' and 'large' date formats. This function can handle these formats, * as well as any custom format. * - * @param $timestamp The exact date to format - * @param $type Could be 'small', 'medium' or 'large' for the preconfigured - * date formats. If 'custom' is specified, the next parameter - * should contain the format string - * @param $format Format string (as required by the PHP date() function). - * Only required if 'custom' date format is requested. - * @param $timezone Timezone offset in seconds in case the user timezone - * should not be used. - * @return Translated date string in the requested format + * @param $timestamp + * The exact date to format, as a UNIX timestamp. + * @param $type + * The format to use. Can be "small", "medium" or "large" for the preconfigured + * date formats. If "custom" is specified, then $format is required as well. + * @param $format + * A PHP date format string as required by date(). + * @param $timezone + * Time zone offset in seconds; if omitted, the user's time zone is used. + * @return + * A translated date string in the requested format. */ function format_date($timestamp, $type = 'medium', $format = '', $timezone = NULL) { if ($timezone === NULL) { @@ -892,40 +958,34 @@ function format_date($timestamp, $type = 'medium', $format = '', $timezone = NUL } /** - * Formats a username. + * Format a username. * - * @param $object User object - * @return String containing a HTML link to the user's page if the - * passed object suggests that this is a site user. Otherwise - * only the user name is returned. + * @param $object + * The user object to format, usually returned from user_load(). + * @return + * A string containing an HTML link to the user's page if the passed object + * suggests that this is a site user. Otherwise, only the username is returned. */ function format_name($object) { if ($object->uid && $object->name) { - /* - ** Shorten the name when it is too long or it will break many - ** tables. - */ - + // Shorten the name when it is too long or it will break many tables. if (strlen($object->name) > 20) { - $name = truncate_utf8($object->name, 15) ."..."; + $name = truncate_utf8($object->name, 15) .'...'; } else { $name = $object->name; } - $output = l($name, "user/$object->uid", array("title" => t("View user profile."))); + $output = l($name, 'user/'. $object->uid, array('title' => t('View user profile.'))); } else if ($object->name) { - /* - ** Sometimes modules display content composed by people who are - ** not registers members of the site (i.e. mailing list or news - ** aggregator modules). This clause enables modules to display - ** the true author of the content. - */ - + // Sometimes modules display content composed by people who are + // not registered members of the site (e.g. mailing list or news + // aggregator modules). This clause enables modules to display + // the true author of the content. if ($object->homepage) { - $output = "<a href=\"$object->homepage\">$object->name</a>"; + $output = '<a href="'. $object->homepage .'">'. $object->name .'</a>'; } else { $output = $object->name; @@ -934,7 +994,7 @@ function format_name($object) { $output .= ' ('. t('not verified') .')'; } else { - $output = t(variable_get("anonymous", "Anonymous")); + $output = t(variable_get('anonymous', 'Anonymous')); } return $output; @@ -942,18 +1002,33 @@ function format_name($object) { /* @} */ /** - * @defgroup from Form generation + * @defgroup form Form generation * @{ */ -function form($form, $method = "post", $action = NULL, $attributes = NULL) { + +/** + * Generate a form from a set of form elements. + * + * @param $form + * An HTML string containing one or more form elements. + * @param $method + * The query method to use ("post" or "get"). + * @param $action + * The URL to send the form contents to, if not the current page. + * @param $attributes + * An associative array of attributes to add to the form tag. + * @result + * An HTML string with the contents of $form wrapped in a form tag. + */ +function form($form, $method = 'post', $action = NULL, $attributes = NULL) { if (!$action) { $action = request_uri(); } - return "<form action=\"$action\" method=\"$method\"". drupal_attributes($attributes) .">\n$form\n</form>\n"; + return '<form action="'. $action .'" method="'. $method .'"'. drupal_attributes($attributes) .">\n". $form ."\n</form>\n"; } /** - * File an error against the form with the specified name. + * File an error against the form element with the specified name. */ function form_set_error($name, $message) { $GLOBALS['form'][$name] = $message; @@ -982,40 +1057,152 @@ function _form_get_class($name, $required, $error) { return $name. ($required ? ' required' : '') . ($error ? ' error' : ''); } +/** + * Format a general form item. + * + * @param $title + * The label for the form item. + * @param $value + * The contents of the form item. + * @param $description + * Explanatory text to display after the form item. + * @param $id + * A unique identifier for the form item. + * @param $required + * Whether the user must fill in this form element before submitting the form. + * @param $error + * An error message to display alongside the form element. + * @return + * A themed HTML string representing the form item. + */ function form_item($title, $value, $description = NULL, $id = NULL, $required = FALSE, $error = FALSE) { return theme('form_element', $title, $value, $description, $id, $required, $error); } +/** + * Format a group of form items. + * + * @param $legend + * The label for the form item group. + * @param $group + * The form items within the group, as an HTML string. + * @param $description + * Explanatory text to display after the form item group. + * @return + * A themed HTML string representing the form item group. + */ function form_group($legend, $group, $description = NULL) { - return "<fieldset>" . ($legend ? "<legend>$legend</legend>" : "") . $group . ($description ? "<div class=\"description\">$description</div>" : "") . "</fieldset>\n"; + return '<fieldset>' . ($legend ? '<legend>'. $legend .'</legend>' : '') . $group . ($description ? '<div class="description">'. $description .'</div>' : '') . "</fieldset>\n"; } -function form_radio($title, $name, $value = 1, $checked = 0, $description = NULL, $attributes = NULL, $required = FALSE) { - $element = "<input type=\"radio\" class=\"". _form_get_class('form-radio', $required, _form_get_error($name)) ."\" name=\"edit[$name]\" value=\"$value\"". ($checked ? " checked=\"checked\"" : "") . drupal_attributes($attributes) .' />'; +/** + * Format a radio button. + * + * @param $title + * The label for the radio button. + * @param $name + * The internal name used to refer to the button. + * @param $value + * The value that the form element takes on when selected. + * @param $checked + * Whether the button will be initially selected when the page is rendered. + * @param $description + * Explanatory text to display after the form item. + * @param $attributes + * An associative array of HTML attributes to add to the button. + * @param $required + * Whether the user must select this radio button before submitting the form. + * @return + * A themed HTML string representing the radio button. + */ +function form_radio($title, $name, $value = 1, $checked = FALSE, $description = NULL, $attributes = NULL, $required = FALSE) { + $element = '<input type="radio" class="'. _form_get_class('form-radio', $required, _form_get_error($name)) .'" name="edit['. $name .']" value="'. $value .'"'. ($checked ? ' checked="checked"' : '') . drupal_attributes($attributes) .' />'; if (!is_null($title)) { - $element = "<label class=\"option\">$element $title</label>"; + $element = '<label class="option">'. $element .' '. $title .'</label>'; } return theme('form_element', NULL, $element, $description, $name, $required, _form_get_error($name)); } +/** + * Format a set of radio buttons. + * + * @param $title + * The label for the radio buttons as a group. + * @param $name + * The internal name used to refer to the buttons. + * @param $value + * The currently selected radio button's key. + * @param $options + * An associative array of buttons to display. The keys in this array are + * button values, while the values are the labels to display for each button. + * @param $description + * Explanatory text to display after the form item. + * @param $required + * Whether the user must select a radio button before submitting the form. + * @param $attributes + * An associative array of HTML attributes to add to each button. + * @return + * A themed HTML string representing the radio button set. + */ function form_radios($title, $name, $value, $options, $description = NULL, $required = FALSE, $attributes = NULL) { if (count($options) > 0) { $choices = ''; foreach ($options as $key => $choice) { - $choices .= "<label class=\"option\"><input type=\"radio\" class=\"form-radio\" name=\"edit[$name]\" value=\"$key\"". ($key == $value ? " checked=\"checked\"" : ""). drupal_attributes($attributes). " /> $choice</label><br />"; + $choices .= '<label class="option"><input type="radio" class="form-radio" name="edit['. $name .']" value="'. $key .'"'. ($key == $value ? ' checked="checked"' : ''). drupal_attributes($attributes). ' /> '. $choice .'</label><br />'; } return theme('form_element', $title, $choices, $description, $name, $required, _form_get_error($name)); } } -function form_checkbox($title, $name, $value = 1, $checked = 0, $description = NULL, $attributes = NULL, $required = FALSE) { - $element = "<input type=\"checkbox\" class=\"". _form_get_class('form-checkbox', $required, _form_get_error($name)) ."\" name=\"edit[$name]\" id=\"edit-$name\" value=\"". $value ."\"". ($checked ? " checked=\"checked\"" : "") . drupal_attributes($attributes) .' />'; +/** + * Format a checkbox. + * + * @param $title + * The label for the checkbox. + * @param $name + * The internal name used to refer to the button. + * @param $value + * The value that the form element takes on when selected. + * @param $checked + * Whether the button will be initially selected when the page is rendered. + * @param $description + * Explanatory text to display after the form item. + * @param $attributes + * An associative array of HTML attributes to add to the button. + * @param $required + * Whether the user must check this box before submitting the form. + * @return + * A themed HTML string representing the checkbox. + */ +function form_checkbox($title, $name, $value = 1, $checked = FALSE, $description = NULL, $attributes = NULL, $required = FALSE) { + $element = '<input type="checkbox" class="'. _form_get_class('form-checkbox', $required, _form_get_error($name)) .'" name="edit['. $name .']" id="edit-'. $name .'" value="'. $value .'"'. ($checked ? ' checked="checked"' : '') . drupal_attributes($attributes) .' />'; if (!is_null($title)) { - $element = "<label class=\"option\">$element $title</label>"; + $element = '<label class="option">'. $element .' '. $title .'</label>'; } return form_hidden($name, 0) . theme('form_element', NULL, $element, $description, $name, $required, _form_get_error($name)); } +/** + * Format a set of checkboxes. + * + * @param $title + * The label for the checkboxes as a group. + * @param $name + * The internal name used to refer to the buttons. + * @param $values + * A linear array of keys of the initally checked boxes. + * @param $options + * An associative array of buttons to display. The keys in this array are + * button values, while the values are the labels to display for each button. + * @param $description + * Explanatory text to display after the form item. + * @param $attributes + * An associative array of HTML attributes to add to each button. + * @param $required + * Whether the user must check a box before submitting the form. + * @return + * A themed HTML string representing the radio button set. + */ function form_checkboxes($title, $name, $values, $options, $description = NULL, $attributes = NULL, $required = FALSE) { if (count($options) > 0) { if (!isset($values)) { @@ -1023,75 +1210,236 @@ function form_checkboxes($title, $name, $values, $options, $description = NULL, } $choices = ''; foreach ($options as $key => $choice) { - $choices .= "<label class=\"option\"><input type=\"checkbox\" class=\"form-checkbox\" name=\"edit[$name][]\" value=\"$key\"". (in_array($key, $values) ? " checked=\"checked\"" : ""). drupal_attributes($attributes). " /> $choice</label><br />"; + $choices .= '<label class="option"><input type="checkbox" class="form-checkbox" name="edit['. $name .'][]" value="'. $key .'"'. (in_array($key, $values) ? ' checked="checked"' : ''). drupal_attributes($attributes). ' /> '. $choice .'</label><br />'; } return theme('form_element', $title, $choices, $description, $name, $required, _form_get_error($name)); } } +/** + * Format a single-line text field. + * + * @param $title + * The label for the text field. + * @param $name + * The internal name used to refer to the field. + * @param $value + * The initial value for the field at page load time. + * @param $size + * A measure of the visible size of the field (passed directly to HTML). + * @param $maxlength + * The maximum number of characters that may be entered in the field. + * @param $description + * Explanatory text to display after the form item. + * @param $attributes + * An associative array of HTML attributes to add to the form item. + * @param $required + * Whether the user must enter some text in the field. + * @return + * A themed HTML string representing the field. + */ function form_textfield($title, $name, $value, $size, $maxlength, $description = NULL, $attributes = NULL, $required = FALSE) { - $size = $size ? " size=\"$size\"" : ""; - return theme('form_element', $title, "<input type=\"text\" maxlength=\"$maxlength\" class=\"". _form_get_class('form-text', $required, _form_get_error($name)) ."\" name=\"edit[$name]\" id=\"$name\"$size value=\"". check_form($value) ."\"". drupal_attributes($attributes) ." />", $description, $name, $required, _form_get_error($name)); + $size = $size ? ' size="'. $size .'"' : ''; + return theme('form_element', $title, '<input type="text" maxlength="'. $maxlength .'" class="'. _form_get_class('form-text', $required, _form_get_error($name)) .'" name="edit['. $name .']" id="'. $name .'"'. $size .' value="'. check_form($value) .'"'. drupal_attributes($attributes) .' />', $description, $name, $required, _form_get_error($name)); } +/** + * Format a single-line text field that does not display its contents visibly. + * + * @param $title + * The label for the text field. + * @param $name + * The internal name used to refer to the field. + * @param $value + * The initial value for the field at page load time. + * @param $size + * A measure of the visible size of the field (passed directly to HTML). + * @param $maxlength + * The maximum number of characters that may be entered in the field. + * @param $description + * Explanatory text to display after the form item. + * @param $attributes + * An associative array of HTML attributes to add to the form item. + * @param $required + * Whether the user must enter some text in the field. + * @return + * A themed HTML string representing the field. + */ function form_password($title, $name, $value, $size, $maxlength, $description = NULL, $attributes = NULL, $required = FALSE) { - $size = $size ? " size=\"$size\"" : ""; - return theme('form_element', $title, "<input type=\"password\" class=\"". _form_get_class('form-password', $required, _form_get_error($name)) ."\" maxlength=\"$maxlength\" name=\"edit[$name]\" id=\"$name\"$size value=\"". check_form($value) ."\"". drupal_attributes($attributes) ." />", $description, $name, $required, _form_get_error($name)); + $size = $size ? ' size="'. $size .'"' : ''; + return theme('form_element', $title, '<input type="password" class="'. _form_get_class('form-password', $required, _form_get_error($name)) .'" maxlength="'. $maxlength .'" name="edit['. $name .']" id="'. $name .'"'. $size .' value="'. check_form($value) .'"'. drupal_attributes($attributes) .' />', $description, $name, $required, _form_get_error($name)); } +/** + * Format a multiple-line text field. + * + * @param $title + * The label for the text field. + * @param $name + * The internal name used to refer to the field. + * @param $value + * The initial value for the field at page load time. + * @param $cols + * The width of the field, in columns of text. + * @param $rows + * The height of the field, in rows of text. + * @param $description + * Explanatory text to display after the form item. + * @param $attributes + * An associative array of HTML attributes to add to the form item. + * @param $required + * Whether the user must enter some text in the field. + * @return + * A themed HTML string representing the field. + */ function form_textarea($title, $name, $value, $cols, $rows, $description = NULL, $attributes = NULL, $required = FALSE) { - $cols = $cols ? " cols=\"$cols\"" : ""; - module_invoke_all("textarea", $name); // eg. optionally plug in a WYSIWYG editor - return theme('form_element', $title, "<textarea wrap=\"virtual\"$cols rows=\"$rows\" name=\"edit[$name]\" id=\"$name\" class=\"". _form_get_class('textarea', $required, _form_get_error($name)) ."\"". drupal_attributes($attributes) .">". check_form($value) ."</textarea>", $description, $name, $required, _form_get_error($name)); + $cols = $cols ? ' cols="'. $cols .'"' : ''; + module_invoke_all('textarea', $name); // eg. optionally plug in a WYSIWYG editor + return theme('form_element', $title, '<textarea wrap="virtual"'. $cols .' rows="'. $rows .'" name="edit['. $name .']" id="'. $name .'" class="'. _form_get_class('textarea', $required, _form_get_error($name)) .'"'. drupal_attributes($attributes) .'>'. check_form($value) .'</textarea>', $description, $name, $required, _form_get_error($name)); } /** - * Outputs a form select item. + * Format a dropdown menu or scrolling selection box. * - * @param $options Array containing the options to choose from. The basic format - * is "value" => "label". If you want to group options together - * (with <optgroup> tags), the format becomes "group name" => - * $options, where $options is an array of "value" => "label" - * pairs. + * @param $title + * The label for the form element. + * @param $name + * The internal name used to refer to the form element. + * @param $value + * The key of the currently selected item, or a linear array of keys of all the + * currently selected items if multiple selections are allowed. + * @param $options + * An associative array of buttons to display. The keys in this array are + * button values, while the values are the labels to display for each button. + * @param $description + * Explanatory text to display after the form item. + * @param $extra + * Additional HTML to inject into the select element tag. + * @param $multiple + * Whether the user may select more than one item. + * @param $required + * Whether the user must select a value before submitting the form. + * @return + * A themed HTML string representing the form element. * - * Examples: - * @verbatim $flavor = array(1 => "Vanilla", 2 => "Chocolate", 3 => "Strawberry"); @endverbatim - * @verbatim $order = array("Food" => array(1 => "Ice cream", 2 => "Hamburger"), "Drink" => array(1 => "Cola", 2 => "Water")); @endverbatim + * It is possible to group options together; to do this, change the format of + * $options to an associative array in which the keys are group labels, and the + * values are associative arrays in the normal $options format. */ -function form_select($title, $name, $value, $options, $description = NULL, $extra = 0, $multiple = 0, $required = FALSE) { +function form_select($title, $name, $value, $options, $description = NULL, $extra = 0, $multiple = FALSE, $required = FALSE) { $select = ''; foreach ($options as $key => $choice) { if (is_array($choice)) { - $select .= "<optgroup label=\"$key\">"; + $select .= '<optgroup label="'. $key .'">'; foreach ($choice as $key => $choice) { - $select .= "<option value=\"$key\"". (is_array($value) ? (in_array($key, $value) ? " selected=\"selected\"" : "") : ($value == $key ? " selected=\"selected\"" : "")) .">". check_form($choice) ."</option>"; + $select .= '<option value="'. $key .'"'. (is_array($value) ? (in_array($key, $value) ? ' selected="selected"' : '') : ($value == $key ? ' selected="selected"' : '')) .'>'. check_form($choice) .'</option>'; } - $select .= "</optgroup>"; + $select .= '</optgroup>'; } else { - $select .= "<option value=\"$key\"". (is_array($value) ? (in_array($key, $value) ? " selected=\"selected\"" : "") : ($value == $key ? " selected=\"selected\"" : "")) .">". check_form($choice) ."</option>"; + $select .= '<option value="'. $key .'"'. (is_array($value) ? (in_array($key, $value) ? ' selected="selected"' : '') : ($value == $key ? ' selected="selected"' : '')) .'>'. check_form($choice) .'</option>'; } } - return theme('form_element', $title, "<select name=\"edit[$name]". ($multiple ? "[]" : "") ."\"". ($multiple ? " multiple=\"multiple\" " : "") . ($extra ? " $extra" : "") ." id=\"$name\">$select</select>", $description, $name, $required, _form_get_error($name)); + return theme('form_element', $title, '<select name="edit['. $name .']'. ($multiple ? '[]' : '') .'"'. ($multiple ? ' multiple="multiple" ' : '') . ($extra ? ' '. $extra : '') .' id="'. $name .'">'. $select .'</select>', $description, $name, $required, _form_get_error($name)); } +/** + * Format a file upload field. + * + * @param $title + * The label for the file upload field. + * @param $name + * The internal name used to refer to the field. + * @param $size + * A measure of the visible size of the field (passed directly to HTML). + * @param $description + * Explanatory text to display after the form item. + * @param $required + * Whether the user must upload a file to the field. + * @return + * A themed HTML string representing the field. + * + * For assistance with handling the uploaded file correctly, see the API + * provided by file.inc. + */ function form_file($title, $name, $size, $description = NULL, $required = FALSE) { - return theme('form_element', $title, "<input type=\"file\" class=\"". _form_get_class('form-file', $required, _form_get_error($name)) ."\" name=\"edit[$name]\" id=\"$name\" size=\"$size\" />\n", $description, $name, $required, _form_get_error($error)); + return theme('form_element', $title, '<input type="file" class="'. _form_get_class('form-file', $required, _form_get_error($name)) .'" name="edit['. $name .']" id="'. $name .'" size="'. $size ."\" />\n", $description, $name, $required, _form_get_error($error)); } +/** + * Store data in a hidden form field. + * + * @param $name + * The internal name used to refer to the field. + * @param $value + * The stored data. + * @return + * A themed HTML string representing the hidden field. + * + * This function can be useful in retaining information between page requests, + * but be sure to validate the data on the receiving page as it is possible for + * an attacker to change the value before it is submitted. + */ function form_hidden($name, $value) { - return "<input type=\"hidden\" name=\"edit[$name]\" value=\"". check_form($value) ."\" />\n"; + return '<input type="hidden" name="edit['. $name .']" value="'. check_form($value) ."\" />\n"; } -function form_button($value, $name = "op", $type = "submit", $attributes = NULL) { - return "<input type=\"$type\" class=\"form-$type\" name=\"$name\" value=\"". check_form($value) ."\" ". drupal_attributes($attributes) ." />\n"; +/** + * Format an action button. + * + * @param $value + * Both the label for the button, and the value passed to the target page + * when this button is clicked. + * @param $name + * The internal name used to refer to the button. + * @param $type + * What type to pass to the HTML input tag. + * @param $attributes + * An associative array of HTML attributes to add to the form item. + * @return + * A themed HTML string representing the button. + */ +function form_button($value, $name = 'op', $type = 'submit', $attributes = NULL) { + return '<input type="'. $type .'" class="form-'. $type .'" name="'. $name .'" value="'. check_form($value) .'" '. drupal_attributes($attributes) ." />\n"; } -function form_submit($value, $name = "op", $attributes = NULL) { - return form_button($value, $name, "submit", $attributes); +/** + * Format a form submit button. + * + * @param $value + * Both the label for the button, and the value passed to the target page + * when this button is clicked. + * @param $name + * The internal name used to refer to the button. + * @param $attributes + * An associative array of HTML attributes to add to the form item. + * @return + * A themed HTML string representing the button. + */ +function form_submit($value, $name = 'op', $attributes = NULL) { + return form_button($value, $name, 'submit', $attributes); } -function form_weight($title = NULL, $name = "weight", $value = 0, $delta = 10, $description = NULL, $extra = 0) { +/** + * Format a weight selection menu. + * + * @param $title + * The label for the form element. + * @param $name + * The internal name used to refer to the form element. + * @param $value + * The selected weight value at page load time. + * @param $delta + * The largest in absolute value the weight can be. For example, if set to 10, + * weights could range from -10 to 10 inclusive. + * @param $description + * Explanatory text to display after the form item. + * @param $extra + * Additional HTML to inject into the select element tag. + * @return + * A themed HTML string representing the form element. + */ +function form_weight($title = NULL, $name = 'weight', $value = 0, $delta = 10, $description = NULL, $extra = 0) { for ($n = (-1 * $delta); $n <= $delta; $n++) { $weights[$n] = $n; } @@ -1100,7 +1448,25 @@ function form_weight($title = NULL, $name = "weight", $value = 0, $delta = 10, $ } /* @} */ -function url($url = NULL, $query = NULL, $fragment = NULL, $absolute = NULL) { +/** + * Generate an internal Drupal URL. + * + * @param $path + * The Drupal path being linked to, such as "admin/node". + * @param $query + * A query string to append to the link. + * @param $fragment + * A fragment identifier (named anchor) to append to the link. + * @param $absolute + * Whether to force the output to be an absolute link (beginning with http:). + * Useful for links that will be displayed outside the site, such as in an RSS feed. + * @return + * an HTML string containing a link to the given path. + * + * When creating links in modules, consider whether l() could be a better + * alternative than url(). + */ +function url($path = NULL, $query = NULL, $fragment = NULL, $absolute = FALSE) { global $base_url; static $script; @@ -1111,68 +1477,99 @@ function url($url = NULL, $query = NULL, $fragment = NULL, $absolute = NULL) { ** generate "index.php?q=foo" instead of "?q=foo" on anything that is not ** Apache. */ - $script = (strpos($_SERVER["SERVER_SOFTWARE"], "Apache") === false) ? "index.php" : ""; + $script = (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') === false) ? 'index.php' : ''; } - $url = drupal_get_path_alias($url); + $path = drupal_get_path_alias($path); if (isset($fragment)) { - $fragment = "#$fragment"; + $fragment = '#'. $fragment; } $base = ($absolute ? $base_url . '/' : ''); - if (variable_get("clean_url", "0") == "0") { - if (isset($url)) { + if (variable_get('clean_url', '0') == '0') { + if (isset($path)) { if (isset($query)) { - return "$base$script?q=$url&$query$fragment"; + return $base . $script .'?q='. $path .'&'. $query . $fragment; } else { - return "$base$script?q=$url$fragment"; + return $base . $script .'?q='. $path . $fragment; } } else { if (isset($query)) { - return "$base$script?$query$fragment"; + return $base . $script .'?'. $query . $fragment; } else { - return "$base$fragment"; + return $base . $fragment; } } } else { - if (isset($url)) { + if (isset($path)) { if (isset($query)) { - return "$base$url?$query$fragment"; + return $base . $path .'?'. $query . $fragment; } else { - return "$base$url$fragment"; + return $base . $path . $fragment; } } else { if (isset($query)) { - return "$base$script?$query$fragment"; + return $base . $script .'?'. $query . $fragment; } else { - return "$base$fragment"; + return $base . $fragment; } } } } +/** + * Format an attribute string to insert in a tag. + * + * @param $attributes + * An associative array of HTML attributes. + * @return + * An HTML string ready for insertion in a tag. + */ function drupal_attributes($attributes = array()) { if ($attributes) { $t = array(); foreach ($attributes as $key => $value) { - $t[] = "$key=\"$value\""; + $t[] = $key .'="'. $value .'"'; } - return " ". implode($t, " "); + return ' '. implode($t, ' '); } } -function l($text, $url, $attributes = array(), $query = NULL, $fragment = NULL, $absolute = NULL) { - if (drupal_get_normal_path($url) == $_GET['q']) { +/** + * Format an internal Drupal link. + * + * This function correctly handles aliased paths, and allows themes to highlight + * links to the current page correctly, so all internal links output by modules + * should be generated by this function if possible. + * + * @param $text + * The text to be enclosed with the anchor tag. + * @param $path + * The Drupal path being linked to, such as "admin/node". + * @param $attributes + * An associative array of HTML attributes to apply to the anchor tag. + * @param $query + * A query string to append to the link. + * @param $fragment + * A fragment identifier (named anchor) to append to the link. + * @param $absolute + * Whether to force the output to be an absolute link (beginning with http:). + * Useful for links that will be displayed outside the site, such as in an RSS feed. + * @return + * an HTML string containing a link to the given path. + */ +function l($text, $path, $attributes = array(), $query = NULL, $fragment = NULL, $absolute = FALSE) { + if (drupal_get_normal_path($path) == $_GET['q']) { if (isset($attributes['class'])) { $attributes['class'] .= ' active'; } @@ -1180,7 +1577,7 @@ function l($text, $url, $attributes = array(), $query = NULL, $fragment = NULL, $attributes['class'] = 'active'; } } - return "<a href=\"". url($url, $query, $fragment, $absolute) ."\"". drupal_attributes($attributes) .">$text</a>"; + return '<a href="'. url($path, $query, $fragment, $absolute) .'"'. drupal_attributes($attributes) .'>'. $text .'</a>'; } function field_get($string, $name) { @@ -1191,11 +1588,16 @@ function field_get($string, $name) { function field_set($string, $name, $value) { $rval = ereg_replace(",$name=[^,]+", "", ",$string"); if (isset($value)) { - $rval .= ($rval == "," ? "" : ",") ."$name=$value"; + $rval .= ($rval == ',' ? '' : ',') . $name .'='. $value; } return substr($rval, 1); } +/** + * Fetch a set of global navigation links. + * + * The links are gathered by calls to hook_link('page') in each module. + */ function link_page() { global $custom_links; @@ -1203,38 +1605,50 @@ function link_page() { return $custom_links; } else { - $links = module_invoke_all("link", "page"); - array_unshift($links, l(t("home"), "", array("title" => t("Return to the main page.")))); + $links = module_invoke_all('link', 'page'); + array_unshift($links, l(t('home'), '', array('title' => t('Return to the main page.')))); return $links; } } +/** + * Fetch a set of links to display after a given node. + * + * The links are gathered by calls to hook_link('node') in each module. + */ function link_node($node, $main = 0) { - return module_invoke_all("link", "node", $node, $main); + return module_invoke_all('link', 'node', $node, $main); } +/** + * Perform end-of-request tasks. + * + * This function sets the page cache if appropriate, and allows modules to + * react to the closing of the page by calling hook_exit(). + */ function drupal_page_footer() { - if (variable_get("cache", 0)) { + if (variable_get('cache', 0)) { page_set_cache(); } - /* - ** A hook for modules where modules may take action at the end of a - ** request good uses include setting a cache, page logging, etc. - */ - - module_invoke_all("exit"); + module_invoke_all('exit'); } /** - * Walks through the provided array and constructs an associative - * array out of it. The keys of the resulting array will be the - * values of the passed array. The values will either be the same - * (if no function was specified), or the results of the function - * given the value. + * Form an associative array from a linear array. * - * @param $array An array - * @param $function A name of a function to apply to all values + * This function walks through the provided array and constructs an associative + * array out of it. The keys of the resulting array will be the values of the + * input array. The values will be the same as the keys unless a function is + * specified, in which case the output of the function is used for the values + * instead. + * + * @param $array + * A linear array. + * @param $function + * The name of a function to apply to all values before output. + * @result + * An associative array. */ function drupal_map_assoc($array, $function = NULL) { if (!isset($function)) { @@ -1254,16 +1668,21 @@ function drupal_map_assoc($array, $function = NULL) { } /** - * Wrapper around xml_parser_create() which extracts the encoding from the XML - * data first and sets the output encoding to UTF-8. This function should be - * used instead of xml_parser_create(), because PHP's XML parser doesn't check + * Prepare a new XML parser. + * + * This is a wrapper around xml_parser_create() which extracts the encoding from + * the XML data first and sets the output encoding to UTF-8. This function should + * be used instead of xml_parser_create(), because PHP's XML parser doesn't check * the input encoding itself. * * This is also where unsupported encodings should be converted. * Callers should take this into account: $data might have been changed after * the call. * - * @param $data The XML data which will be parsed later. + * @param &$data + * The XML data which will be parsed later. + * @return + * An XML parser object. */ function drupal_xml_parser_create(&$data) { $encoding = 'utf-8'; @@ -1287,7 +1706,7 @@ function drupal_xml_parser_create(&$data) { $out = @recode_string($encoding . '..utf-8', $data); } else { - watchdog(t("Unsupported XML encoding '%s'. Please install iconv, GNU recode or mbstring for PHP.", $encoding)); + watchdog(t("Unsupported XML encoding '%s'. Please install iconv, GNU recode or mbstring for PHP.", $encoding)); return 0; } @@ -1296,7 +1715,7 @@ function drupal_xml_parser_create(&$data) { $encoding = 'utf-8'; } else { - watchdog(t("Could not convert XML encoding '%s' to UTF-8.", $encoding)); + watchdog(t("Could not convert XML encoding '%s' to UTF-8.", $encoding)); return 0; } } @@ -1307,7 +1726,8 @@ function drupal_xml_parser_create(&$data) { } /** - * UTF-8-safe string truncation + * Truncate a UTF-8-encoded string safely. + * * If the end position is in the middle of a UTF-8 sequence, it scans backwards * until the beginning of the byte sequence. * @@ -1316,8 +1736,12 @@ function drupal_xml_parser_create(&$data) { * character boundary (e.g. after using strpos or similar), you can safely use * substr() instead. * - * @param $string The string to truncate - * @param $len An upper limit on the returned string length. + * @param $string + * The string to truncate. + * @param $len + * An upper limit on the returned string length. + * @return + * The truncated string. */ function truncate_utf8($string, $len) { $slen = strlen($string); @@ -1331,33 +1755,33 @@ function truncate_utf8($string, $len) { return substr($string, 0, $len); } -include_once "includes/theme.inc"; -include_once "includes/pager.inc"; -include_once "includes/menu.inc"; -include_once "includes/xmlrpc.inc"; -include_once "includes/tablesort.inc"; -include_once "includes/file.inc"; +include_once 'includes/theme.inc'; +include_once 'includes/pager.inc'; +include_once 'includes/menu.inc'; +include_once 'includes/xmlrpc.inc'; +include_once 'includes/tablesort.inc'; +include_once 'includes/file.inc'; // set error handler: -set_error_handler("error_handler"); +set_error_handler('error_handler'); // spit out the correct charset http header -drupal_set_header("Content-Type: text/html; charset=utf-8"); +drupal_set_header('Content-Type: text/html; charset=utf-8'); -// initialize the _GET["q"] prior to loading the modules and invoking their 'init' hook: -if (!empty($_GET["q"])) { - $_GET["q"] = drupal_get_normal_path(trim($_GET["q"], "/")); +// initialize the _GET['q'] prior to loading the modules and invoking their 'init' hook: +if (!empty($_GET['q'])) { + $_GET['q'] = drupal_get_normal_path(trim($_GET['q'], '/')); } else { - $_GET["q"] = drupal_get_normal_path(variable_get("site_frontpage", "node")); + $_GET['q'] = drupal_get_normal_path(variable_get('site_frontpage', 'node')); } // initialize installed modules: module_init(); -if ($_REQUEST && !user_access("bypass input data check")) { +if ($_REQUEST && !user_access('bypass input data check')) { if (!valid_input_data($_REQUEST)) { - die("terminated request because of suspicious input data"); + die('terminated request because of suspicious input data'); } } |