@@ -1,4 +1,71 @@
 | 
			
		||||
 | 
			
		||||
Drupal 7.22, 2013-04-03
 | 
			
		||||
-----------------------
 | 
			
		||||
- Allowed the drupal_http_request() function to be overridden so that
 | 
			
		||||
  additional HTTP request capabilities can be added by contributed modules.
 | 
			
		||||
- Changed the Simpletest module to allow PSR-0 test classes to be used in
 | 
			
		||||
  Drupal 7.
 | 
			
		||||
- Removed an unnecessary "Content-Disposition" header from private file
 | 
			
		||||
  downloads; it prevented many private files from being viewed inline in a web
 | 
			
		||||
  browser.
 | 
			
		||||
- Changed various field API functions to allow them to optionally act on a
 | 
			
		||||
  single field within an entity (API addition: http://drupal.org/node/1825844).
 | 
			
		||||
- Fixed a bug which prevented Drupal's file transfer functionality from working
 | 
			
		||||
  on some PHP 5.4 systems.
 | 
			
		||||
- Fixed incorrect log message when theme() is called for a theme hook that does
 | 
			
		||||
  not exist (minor string change).
 | 
			
		||||
- Fixed Drupal's token-replacement system to allow spaces in the token value.
 | 
			
		||||
- Changed the default behavior after a user creates a node they do not have
 | 
			
		||||
  access to view. The user will now be redirected to the front page rather than
 | 
			
		||||
  an access denied page.
 | 
			
		||||
- Fixed a bug which prevented empty HTTP headers (such as "0") from being set.
 | 
			
		||||
  (Minor behavior change: Callers of drupal_add_http_header() must now set
 | 
			
		||||
  FALSE explicitly to prevent a header from being sent at all; this was already
 | 
			
		||||
  indicated in the function's documentation.)
 | 
			
		||||
- Fixed OpenID errors when more than one module implements hook_openid(). The
 | 
			
		||||
  behavior is now changed so that if more than one module tries to set the same
 | 
			
		||||
  parameter, the last module's change takes effect.
 | 
			
		||||
- Fixed a serious documentation bug: The $name variable in the
 | 
			
		||||
  taxonomy-term.tpl.php theme template was incorrectly documented as being
 | 
			
		||||
  sanitized when in fact it is not.
 | 
			
		||||
- Fixed a bug which prevented Drupal 6 to Drupal 7 upgrades on sites which had
 | 
			
		||||
  duplicate permission names in the User module's database tables.
 | 
			
		||||
- Added an empty "datatype" attribute to taxonomy term and username links to
 | 
			
		||||
  make the RDFa markup upward compatible with RDFa 1.1 (minor markup addition).
 | 
			
		||||
- Fixed a bug which caused the denial-of-service protection added in Drupal
 | 
			
		||||
  7.20 to break certain valid image URLs that had an extra slash in them.
 | 
			
		||||
- Fixed a bug with update queries in the SQLite database driver that prevented
 | 
			
		||||
  Drupal from being installed with SQLite on PHP 5.4.
 | 
			
		||||
- Fixed enforced dependencies errors updating to recent versions of Drupal 7 on
 | 
			
		||||
  certain non-MySQL databases.
 | 
			
		||||
- Refactored the Field module's caching behavior to obtain large improvements
 | 
			
		||||
  in memory usage for sites with many fields and instances (API addition:
 | 
			
		||||
  http://drupal.org/node/1915646).
 | 
			
		||||
- Fixed entity argument not being passed to implementations of
 | 
			
		||||
  hook_file_download_access_alter(). The fix adds an additional context
 | 
			
		||||
  parameter that can be passed when calling drupal_alter() for any hook (API
 | 
			
		||||
  change: http://drupal.org/node/1882722).
 | 
			
		||||
- Fixed broken support for translatable comment fields (API change:
 | 
			
		||||
  http://drupal.org/node/1874724).
 | 
			
		||||
- 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 a 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.
 | 
			
		||||
- Numerous small bug fixes.
 | 
			
		||||
- Numerous API documentation improvements.
 | 
			
		||||
- Additional automated test coverage.
 | 
			
		||||
 | 
			
		||||
Drupal 7.21, 2013-03-06
 | 
			
		||||
-----------------------
 | 
			
		||||
- Allowed sites using the 'image_allow_insecure_derivatives' variable to still
 | 
			
		||||
 
 | 
			
		||||
@@ -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');
 | 
			
		||||
 
 | 
			
		||||
@@ -251,8 +251,8 @@ function ajax_render($commands = array()) {
 | 
			
		||||
      //   reliably diffed with array_diff_key(), since the number can change
 | 
			
		||||
      //   due to factors unrelated to the inline content, so for now, we strip
 | 
			
		||||
      //   the inline items from Ajax responses, and can add support for them
 | 
			
		||||
      //   when drupal_add_css() and drupal_add_js() are changed to using md5()
 | 
			
		||||
      //   or some other hash of the inline content.
 | 
			
		||||
      //   when drupal_add_css() and drupal_add_js() are changed to use a hash
 | 
			
		||||
      //   of the inline content as the array key.
 | 
			
		||||
      foreach ($items[$type] as $key => $item) {
 | 
			
		||||
        if (is_numeric($key)) {
 | 
			
		||||
          unset($items[$type][$key]);
 | 
			
		||||
@@ -836,7 +836,8 @@ function ajax_command_insert($selector, $html, $settings = NULL) {
 | 
			
		||||
 * @return
 | 
			
		||||
 *   An array suitable for use with the ajax_render() function.
 | 
			
		||||
 *
 | 
			
		||||
 * See @link http://docs.jquery.com/Manipulation/replaceWith#content jQuery replaceWith command @endlink
 | 
			
		||||
 * See
 | 
			
		||||
 * @link http://docs.jquery.com/Manipulation/replaceWith#content jQuery replaceWith command @endlink
 | 
			
		||||
 */
 | 
			
		||||
function ajax_command_replace($selector, $html, $settings = NULL) {
 | 
			
		||||
  return array(
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
/**
 | 
			
		||||
 * The current system version.
 | 
			
		||||
 */
 | 
			
		||||
define('VERSION', '7.21');
 | 
			
		||||
define('VERSION', '7.22');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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'] = '';
 | 
			
		||||
    }
 | 
			
		||||
@@ -811,7 +810,7 @@ function drupal_settings_initialize() {
 | 
			
		||||
 *   than by consulting the database.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The filename of the requested item.
 | 
			
		||||
 *   The filename of the requested item or NULL if the item is not found.
 | 
			
		||||
 */
 | 
			
		||||
function drupal_get_filename($type, $name, $filename = NULL) {
 | 
			
		||||
  // The location of files will not change during the request, so do not use
 | 
			
		||||
@@ -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);
 | 
			
		||||
@@ -1212,7 +1212,7 @@ function drupal_send_headers($default_headers = array(), $only_default = FALSE)
 | 
			
		||||
      header($_SERVER['SERVER_PROTOCOL'] . ' ' . $value);
 | 
			
		||||
    }
 | 
			
		||||
    // Skip headers that have been unset.
 | 
			
		||||
    elseif ($value) {
 | 
			
		||||
    elseif ($value !== FALSE) {
 | 
			
		||||
      header($header_names[$name_lower] . ': ' . $value);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -1420,8 +1420,9 @@ function drupal_unpack($obj, $field = 'data') {
 | 
			
		||||
 * Basically, you can put variables like @name into your string, and t() will
 | 
			
		||||
 * substitute their sanitized values at translation time. (See the
 | 
			
		||||
 * Localization API pages referenced above and the documentation of
 | 
			
		||||
 * format_string() for details.) Translators can then rearrange the string as
 | 
			
		||||
 * necessary for the language (e.g., in Spanish, it might be "blog de @name").
 | 
			
		||||
 * format_string() for details about how to define variables in your string.)
 | 
			
		||||
 * Translators can then rearrange the string as necessary for the language
 | 
			
		||||
 * (e.g., in Spanish, it might be "blog de @name").
 | 
			
		||||
 *
 | 
			
		||||
 * During the Drupal installation phase, some resources used by t() wil not be
 | 
			
		||||
 * available to code that needs localization. See st() and get_t() for
 | 
			
		||||
@@ -1484,21 +1485,34 @@ function t($string, array $args = array(), array $options = array()) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Replaces placeholders with sanitized values in a string.
 | 
			
		||||
 * Formats a string for HTML display by replacing variable placeholders.
 | 
			
		||||
 *
 | 
			
		||||
 * This function replaces variable placeholders in a string with the requested
 | 
			
		||||
 * values and escapes the values so they can be safely displayed as HTML. It
 | 
			
		||||
 * should be used on any unknown text that is intended to be printed to an HTML
 | 
			
		||||
 * page (especially text that may have come from untrusted users, since in that
 | 
			
		||||
 * case it prevents cross-site scripting and other security problems).
 | 
			
		||||
 *
 | 
			
		||||
 * In most cases, you should use t() rather than calling this function
 | 
			
		||||
 * directly, since it will translate the text (on non-English-only sites) in
 | 
			
		||||
 * addition to formatting it.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $string
 | 
			
		||||
 *   A string containing placeholders.
 | 
			
		||||
 * @param $args
 | 
			
		||||
 *   An associative array of replacements to make. Occurrences in $string of
 | 
			
		||||
 *   any key in $args are replaced with the corresponding value, after
 | 
			
		||||
 *   sanitization. The sanitization function depends on the first character of
 | 
			
		||||
 *   the key:
 | 
			
		||||
 *   - !variable: Inserted as is. Use this for text that has already been
 | 
			
		||||
 *     sanitized.
 | 
			
		||||
 *   - @variable: Escaped to HTML using check_plain(). Use this for anything
 | 
			
		||||
 *     displayed on a page on the site.
 | 
			
		||||
 *   - %variable: Escaped as a placeholder for user-submitted content using
 | 
			
		||||
 *     drupal_placeholder(), which shows up as <em>emphasized</em> text.
 | 
			
		||||
 *   any key in $args are replaced with the corresponding value, after optional
 | 
			
		||||
 *   sanitization and formatting. The type of sanitization and formatting
 | 
			
		||||
 *   depends on the first character of the key:
 | 
			
		||||
 *   - @variable: Escaped to HTML using check_plain(). Use this as the default
 | 
			
		||||
 *     choice for anything displayed on a page on the site.
 | 
			
		||||
 *   - %variable: Escaped to HTML and formatted using drupal_placeholder(),
 | 
			
		||||
 *     which makes it display as <em>emphasized</em> text.
 | 
			
		||||
 *   - !variable: Inserted as is, with no sanitization or formatting. Only use
 | 
			
		||||
 *     this for text that has already been prepared for HTML display (for
 | 
			
		||||
 *     example, user-supplied text that has already been run through
 | 
			
		||||
 *     check_plain() previously, or is expected to contain some limited HTML
 | 
			
		||||
 *     tags and has already been run through filter_xss() previously).
 | 
			
		||||
 *
 | 
			
		||||
 * @see t()
 | 
			
		||||
 * @ingroup sanitization
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -281,7 +281,7 @@ function drupal_get_rdf_namespaces() {
 | 
			
		||||
/**
 | 
			
		||||
 * Adds output to the HEAD tag of the HTML page.
 | 
			
		||||
 *
 | 
			
		||||
 * This function can be called as long the headers aren't sent. Pass no
 | 
			
		||||
 * This function can be called as long as the headers aren't sent. Pass no
 | 
			
		||||
 * arguments (or NULL for both) to retrieve the currently stored elements.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $data
 | 
			
		||||
@@ -785,6 +785,13 @@ function drupal_access_denied() {
 | 
			
		||||
 *   - data: A string containing the response body that was received.
 | 
			
		||||
 */
 | 
			
		||||
function drupal_http_request($url, array $options = array()) {
 | 
			
		||||
  // Allow an alternate HTTP client library to replace Drupal's default
 | 
			
		||||
  // implementation.
 | 
			
		||||
  $override_function = variable_get('drupal_http_request_function', FALSE);
 | 
			
		||||
  if (!empty($override_function) && function_exists($override_function)) {
 | 
			
		||||
    return $override_function($url, $options);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  $result = new stdClass();
 | 
			
		||||
 | 
			
		||||
  // Parse the URL and make sure we can handle the schema.
 | 
			
		||||
@@ -1167,7 +1174,8 @@ function fix_gpc_magic() {
 | 
			
		||||
/**
 | 
			
		||||
 * Verifies the syntax of the given e-mail address.
 | 
			
		||||
 *
 | 
			
		||||
 * See @link http://tools.ietf.org/html/rfc5321 RFC 5321 @endlink for details.
 | 
			
		||||
 * This uses the
 | 
			
		||||
 * @link http://php.net/manual/filter.filters.validate.php PHP e-mail validation filter. @endlink
 | 
			
		||||
 *
 | 
			
		||||
 * @param $mail
 | 
			
		||||
 *   A string containing an e-mail address.
 | 
			
		||||
@@ -2379,6 +2387,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
 | 
			
		||||
@@ -2779,7 +2795,7 @@ function drupal_set_time_limit($time_limit) {
 | 
			
		||||
 *   The name of the item for which the path is requested.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The path to the requested item.
 | 
			
		||||
 *   The path to the requested item or an empty string if the item is not found.
 | 
			
		||||
 */
 | 
			
		||||
function drupal_get_path($type, $name) {
 | 
			
		||||
  return dirname(drupal_get_filename($type, $name));
 | 
			
		||||
@@ -3869,7 +3885,16 @@ function drupal_html_id($id) {
 | 
			
		||||
      // requested id. $_POST['ajax_html_ids'] contains the ids as they were
 | 
			
		||||
      // returned by this function, potentially with the appended counter, so
 | 
			
		||||
      // we parse that to reconstruct the $seen_ids array.
 | 
			
		||||
      foreach ($_POST['ajax_html_ids'] as $seen_id) {
 | 
			
		||||
      if (is_array($_POST['ajax_html_ids'])) {
 | 
			
		||||
        $ajax_html_ids = $_POST['ajax_html_ids'];
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        // jquery.form.js may send the server a comma-separated string instead
 | 
			
		||||
        // of an array (see http://drupal.org/node/1575060), so we need to
 | 
			
		||||
        // convert it to an array in that case.
 | 
			
		||||
        $ajax_html_ids = explode(',', $_POST['ajax_html_ids']);
 | 
			
		||||
      }
 | 
			
		||||
      foreach ($ajax_html_ids as $seen_id) {
 | 
			
		||||
        // We rely on '--' being used solely for separating a base id from the
 | 
			
		||||
        // counter, which this function ensures when returning an id.
 | 
			
		||||
        $parts = explode('--', $seen_id, 2);
 | 
			
		||||
@@ -5038,6 +5063,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());
 | 
			
		||||
@@ -5568,7 +5598,7 @@ function drupal_pre_render_link($element) {
 | 
			
		||||
 * @code
 | 
			
		||||
 * $node->content['links'] = array(
 | 
			
		||||
 *   '#theme' => 'links__node',
 | 
			
		||||
 *   '#pre_render' = array('drupal_pre_render_links'),
 | 
			
		||||
 *   '#pre_render' => array('drupal_pre_render_links'),
 | 
			
		||||
 *   'comment' => array(
 | 
			
		||||
 *     '#theme' => 'links__node__comment',
 | 
			
		||||
 *     '#links' => array(
 | 
			
		||||
 
 | 
			
		||||
@@ -167,7 +167,7 @@
 | 
			
		||||
 * }
 | 
			
		||||
 * @endcode
 | 
			
		||||
 *
 | 
			
		||||
 * @link http://drupal.org/developing/api/database @endlink
 | 
			
		||||
 * @see http://drupal.org/developing/api/database
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -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,12 +303,28 @@ 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.
 | 
			
		||||
   *
 | 
			
		||||
@@ -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()) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1898,8 +1898,13 @@ class DatabaseCondition implements QueryConditionInterface, Countable {
 | 
			
		||||
  function __clone() {
 | 
			
		||||
    $this->changed = TRUE;
 | 
			
		||||
    foreach ($this->conditions as $key => $condition) {
 | 
			
		||||
      if ($key !== '#conjunction' && $condition['field'] instanceOf QueryConditionInterface) {
 | 
			
		||||
        $this->conditions[$key]['field'] = clone($condition['field']);
 | 
			
		||||
      if ($key !== '#conjunction') {
 | 
			
		||||
        if ($condition['field'] instanceOf QueryConditionInterface) {
 | 
			
		||||
          $this->conditions[$key]['field'] = clone($condition['field']);
 | 
			
		||||
        }
 | 
			
		||||
        if ($condition['value'] instanceOf SelectQueryInterface) {
 | 
			
		||||
          $this->conditions[$key]['value'] = clone($condition['value']);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -57,39 +57,18 @@ class InsertQuery_sqlite extends InsertQuery {
 | 
			
		||||
 * we don't select those rows.
 | 
			
		||||
 *
 | 
			
		||||
 * A query like this one:
 | 
			
		||||
 *   UPDATE test SET name = 'newname' WHERE tid = 1
 | 
			
		||||
 *   UPDATE test SET col1 = 'newcol1', col2 = 'newcol2' WHERE tid = 1
 | 
			
		||||
 * will become:
 | 
			
		||||
 *   UPDATE test SET name = 'newname' WHERE tid = 1 AND name <> 'newname'
 | 
			
		||||
 *   UPDATE test SET col1 = 'newcol1', col2 = 'newcol2' WHERE tid = 1 AND (col1 <> 'newcol1' OR col2 <> 'newcol2')
 | 
			
		||||
 */
 | 
			
		||||
class UpdateQuery_sqlite extends UpdateQuery {
 | 
			
		||||
  /**
 | 
			
		||||
   * Helper function that removes the fields that are already in a condition.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $fields
 | 
			
		||||
   *   The fields.
 | 
			
		||||
   * @param QueryConditionInterface $condition
 | 
			
		||||
   *   A database condition.
 | 
			
		||||
   */
 | 
			
		||||
  protected function removeFieldsInCondition(&$fields, QueryConditionInterface $condition) {
 | 
			
		||||
    foreach ($condition->conditions() as $child_condition) {
 | 
			
		||||
      if ($child_condition['field'] instanceof QueryConditionInterface) {
 | 
			
		||||
        $this->removeFieldsInCondition($fields, $child_condition['field']);
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        unset($fields[$child_condition['field']]);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public function execute() {
 | 
			
		||||
    if (!empty($this->queryOptions['sqlite_return_matched_rows'])) {
 | 
			
		||||
      return parent::execute();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Get the fields used in the update query, and remove those that are already
 | 
			
		||||
    // in the condition.
 | 
			
		||||
    // Get the fields used in the update query.
 | 
			
		||||
    $fields = $this->expressionFields + $this->fields;
 | 
			
		||||
    $this->removeFieldsInCondition($fields, $this->condition);
 | 
			
		||||
 | 
			
		||||
    // Add the inverse of the fields to the condition.
 | 
			
		||||
    $condition = new DatabaseCondition('OR');
 | 
			
		||||
 
 | 
			
		||||
@@ -160,18 +160,6 @@ class DrupalDefaultEntityController implements DrupalEntityControllerInterface {
 | 
			
		||||
  public function load($ids = array(), $conditions = array()) {
 | 
			
		||||
    $entities = array();
 | 
			
		||||
 | 
			
		||||
    # PATCH http://drupal.org/node/1003788#comment-5195682
 | 
			
		||||
    // Clean the $ids array to remove non-integer values that can be passed
 | 
			
		||||
    // in from various sources, including menu callbacks.
 | 
			
		||||
    if (is_array($ids)) {
 | 
			
		||||
      foreach ($ids as $key => $id) {
 | 
			
		||||
        if (empty($id) || ((string) $id !== (string) (int) $id)) {
 | 
			
		||||
          unset($ids[$key]);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    # endpatch
 | 
			
		||||
 | 
			
		||||
    // Revisions are not statically cached, and require a different query to
 | 
			
		||||
    // other conditions, so separate the revision id into its own variable.
 | 
			
		||||
    if ($this->revisionKey && isset($conditions[$this->revisionKey])) {
 | 
			
		||||
 
 | 
			
		||||
@@ -89,7 +89,7 @@ define('FILE_STATUS_PERMANENT', 1);
 | 
			
		||||
 * wrappers that are appropriate for particular usage. For example, this returns
 | 
			
		||||
 * only stream wrappers that use local file storage:
 | 
			
		||||
 * @code
 | 
			
		||||
 *   $local_stream_wrappers = file_get_stream_wrappers(STEAM_WRAPPERS_LOCAL);
 | 
			
		||||
 *   $local_stream_wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL);
 | 
			
		||||
 * @endcode
 | 
			
		||||
 *
 | 
			
		||||
 * The $filter parameter can only filter to types containing a particular flag.
 | 
			
		||||
@@ -99,7 +99,7 @@ define('FILE_STATUS_PERMANENT', 1);
 | 
			
		||||
 * array_diff_key() function can be used to help with this. For example, this
 | 
			
		||||
 * returns only stream wrappers that do not use local file storage:
 | 
			
		||||
 * @code
 | 
			
		||||
 *   $remote_stream_wrappers = array_diff_key(file_get_stream_wrappers(STREAM_WRAPPERS_ALL), file_get_stream_wrappers(STEAM_WRAPPERS_LOCAL));
 | 
			
		||||
 *   $remote_stream_wrappers = array_diff_key(file_get_stream_wrappers(STREAM_WRAPPERS_ALL), file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL));
 | 
			
		||||
 * @endcode
 | 
			
		||||
 *
 | 
			
		||||
 * @param $filter
 | 
			
		||||
@@ -282,10 +282,6 @@ function file_stream_wrapper_uri_normalize($uri) {
 | 
			
		||||
      $uri = $scheme . '://' . $target;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    // The default scheme is file://
 | 
			
		||||
    $url = 'file://' . $uri;
 | 
			
		||||
  }
 | 
			
		||||
  return $uri;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -834,9 +830,8 @@ function file_valid_uri($uri) {
 | 
			
		||||
 *   A string specifying the filepath or URI of the source file.
 | 
			
		||||
 * @param $destination
 | 
			
		||||
 *   A URI containing the destination that $source should be copied to. The
 | 
			
		||||
 *   URI may be a bare filepath (without a scheme) and in that case the default
 | 
			
		||||
 *   scheme (file://) will be used. If this value is omitted, Drupal's default
 | 
			
		||||
 *   files scheme will be used, usually "public://".
 | 
			
		||||
 *   URI may be a bare filepath (without a scheme). If this value is omitted,
 | 
			
		||||
 *   Drupal's default files scheme will be used, usually "public://".
 | 
			
		||||
 * @param $replace
 | 
			
		||||
 *   Replace behavior when the destination file already exists:
 | 
			
		||||
 *   - FILE_EXISTS_REPLACE - Replace the existing file.
 | 
			
		||||
@@ -892,7 +887,7 @@ function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXIST
 | 
			
		||||
  $destination = file_destination($destination, $replace);
 | 
			
		||||
  if ($destination === FALSE) {
 | 
			
		||||
    drupal_set_message(t('The file %file could not be copied because a file by that name already exists in the destination directory.', array('%file' => $original_source)), 'error');
 | 
			
		||||
    watchdog('file', 'File %file could not be copied because a file by that name already exists in the destination directory (%directory)', array('%file' => $original_source, '%destination' => $destination));
 | 
			
		||||
    watchdog('file', 'File %file could not be copied because a file by that name already exists in the destination directory (%directory)', array('%file' => $original_source, '%directory' => $destination));
 | 
			
		||||
    return FALSE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -2481,20 +2476,10 @@ function file_directory_temp() {
 | 
			
		||||
function file_get_content_headers($file) {
 | 
			
		||||
  $name = mime_header_encode($file->filename);
 | 
			
		||||
  $type = mime_header_encode($file->filemime);
 | 
			
		||||
  // Serve images, text, and flash content for display rather than download.
 | 
			
		||||
  $inline_types = variable_get('file_inline_types', array('^text/', '^image/', 'flash$'));
 | 
			
		||||
  $disposition = 'attachment';
 | 
			
		||||
  foreach ($inline_types as $inline_type) {
 | 
			
		||||
    // Exclamation marks are used as delimiters to avoid escaping slashes.
 | 
			
		||||
    if (preg_match('!' . $inline_type . '!', $file->filemime)) {
 | 
			
		||||
      $disposition = 'inline';
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return array(
 | 
			
		||||
    'Content-Type' => $type,
 | 
			
		||||
    'Content-Length' => $file->filesize,
 | 
			
		||||
    'Content-Disposition' => $disposition . '; filename="' . $name . '"',
 | 
			
		||||
    'Cache-Control' => 'private',
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -406,10 +406,20 @@ class SkipDotsRecursiveDirectoryIterator extends RecursiveDirectoryIterator {
 | 
			
		||||
   */
 | 
			
		||||
  function __construct($path) {
 | 
			
		||||
    parent::__construct($path);
 | 
			
		||||
    $this->skipdots();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function rewind() {
 | 
			
		||||
    parent::rewind();
 | 
			
		||||
    $this->skipdots();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function next() {
 | 
			
		||||
    parent::next();
 | 
			
		||||
    $this->skipdots();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected function skipdots() {
 | 
			
		||||
    while ($this->isDot()) {
 | 
			
		||||
      parent::next();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -3058,7 +3058,6 @@ function form_process_radios($element) {
 | 
			
		||||
 */
 | 
			
		||||
function theme_checkbox($variables) {
 | 
			
		||||
  $element = $variables['element'];
 | 
			
		||||
  $t = get_t();
 | 
			
		||||
  $element['#attributes']['type'] = 'checkbox';
 | 
			
		||||
  element_set_attributes($element, array('id', 'name', '#return_value' => 'value'));
 | 
			
		||||
 | 
			
		||||
@@ -3662,35 +3661,6 @@ function form_pre_render_fieldset($element) {
 | 
			
		||||
/**
 | 
			
		||||
 * Creates a group formatted as vertical tabs.
 | 
			
		||||
 *
 | 
			
		||||
 * Note that autocomplete callbacks should include special handling as the
 | 
			
		||||
 * user's input may contain forward slashes. If the user-submitted string has a
 | 
			
		||||
 * '/' in the text that is sent in the autocomplete request, the menu system
 | 
			
		||||
 * will split the text and pass it to the callback as multiple arguments.
 | 
			
		||||
 *
 | 
			
		||||
 * Suppose your autocomplete path in the menu system is 'mymodule_autocomplete.'
 | 
			
		||||
 * In your form you have:
 | 
			
		||||
 * @code
 | 
			
		||||
 * '#autocomplete_path' => 'mymodule_autocomplete/' . $some_key . '/' . $some_id,
 | 
			
		||||
 * @endcode
 | 
			
		||||
 * The user types in "keywords" so the full path called is:
 | 
			
		||||
 * 'mymodule_autocomplete/$some_key/$some_id/keywords'
 | 
			
		||||
 *
 | 
			
		||||
 * You should include code similar to the following to handle slashes in the
 | 
			
		||||
 * input:
 | 
			
		||||
 * @code
 | 
			
		||||
 * function mymodule_autocomplete_callback($arg1, $arg2, $keywords) {
 | 
			
		||||
 *   $args = func_get_args();
 | 
			
		||||
 *   // We need to remove $arg1 and $arg2 from the beginning of the array so we
 | 
			
		||||
 *   // are left with the keywords.
 | 
			
		||||
 *   array_shift($args);
 | 
			
		||||
 *   array_shift($args);
 | 
			
		||||
 *   // We store the user's original input in $keywords, including any slashes.
 | 
			
		||||
 *   $keywords = implode('/', $args);
 | 
			
		||||
 *
 | 
			
		||||
 *   // Your code here.
 | 
			
		||||
 * }
 | 
			
		||||
 * @endcode
 | 
			
		||||
 *
 | 
			
		||||
 * @param $element
 | 
			
		||||
 *   An associative array containing the properties and children of the
 | 
			
		||||
 *   fieldset.
 | 
			
		||||
@@ -4039,8 +4009,6 @@ function theme_file($variables) {
 | 
			
		||||
 */
 | 
			
		||||
function theme_form_element($variables) {
 | 
			
		||||
  $element = &$variables['element'];
 | 
			
		||||
  // This is also used in the installer, pre-database setup.
 | 
			
		||||
  $t = get_t();
 | 
			
		||||
 | 
			
		||||
  // This function is invoked as theme wrapper, but the rendered form element
 | 
			
		||||
  // may not necessarily have been processed by form_builder().
 | 
			
		||||
@@ -4199,7 +4167,7 @@ function _form_set_class(&$element, $class = array()) {
 | 
			
		||||
  if (!empty($element['#required'])) {
 | 
			
		||||
    $element['#attributes']['class'][] = 'required';
 | 
			
		||||
  }
 | 
			
		||||
  if (isset($element['#parents']) && form_get_error($element) !== NULL) {
 | 
			
		||||
  if (isset($element['#parents']) && form_get_error($element) !== NULL && !empty($element['#validated'])) {
 | 
			
		||||
    $element['#attributes']['class'][] = 'error';
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -233,11 +233,11 @@ function image_dimensions_scale(array &$dimensions, $width = NULL, $height = NUL
 | 
			
		||||
 * @param $image
 | 
			
		||||
 *   An image object returned by image_load().
 | 
			
		||||
 * @param $width
 | 
			
		||||
 *   The target width, in pixels. This value is omitted then the scaling will
 | 
			
		||||
 *   based only on the height value.
 | 
			
		||||
 *   The target width, in pixels. If this value is NULL then the scaling will
 | 
			
		||||
 *   be based only on the height value.
 | 
			
		||||
 * @param $height
 | 
			
		||||
 *   The target height, in pixels. This value is omitted then the scaling will
 | 
			
		||||
 *   based only on the width value.
 | 
			
		||||
 *   The target height, in pixels. If this value is NULL then the scaling will
 | 
			
		||||
 *   be based only on the width value.
 | 
			
		||||
 * @param $upscale
 | 
			
		||||
 *   Boolean indicating that files smaller than the dimensions will be scaled
 | 
			
		||||
 *   up. This generally results in a low quality image.
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,9 @@
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * Multiple language handling functionality.
 | 
			
		||||
 * Language Negotiation API.
 | 
			
		||||
 *
 | 
			
		||||
 * @see http://drupal.org/node/1497272
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -11,7 +13,96 @@
 | 
			
		||||
define('LANGUAGE_NEGOTIATION_DEFAULT', 'language-default');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return all the defined language types.
 | 
			
		||||
 * @defgroup language_negotiation Language Negotiation API functionality
 | 
			
		||||
 * @{
 | 
			
		||||
 * Functions to customize the language types and the negotiation process.
 | 
			
		||||
 *
 | 
			
		||||
 * The language negotiation API is based on two major concepts:
 | 
			
		||||
 * - Language types: types of translatable data (the types of data that a user
 | 
			
		||||
 *   can view or request).
 | 
			
		||||
 * - Language negotiation providers: functions for determining which language to
 | 
			
		||||
 *   use to present a particular piece of data to the user.
 | 
			
		||||
 * Both language types and language negotiation providers are customizable.
 | 
			
		||||
 *
 | 
			
		||||
 * Drupal defines three built-in language types:
 | 
			
		||||
 * - Interface language: The page's main language, used to present translated
 | 
			
		||||
 *   user interface elements such as titles, labels, help text, and messages.
 | 
			
		||||
 * - Content language: The language used to present content that is available
 | 
			
		||||
 *   in more than one language (see
 | 
			
		||||
 *   @link field_language Field Language API @endlink for details).
 | 
			
		||||
 * - URL language: The language associated with URLs. When generating a URL,
 | 
			
		||||
 *   this value will be used by url() as a default if no explicit preference is
 | 
			
		||||
 *   provided.
 | 
			
		||||
 * Modules can define additional language types through
 | 
			
		||||
 * hook_language_types_info(), and alter existing language type definitions
 | 
			
		||||
 * through hook_language_types_info_alter().
 | 
			
		||||
 *
 | 
			
		||||
 * Language types may be configurable or fixed. The language negotiation
 | 
			
		||||
 * providers associated with a configurable language type can be explicitly
 | 
			
		||||
 * set through the user interface. A fixed language type has predetermined
 | 
			
		||||
 * (module-defined) language negotiation settings and, thus, does not appear in
 | 
			
		||||
 * the configuration page. Here is a code snippet that makes the content
 | 
			
		||||
 * language (which by default inherits the interface language's values)
 | 
			
		||||
 * configurable:
 | 
			
		||||
 * @code
 | 
			
		||||
 * function mymodule_language_types_info_alter(&$language_types) {
 | 
			
		||||
 *   unset($language_types[LANGUAGE_TYPE_CONTENT]['fixed']);
 | 
			
		||||
 * }
 | 
			
		||||
 * @endcode
 | 
			
		||||
 *
 | 
			
		||||
 * Every language type can have a different set of language negotiation
 | 
			
		||||
 * providers assigned to it. Different language types often share the same
 | 
			
		||||
 * language negotiation settings, but they can have independent settings if
 | 
			
		||||
 * needed. If two language types are configured the same way, their language
 | 
			
		||||
 * switcher configuration will be functionally identical and the same settings
 | 
			
		||||
 * will act on both language types.
 | 
			
		||||
 *
 | 
			
		||||
 * Drupal defines the following built-in language negotiation providers:
 | 
			
		||||
 * - URL: Determine the language from the URL (path prefix or domain).
 | 
			
		||||
 * - Session: Determine the language from a request/session parameter.
 | 
			
		||||
 * - User: Follow the user's language preference.
 | 
			
		||||
 * - Browser: Determine the language from the browser's language settings.
 | 
			
		||||
 * - Default language: Use the default site language.
 | 
			
		||||
 * Language negotiation providers are simple callback functions that implement a
 | 
			
		||||
 * particular logic to return a language code. For instance, the URL provider
 | 
			
		||||
 * searches for a valid path prefix or domain name in the current request URL.
 | 
			
		||||
 * If a language negotiation provider does not return a valid language code, the
 | 
			
		||||
 * next provider associated to the language type (based on provider weight) is
 | 
			
		||||
 * invoked.
 | 
			
		||||
 *
 | 
			
		||||
 * Modules can define additional language negotiation providers through
 | 
			
		||||
 * hook_language_negotiation_info(), and alter existing providers through
 | 
			
		||||
 * hook_language_negotiation_info_alter(). Here is an example snippet that lets
 | 
			
		||||
 * path prefixes be ignored for administrative paths:
 | 
			
		||||
 * @code
 | 
			
		||||
 * function mymodule_language_negotiation_info_alter(&$negotiation_info) {
 | 
			
		||||
 *   // Replace the core function with our own function.
 | 
			
		||||
 *   module_load_include('language', 'inc', 'language.negotiation');
 | 
			
		||||
 *   $negotiation_info[LANGUAGE_NEGOTIATION_URL]['callbacks']['negotiation'] = 'mymodule_from_url';
 | 
			
		||||
 *   $negotiation_info[LANGUAGE_NEGOTIATION_URL]['file'] = drupal_get_path('module', 'mymodule') . '/mymodule.module';
 | 
			
		||||
 * }
 | 
			
		||||
 *
 | 
			
		||||
 * function mymodule_from_url($languages) {
 | 
			
		||||
 *   // Use the core URL language negotiation provider to get a valid language
 | 
			
		||||
 *   // code.
 | 
			
		||||
 *   module_load_include('language', 'inc', 'language.negotiation');
 | 
			
		||||
 *   $langcode = language_from_url($languages);
 | 
			
		||||
 *
 | 
			
		||||
 *   // If we are on an administrative path, override with the default language.
 | 
			
		||||
 *   if (isset($_GET['q']) && strtok($_GET['q'], '/') == 'admin') {
 | 
			
		||||
 *     return language_default()->langcode;
 | 
			
		||||
 *   }
 | 
			
		||||
 *   return $langcode;
 | 
			
		||||
 * }
 | 
			
		||||
 * ?>
 | 
			
		||||
 * @endcode
 | 
			
		||||
 *
 | 
			
		||||
 * For more information, see
 | 
			
		||||
 * @link http://drupal.org/node/1497272 Language Negotiation API @endlink
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns all the defined language types.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   An array of language type names. The name will be used as the global
 | 
			
		||||
@@ -30,11 +121,11 @@ function language_types_info() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return only the configurable language types.
 | 
			
		||||
 * Returns only the configurable language types.
 | 
			
		||||
 *
 | 
			
		||||
 * A language type maybe configurable or fixed. A fixed language type is a type
 | 
			
		||||
 * whose negotiation values are unchangeable and defined while defining the
 | 
			
		||||
 * language type itself.
 | 
			
		||||
 * whose language negotiation providers are module-defined and not altered
 | 
			
		||||
 * through the user interface.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $stored
 | 
			
		||||
 *   Optional. By default retrieves values from the 'language_types' variable to
 | 
			
		||||
@@ -68,7 +159,7 @@ function language_types_configurable($stored = TRUE) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Disable the given language types.
 | 
			
		||||
 * Disables the given language types.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $types
 | 
			
		||||
 *   An array of language types.
 | 
			
		||||
@@ -122,16 +213,17 @@ function language_types_set() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Check if a language provider is enabled.
 | 
			
		||||
 * Checks whether a language negotiation provider is enabled for a language type.
 | 
			
		||||
 *
 | 
			
		||||
 * This has two possible behaviors:
 | 
			
		||||
 *  - If $provider_id is given return its ID if enabled, FALSE otherwise.
 | 
			
		||||
 *  - If no ID is passed the first enabled language provider is returned.
 | 
			
		||||
 *  - If no ID is passed the first enabled language negotiation provider is
 | 
			
		||||
 *    returned.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $type
 | 
			
		||||
 *   The language negotiation type.
 | 
			
		||||
 *   The language negotiation provider type.
 | 
			
		||||
 * @param $provider_id
 | 
			
		||||
 *   The language provider ID.
 | 
			
		||||
 *   The language negotiation provider ID.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The provider ID if it is enabled, FALSE otherwise.
 | 
			
		||||
@@ -155,14 +247,13 @@ function language_negotiation_get($type, $provider_id = NULL) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Check if the given language provider is enabled for any configurable language
 | 
			
		||||
 * type.
 | 
			
		||||
 * Checks if the language negotiation provider is enabled for any language type.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $provider_id
 | 
			
		||||
 *   The language provider ID.
 | 
			
		||||
 *   The language negotiation provider ID.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   TRUE if there is at least one language type for which the give language
 | 
			
		||||
 *   TRUE if there is at least one language type for which the given language
 | 
			
		||||
 *   provider is enabled, FALSE otherwise.
 | 
			
		||||
 */
 | 
			
		||||
function language_negotiation_get_any($provider_id) {
 | 
			
		||||
@@ -176,7 +267,7 @@ function language_negotiation_get_any($provider_id) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return the language switch links for the given language.
 | 
			
		||||
 * Returns the language switch links for the given language.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $type
 | 
			
		||||
 *   The language negotiation type.
 | 
			
		||||
@@ -223,7 +314,7 @@ function language_negotiation_get_switch_links($type, $path) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Updates language configuration to remove any language provider that is no longer defined.
 | 
			
		||||
 * Removes any unused language negotation providers from the configuration.
 | 
			
		||||
 */
 | 
			
		||||
function language_negotiation_purge() {
 | 
			
		||||
  // Ensure that we are getting the defined language negotiation information. An
 | 
			
		||||
@@ -246,12 +337,12 @@ function language_negotiation_purge() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Save a list of language providers.
 | 
			
		||||
 * Saves a list of language negotiation providers.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $type
 | 
			
		||||
 *   The language negotiation type.
 | 
			
		||||
 * @param $language_providers
 | 
			
		||||
 *   An array of language provider weights keyed by id.
 | 
			
		||||
 *   An array of language negotiation provider weights keyed by provider ID.
 | 
			
		||||
 *   @see language_provider_weight()
 | 
			
		||||
 */
 | 
			
		||||
function language_negotiation_set($type, $language_providers) {
 | 
			
		||||
@@ -277,7 +368,7 @@ function language_negotiation_set($type, $language_providers) {
 | 
			
		||||
      // If the provider does not express any preference about types, make it
 | 
			
		||||
      // available for any configurable type.
 | 
			
		||||
      $types = array_flip(isset($provider['types']) ? $provider['types'] : $default_types);
 | 
			
		||||
      // Check if the provider is defined and has the right type.
 | 
			
		||||
      // Check whether the provider is defined and has the right type.
 | 
			
		||||
      if (isset($types[$type])) {
 | 
			
		||||
        $provider_data = array();
 | 
			
		||||
        foreach ($provider_fields as $field) {
 | 
			
		||||
@@ -294,10 +385,10 @@ function language_negotiation_set($type, $language_providers) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return all the defined language providers.
 | 
			
		||||
 * Returns all the defined language negotiation providers.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   An array of language providers.
 | 
			
		||||
 *   An array of language negotiation providers.
 | 
			
		||||
 */
 | 
			
		||||
function language_negotiation_info() {
 | 
			
		||||
  $language_providers = &drupal_static(__FUNCTION__);
 | 
			
		||||
@@ -306,7 +397,7 @@ function language_negotiation_info() {
 | 
			
		||||
    // Collect all the module-defined language negotiation providers.
 | 
			
		||||
    $language_providers = module_invoke_all('language_negotiation_info');
 | 
			
		||||
 | 
			
		||||
    // Add the default language provider.
 | 
			
		||||
    // Add the default language negotiation provider.
 | 
			
		||||
    $language_providers[LANGUAGE_NEGOTIATION_DEFAULT] = array(
 | 
			
		||||
      'callbacks' => array('language' => 'language_from_default'),
 | 
			
		||||
      'weight' => 10,
 | 
			
		||||
@@ -314,7 +405,7 @@ function language_negotiation_info() {
 | 
			
		||||
      'description' => t('Use the default site language (@language_name).', array('@language_name' => language_default()->native)),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Let other modules alter the list of language providers.
 | 
			
		||||
    // Let other modules alter the list of language negotiation providers.
 | 
			
		||||
    drupal_alter('language_negotiation_info', $language_providers);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -322,16 +413,17 @@ function language_negotiation_info() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Helper function used to cache the language providers results.
 | 
			
		||||
 * Helper function used to cache the language negotiation providers results.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $provider_id
 | 
			
		||||
 *   The language provider ID.
 | 
			
		||||
 *   The language negotiation provider's identifier.
 | 
			
		||||
 * @param $provider
 | 
			
		||||
 *   The language provider to be invoked. If not passed it will be explicitly
 | 
			
		||||
 *   loaded through language_negotiation_info().
 | 
			
		||||
 *   (optional) An associative array of information about the provider to be
 | 
			
		||||
 *   invoked (see hook_language_negotiation_info() for details). If not passed
 | 
			
		||||
 *   in, it will be loaded through language_negotiation_info().
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The language provider's return value.
 | 
			
		||||
 *   A language object representing the language chosen by the provider.
 | 
			
		||||
 */
 | 
			
		||||
function language_provider_invoke($provider_id, $provider = NULL) {
 | 
			
		||||
  $results = &drupal_static(__FUNCTION__);
 | 
			
		||||
@@ -352,25 +444,26 @@ function language_provider_invoke($provider_id, $provider = NULL) {
 | 
			
		||||
      require_once DRUPAL_ROOT . '/' . $provider['file'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // If the language provider has no cache preference or this is satisfied
 | 
			
		||||
    // we can execute the callback.
 | 
			
		||||
    // If the language negotiation provider has no cache preference or this is
 | 
			
		||||
    // satisfied we can execute the callback.
 | 
			
		||||
    $cache = !isset($provider['cache']) || $user->uid || $provider['cache'] == variable_get('cache', 0);
 | 
			
		||||
    $callback = isset($provider['callbacks']['language']) ? $provider['callbacks']['language'] : FALSE;
 | 
			
		||||
    $langcode = $cache && function_exists($callback) ? $callback($languages) : FALSE;
 | 
			
		||||
    $results[$provider_id] = isset($languages[$langcode]) ? $languages[$langcode] : FALSE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Since objects are resources we need to return a clone to prevent the
 | 
			
		||||
  // provider cache to be unintentionally altered. The same providers might be
 | 
			
		||||
  // used with different language types based on configuration.
 | 
			
		||||
  // Since objects are resources, we need to return a clone to prevent the
 | 
			
		||||
  // language negotiation provider cache from being unintentionally altered. The
 | 
			
		||||
  // same providers might be used with different language types based on
 | 
			
		||||
  // configuration.
 | 
			
		||||
  return !empty($results[$provider_id]) ? clone($results[$provider_id]) : $results[$provider_id];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return the passed language provider weight or a default value.
 | 
			
		||||
 * Returns the passed language negotiation provider weight or a default value.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $provider
 | 
			
		||||
 *   A language provider data structure.
 | 
			
		||||
 *   A language negotiation provider data structure.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   A numeric weight.
 | 
			
		||||
@@ -381,16 +474,16 @@ function language_provider_weight($provider) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Choose a language for the given type based on language negotiation settings.
 | 
			
		||||
 * Chooses a language based on language negotiation provider settings.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $type
 | 
			
		||||
 *   The language type.
 | 
			
		||||
 *   The language type key to find the language for.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The negotiated language object.
 | 
			
		||||
 */
 | 
			
		||||
function language_initialize($type) {
 | 
			
		||||
  // Execute the language providers in the order they were set up and return the
 | 
			
		||||
  // Execute the language negotiation providers in the order they were set up and return the
 | 
			
		||||
  // first valid language found.
 | 
			
		||||
  $negotiation = variable_get("language_negotiation_$type", array());
 | 
			
		||||
 | 
			
		||||
@@ -409,7 +502,7 @@ function language_initialize($type) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Default language provider.
 | 
			
		||||
 * Returns the default language negotiation provider.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The default language code.
 | 
			
		||||
@@ -421,8 +514,8 @@ function language_from_default() {
 | 
			
		||||
/**
 | 
			
		||||
 * Splits the given path into prefix and actual path.
 | 
			
		||||
 *
 | 
			
		||||
 * Parse the given path and return the language object identified by the
 | 
			
		||||
 * prefix and the actual path.
 | 
			
		||||
 * Parse the given path and return the language object identified by the prefix
 | 
			
		||||
 * and the actual path.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $path
 | 
			
		||||
 *   The path to split.
 | 
			
		||||
@@ -482,3 +575,7 @@ function language_fallback_get_candidates($type = LANGUAGE_TYPE_CONTENT) {
 | 
			
		||||
 | 
			
		||||
  return $fallback_candidates;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @} End of "language_negotiation"
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -93,7 +93,9 @@ define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || strpos($_SERVER['SERVER
 | 
			
		||||
 *   will be {$module}_{$key}.
 | 
			
		||||
 * @param $to
 | 
			
		||||
 *   The e-mail address or addresses where the message will be sent to. The
 | 
			
		||||
 *   formatting of this string must comply with RFC 2822. Some examples are:
 | 
			
		||||
 *   formatting of this string will be validated with the
 | 
			
		||||
 *   @link http://php.net/manual/filter.filters.validate.php PHP e-mail validation filter. @endlink
 | 
			
		||||
 *   Some examples are:
 | 
			
		||||
 *   - user@example.com
 | 
			
		||||
 *   - user@example.com, anotheruser@example.com
 | 
			
		||||
 *   - User <user@example.com>
 | 
			
		||||
@@ -212,9 +214,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}".
 | 
			
		||||
 *
 | 
			
		||||
@@ -307,19 +309,21 @@ interface MailSystemInterface {
 | 
			
		||||
   *   - id: A unique identifier of the e-mail type. Examples: 'contact_user_copy',
 | 
			
		||||
   *     'user_password_reset'.
 | 
			
		||||
   *   - to: The mail address or addresses where the message will be sent to.
 | 
			
		||||
   *     The formatting of this string must comply with RFC 2822. Some examples:
 | 
			
		||||
   *     The formatting of this string will be validated with the
 | 
			
		||||
   *     @link http://php.net/manual/filter.filters.validate.php PHP e-mail validation filter. @endlink
 | 
			
		||||
   *     Some examples are:
 | 
			
		||||
   *     - user@example.com
 | 
			
		||||
   *     - user@example.com, anotheruser@example.com
 | 
			
		||||
   *     - User <user@example.com>
 | 
			
		||||
   *     - User <user@example.com>, Another User <anotheruser@example.com>
 | 
			
		||||
   *    - subject: Subject of the e-mail to be sent. This must not contain any
 | 
			
		||||
   *      newline characters, or the mail may not be sent properly.
 | 
			
		||||
   *    - body: Message to be sent. Accepts both CRLF and LF line-endings.
 | 
			
		||||
   *      E-mail bodies must be wrapped. You can use drupal_wrap_mail() for
 | 
			
		||||
   *      smart plain text wrapping.
 | 
			
		||||
   *    - headers: Associative array containing all additional mail headers not
 | 
			
		||||
   *      defined by one of the other parameters.  PHP's mail() looks for Cc
 | 
			
		||||
   *      and Bcc headers and sends the mail to addresses in these headers too.
 | 
			
		||||
   *   - subject: Subject of the e-mail to be sent. This must not contain any
 | 
			
		||||
   *     newline characters, or the mail may not be sent properly.
 | 
			
		||||
   *   - body: Message to be sent. Accepts both CRLF and LF line-endings.
 | 
			
		||||
   *     E-mail bodies must be wrapped. You can use drupal_wrap_mail() for
 | 
			
		||||
   *     smart plain text wrapping.
 | 
			
		||||
   *   - headers: Associative array containing all additional mail headers not
 | 
			
		||||
   *     defined by one of the other parameters.  PHP's mail() looks for Cc and
 | 
			
		||||
   *     Bcc headers and sends the mail to addresses in these headers too.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   TRUE if the mail was successfully accepted for delivery, otherwise FALSE.
 | 
			
		||||
 
 | 
			
		||||
@@ -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']);
 | 
			
		||||
 
 | 
			
		||||
@@ -898,9 +898,10 @@ function drupal_required_modules() {
 | 
			
		||||
 * hook_TYPE_alter() implementations in modules. It ensures a consistent
 | 
			
		||||
 * interface for all altering operations.
 | 
			
		||||
 *
 | 
			
		||||
 * A maximum of 2 alterable arguments is supported. In case more arguments need
 | 
			
		||||
 * to be passed and alterable, modules provide additional variables assigned by
 | 
			
		||||
 * reference in the last $context argument:
 | 
			
		||||
 * A maximum of 2 alterable arguments is supported (a third is supported for
 | 
			
		||||
 * legacy reasons, but should not be used in new code). In case more arguments
 | 
			
		||||
 * need to be passed and alterable, modules provide additional variables
 | 
			
		||||
 * assigned by reference in the last $context argument:
 | 
			
		||||
 * @code
 | 
			
		||||
 *   $context = array(
 | 
			
		||||
 *     'alterable' => &$alterable,
 | 
			
		||||
@@ -939,8 +940,14 @@ function drupal_required_modules() {
 | 
			
		||||
 *   (optional) An additional variable that is passed by reference. If more
 | 
			
		||||
 *   context needs to be provided to implementations, then this should be an
 | 
			
		||||
 *   associative array as described above.
 | 
			
		||||
 * @param $context3
 | 
			
		||||
 *   (optional) An additional variable that is passed by reference. This
 | 
			
		||||
 *   parameter is deprecated and will not exist in Drupal 8; consequently, it
 | 
			
		||||
 *   should not be used for new Drupal 7 code either. It is here only for
 | 
			
		||||
 *   backwards compatibility with older code that passed additional arguments
 | 
			
		||||
 *   to drupal_alter().
 | 
			
		||||
 */
 | 
			
		||||
function drupal_alter($type, &$data, &$context1 = NULL, &$context2 = NULL) {
 | 
			
		||||
function drupal_alter($type, &$data, &$context1 = NULL, &$context2 = NULL, &$context3 = NULL) {
 | 
			
		||||
  // Use the advanced drupal_static() pattern, since this is called very often.
 | 
			
		||||
  static $drupal_static_fast;
 | 
			
		||||
  if (!isset($drupal_static_fast)) {
 | 
			
		||||
@@ -1053,6 +1060,6 @@ function drupal_alter($type, &$data, &$context1 = NULL, &$context2 = NULL) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  foreach ($functions[$cid] as $function) {
 | 
			
		||||
    $function($data, $context1, $context2);
 | 
			
		||||
    $function($data, $context1, $context2, $context3);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@ function _password_itoa64() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Encode bytes into printable base 64 using the *nix standard from crypt().
 | 
			
		||||
 * Encodes bytes into printable base 64 using the *nix standard from crypt().
 | 
			
		||||
 *
 | 
			
		||||
 * @param $input
 | 
			
		||||
 *   The string containing bytes to encode.
 | 
			
		||||
 
 | 
			
		||||
@@ -386,7 +386,7 @@ function drupal_path_alias_whitelist_rebuild($source = NULL) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Fetch a specific URL alias from the database.
 | 
			
		||||
 * Fetches a specific URL alias from the database.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $conditions
 | 
			
		||||
 *   A string representing the source, a number representing the pid, or an
 | 
			
		||||
@@ -475,11 +475,11 @@ function path_delete($criteria) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Determine whether a path is in the administrative section of the site.
 | 
			
		||||
 * Determines whether a path is in the administrative section of the site.
 | 
			
		||||
 *
 | 
			
		||||
 * By default, paths are considered to be non-administrative. If a path does not
 | 
			
		||||
 * match any of the patterns in path_get_admin_paths(), or if it matches both
 | 
			
		||||
 * administrative and non-administrative patterns, it is considered
 | 
			
		||||
 * By default, paths are considered to be non-administrative. If a path does
 | 
			
		||||
 * not match any of the patterns in path_get_admin_paths(), or if it matches
 | 
			
		||||
 * both administrative and non-administrative patterns, it is considered
 | 
			
		||||
 * non-administrative.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $path
 | 
			
		||||
@@ -503,7 +503,7 @@ function path_is_admin($path) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Get a list of administrative and non-administrative paths.
 | 
			
		||||
 * Gets a list of administrative and non-administrative paths.
 | 
			
		||||
 *
 | 
			
		||||
 * @return array
 | 
			
		||||
 *   An associative array containing the following keys:
 | 
			
		||||
 
 | 
			
		||||
@@ -274,7 +274,7 @@ function drupal_session_initialize() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Forcefully starts a session, preserving already set session data.
 | 
			
		||||
 * Starts a session forcefully, preserving already set session data.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup php_wrappers
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -55,7 +55,7 @@ class TableSort extends SelectQueryExtender {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Initialize the table sort context.
 | 
			
		||||
   * Initializes the table sort context.
 | 
			
		||||
   */
 | 
			
		||||
  protected function init() {
 | 
			
		||||
    $ts = $this->order();
 | 
			
		||||
@@ -115,7 +115,7 @@ function tablesort_init($header) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Format a column header.
 | 
			
		||||
 * Formats a column header.
 | 
			
		||||
 *
 | 
			
		||||
 * If the cell in question is the column header for the current sort criterion,
 | 
			
		||||
 * it gets special formatting. All possible sort criteria become links.
 | 
			
		||||
@@ -126,6 +126,7 @@ function tablesort_init($header) {
 | 
			
		||||
 *   An array of column headers in the format described in theme_table().
 | 
			
		||||
 * @param $ts
 | 
			
		||||
 *   The current table sort context as returned from tablesort_init().
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   A properly formatted cell, ready for _theme_table_cell().
 | 
			
		||||
 */
 | 
			
		||||
@@ -151,7 +152,7 @@ function tablesort_header($cell, $header, $ts) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Format a table cell.
 | 
			
		||||
 * Formats a table cell.
 | 
			
		||||
 *
 | 
			
		||||
 * Adds a class attribute to all cells in the currently active column.
 | 
			
		||||
 *
 | 
			
		||||
@@ -163,6 +164,7 @@ function tablesort_header($cell, $header, $ts) {
 | 
			
		||||
 *   The current table sort context as returned from tablesort_init().
 | 
			
		||||
 * @param $i
 | 
			
		||||
 *   The index of the cell's table column.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   A properly formatted cell, ready for _theme_table_cell().
 | 
			
		||||
 */
 | 
			
		||||
@@ -179,7 +181,7 @@ function tablesort_cell($cell, $header, $ts, $i) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Compose a URL query parameter array for table sorting links.
 | 
			
		||||
 * Composes a URL query parameter array for table sorting links.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   A URL query parameter array that consists of all components of the current
 | 
			
		||||
@@ -190,10 +192,11 @@ function tablesort_get_query_parameters() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Determine the current sort criterion.
 | 
			
		||||
 * Determines the current sort criterion.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $headers
 | 
			
		||||
 *   An array of column headers in the format described in theme_table().
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   An associative array describing the criterion, containing the keys:
 | 
			
		||||
 *   - "name": The localized title of the table column.
 | 
			
		||||
@@ -226,10 +229,11 @@ function tablesort_get_order($headers) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Determine the current sort direction.
 | 
			
		||||
 * Determines the current sort direction.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $headers
 | 
			
		||||
 *   An array of column headers in the format described in theme_table().
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The current sort direction ("asc" or "desc").
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@ function _drupal_theme_access($theme) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Initialize the theme system by loading the theme.
 | 
			
		||||
 * Initializes the theme system by loading the theme.
 | 
			
		||||
 */
 | 
			
		||||
function drupal_theme_initialize() {
 | 
			
		||||
  global $theme, $user, $theme_key;
 | 
			
		||||
@@ -113,8 +113,9 @@ function drupal_theme_initialize() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Initialize the theme system given already loaded information. This
 | 
			
		||||
 * function is useful to initialize a theme when no database is present.
 | 
			
		||||
 * Initializes the theme system given already loaded information.
 | 
			
		||||
 *
 | 
			
		||||
 * This function is useful to initialize a theme when no database is present.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $theme
 | 
			
		||||
 *   An object with the following information:
 | 
			
		||||
@@ -235,7 +236,7 @@ function _drupal_theme_initialize($theme, $base_theme = array(), $registry_callb
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Get the theme registry.
 | 
			
		||||
 * Gets the theme registry.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $complete
 | 
			
		||||
 *   Optional boolean to indicate whether to return the complete theme registry
 | 
			
		||||
@@ -280,7 +281,7 @@ function theme_get_registry($complete = TRUE) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Set the callback that will be used by theme_get_registry() to fetch the registry.
 | 
			
		||||
 * Sets the callback that will be used by theme_get_registry().
 | 
			
		||||
 *
 | 
			
		||||
 * @param $callback
 | 
			
		||||
 *   The name of the callback function.
 | 
			
		||||
@@ -296,7 +297,7 @@ function _theme_registry_callback($callback = NULL, array $arguments = array())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Get the theme_registry cache; if it doesn't exist, build it.
 | 
			
		||||
 * Gets the theme_registry cache; if it doesn't exist, builds it.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $theme
 | 
			
		||||
 *   The loaded $theme object as returned by list_themes().
 | 
			
		||||
@@ -336,16 +337,17 @@ function _theme_load_registry($theme, $base_theme = NULL, $theme_engine = NULL,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Write the theme_registry cache into the database.
 | 
			
		||||
 * Writes the theme_registry cache into the database.
 | 
			
		||||
 */
 | 
			
		||||
function _theme_save_registry($theme, $registry) {
 | 
			
		||||
  cache_set("theme_registry:$theme->name", $registry);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Force the system to rebuild the theme registry; this should be called
 | 
			
		||||
 * when modules are added to the system, or when a dynamic system needs
 | 
			
		||||
 * to add more theme hooks.
 | 
			
		||||
 * Forces the system to rebuild the theme registry.
 | 
			
		||||
 *
 | 
			
		||||
 * This function should be called when modules are added to the system, or when
 | 
			
		||||
 * a dynamic system needs to add more theme hooks.
 | 
			
		||||
 */
 | 
			
		||||
function drupal_theme_rebuild() {
 | 
			
		||||
  drupal_static_reset('theme_get_registry');
 | 
			
		||||
@@ -635,7 +637,8 @@ function _theme_process_registry(&$cache, $name, $type, $theme, $path) {
 | 
			
		||||
    $cache = $result + $cache;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Let themes have variable processors even if they didn't register a template.
 | 
			
		||||
  // Let themes have variable processors even if they didn't register a
 | 
			
		||||
  // template.
 | 
			
		||||
  if ($type == 'theme' || $type == 'base_theme') {
 | 
			
		||||
    foreach ($cache as $hook => $info) {
 | 
			
		||||
      // Check only if not registered by the theme or engine.
 | 
			
		||||
@@ -662,7 +665,7 @@ function _theme_process_registry(&$cache, $name, $type, $theme, $path) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Build the theme registry cache.
 | 
			
		||||
 * Builds the theme registry cache.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $theme
 | 
			
		||||
 *   The loaded $theme object as returned by list_themes().
 | 
			
		||||
@@ -724,7 +727,7 @@ function _theme_build_registry($theme, $base_theme, $theme_engine) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return a list of all currently available themes.
 | 
			
		||||
 * Returns a list of all currently available themes.
 | 
			
		||||
 *
 | 
			
		||||
 * Retrieved from the database, if available and the site is not in maintenance
 | 
			
		||||
 * mode; otherwise compiled freshly from the filesystem.
 | 
			
		||||
@@ -766,7 +769,7 @@ function _theme_build_registry($theme, $base_theme, $theme_engine) {
 | 
			
		||||
 *     their base theme), direct sub-themes of sub-themes, etc. The keys are
 | 
			
		||||
 *     the themes' machine names, and the values are the themes' human-readable
 | 
			
		||||
 *     names. This element is not set if there are no themes on the system that
 | 
			
		||||
 *     declare this theme as their base theme. 
 | 
			
		||||
 *     declare this theme as their base theme.
 | 
			
		||||
*/
 | 
			
		||||
function list_themes($refresh = FALSE) {
 | 
			
		||||
  $list = &drupal_static(__FUNCTION__, array());
 | 
			
		||||
@@ -900,15 +903,15 @@ function drupal_find_base_themes($themes, $key, $used_keys = array()) {
 | 
			
		||||
 * executed (if they exist), in the following order (note that in the following
 | 
			
		||||
 * list, HOOK indicates the theme hook name, MODULE indicates a module name,
 | 
			
		||||
 * THEME indicates a theme name, and ENGINE indicates a theme engine name):
 | 
			
		||||
 * - template_preprocess(&$variables, $hook): Creates a default set of variables
 | 
			
		||||
 *   for all theme hooks with template implementations.
 | 
			
		||||
 * - template_preprocess(&$variables, $hook): Creates a default set of
 | 
			
		||||
 *   variables for all theme hooks with template implementations.
 | 
			
		||||
 * - template_preprocess_HOOK(&$variables): Should be implemented by the module
 | 
			
		||||
 *   that registers the theme hook, to set up default variables.
 | 
			
		||||
 * - MODULE_preprocess(&$variables, $hook): hook_preprocess() is invoked on all
 | 
			
		||||
 *   implementing modules.
 | 
			
		||||
 * - MODULE_preprocess_HOOK(&$variables): hook_preprocess_HOOK() is invoked on
 | 
			
		||||
 *   all implementing modules, so that modules that didn't define the theme hook
 | 
			
		||||
 *   can alter the variables.
 | 
			
		||||
 *   all implementing modules, so that modules that didn't define the theme
 | 
			
		||||
 *   hook can alter the variables.
 | 
			
		||||
 * - ENGINE_engine_preprocess(&$variables, $hook): Allows the theme engine to
 | 
			
		||||
 *   set necessary variables for all theme hooks with template implementations.
 | 
			
		||||
 * - ENGINE_engine_preprocess_HOOK(&$variables): Allows the theme engine to set
 | 
			
		||||
@@ -963,10 +966,10 @@ function drupal_find_base_themes($themes, $key, $used_keys = array()) {
 | 
			
		||||
 * @param $hook
 | 
			
		||||
 *   The name of the theme hook to call. If the name contains a
 | 
			
		||||
 *   double-underscore ('__') and there isn't an implementation for the full
 | 
			
		||||
 *   name, the part before the '__' is checked. This allows a fallback to a more
 | 
			
		||||
 *   generic implementation. For example, if theme('links__node', ...) is
 | 
			
		||||
 *   called, but there is no implementation of that theme hook, then the 'links'
 | 
			
		||||
 *   implementation is used. This process is iterative, so if
 | 
			
		||||
 *   name, the part before the '__' is checked. This allows a fallback to a
 | 
			
		||||
 *   more generic implementation. For example, if theme('links__node', ...) is
 | 
			
		||||
 *   called, but there is no implementation of that theme hook, then the
 | 
			
		||||
 *   'links' implementation is used. This process is iterative, so if
 | 
			
		||||
 *   theme('links__contextual__node', ...) is called, theme() checks for the
 | 
			
		||||
 *   following implementations, and uses the first one that exists:
 | 
			
		||||
 *   - links__contextual__node
 | 
			
		||||
@@ -1030,7 +1033,7 @@ function theme($hook, $variables = array()) {
 | 
			
		||||
      // Only log a message when not trying theme suggestions ($hook being an
 | 
			
		||||
      // array).
 | 
			
		||||
      if (!isset($candidate)) {
 | 
			
		||||
        watchdog('theme', 'Theme key "@key" not found.', array('@key' => $hook), WATCHDOG_WARNING);
 | 
			
		||||
        watchdog('theme', 'Theme hook %hook not found.', array('%hook' => $hook), WATCHDOG_WARNING);
 | 
			
		||||
      }
 | 
			
		||||
      return '';
 | 
			
		||||
    }
 | 
			
		||||
@@ -1042,7 +1045,8 @@ function theme($hook, $variables = array()) {
 | 
			
		||||
  // point path_to_theme() to the currently used theme path:
 | 
			
		||||
  $theme_path = $info['theme path'];
 | 
			
		||||
 | 
			
		||||
  // Include a file if the theme function or variable processor is held elsewhere.
 | 
			
		||||
  // Include a file if the theme function or variable processor is held
 | 
			
		||||
  // elsewhere.
 | 
			
		||||
  if (!empty($info['includes'])) {
 | 
			
		||||
    foreach ($info['includes'] as $include_file) {
 | 
			
		||||
      include_once DRUPAL_ROOT . '/' . $include_file;
 | 
			
		||||
@@ -1191,14 +1195,14 @@ function theme($hook, $variables = array()) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return the path to the current themed element.
 | 
			
		||||
 * Returns the path to the current themed element.
 | 
			
		||||
 *
 | 
			
		||||
 * It can point to the active theme or the module handling a themed implementation.
 | 
			
		||||
 * For example, when invoked within the scope of a theming call it will depend
 | 
			
		||||
 * on where the theming function is handled. If implemented from a module, it
 | 
			
		||||
 * will point to the module. If implemented from the active theme, it will point
 | 
			
		||||
 * to the active theme. When called outside the scope of a theming call, it will
 | 
			
		||||
 * always point to the active theme.
 | 
			
		||||
 * It can point to the active theme or the module handling a themed
 | 
			
		||||
 * implementation. For example, when invoked within the scope of a theming call
 | 
			
		||||
 * it will depend on where the theming function is handled. If implemented from
 | 
			
		||||
 * a module, it will point to the module. If implemented from the active theme,
 | 
			
		||||
 * it will point to the active theme. When called outside the scope of a
 | 
			
		||||
 * theming call, it will always point to the active theme.
 | 
			
		||||
 */
 | 
			
		||||
function path_to_theme() {
 | 
			
		||||
  global $theme_path;
 | 
			
		||||
@@ -1211,7 +1215,7 @@ function path_to_theme() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Allow themes and/or theme engines to easily discover overridden theme functions.
 | 
			
		||||
 * Allows themes and/or theme engines to discover overridden theme functions.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $cache
 | 
			
		||||
 *   The existing cache of theme hooks to test against.
 | 
			
		||||
@@ -1268,7 +1272,7 @@ function drupal_find_theme_functions($cache, $prefixes) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Allow themes and/or theme engines to easily discover overridden templates.
 | 
			
		||||
 * Allows themes and/or theme engines to easily discover overridden templates.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $cache
 | 
			
		||||
 *   The existing cache of theme hooks to test against.
 | 
			
		||||
@@ -1345,7 +1349,8 @@ function drupal_find_theme_templates($cache, $extension, $path) {
 | 
			
		||||
      if ($matches) {
 | 
			
		||||
        foreach ($matches as $match) {
 | 
			
		||||
          $file = substr($match, 0, strpos($match, '.'));
 | 
			
		||||
          // Put the underscores back in for the hook name and register this pattern.
 | 
			
		||||
          // Put the underscores back in for the hook name and register this
 | 
			
		||||
          // pattern.
 | 
			
		||||
          $arg_name = isset($info['variables']) ? 'variables' : 'render element';
 | 
			
		||||
          $implementations[strtr($file, '-', '_')] = array(
 | 
			
		||||
            'template' => $file,
 | 
			
		||||
@@ -1361,7 +1366,7 @@ function drupal_find_theme_templates($cache, $extension, $path) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Retrieve a setting for the current theme or for a given theme.
 | 
			
		||||
 * Retrieves a setting for the current theme or for a given theme.
 | 
			
		||||
 *
 | 
			
		||||
 * The final setting is obtained from the last value found in the following
 | 
			
		||||
 * sources:
 | 
			
		||||
@@ -1479,7 +1484,7 @@ function theme_get_setting($setting_name, $theme = NULL) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Render a system default template, which is essentially a PHP template.
 | 
			
		||||
 * Renders a system default template, which is essentially a PHP template.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $template_file
 | 
			
		||||
 *   The filename of the template to render.
 | 
			
		||||
@@ -1490,14 +1495,21 @@ function theme_get_setting($setting_name, $theme = NULL) {
 | 
			
		||||
 *   The output generated by the template.
 | 
			
		||||
 */
 | 
			
		||||
function theme_render_template($template_file, $variables) {
 | 
			
		||||
  extract($variables, EXTR_SKIP);               // Extract the variables to a local namespace
 | 
			
		||||
  ob_start();                                   // Start output buffering
 | 
			
		||||
  include DRUPAL_ROOT . '/' . $template_file;   // Include the template file
 | 
			
		||||
  return ob_get_clean();                        // End buffering and return its contents
 | 
			
		||||
  // Extract the variables to a local namespace
 | 
			
		||||
  extract($variables, EXTR_SKIP);
 | 
			
		||||
 | 
			
		||||
  // Start output buffering
 | 
			
		||||
  ob_start();
 | 
			
		||||
 | 
			
		||||
  // Include the template file
 | 
			
		||||
  include DRUPAL_ROOT . '/' . $template_file;
 | 
			
		||||
 | 
			
		||||
  // End buffering and return its contents
 | 
			
		||||
  return ob_get_clean();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Enable a given list of themes.
 | 
			
		||||
 * Enables a given list of themes.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $theme_list
 | 
			
		||||
 *   An array of theme names.
 | 
			
		||||
@@ -1522,7 +1534,7 @@ function theme_enable($theme_list) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Disable a given list of themes.
 | 
			
		||||
 * Disables a given list of themes.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $theme_list
 | 
			
		||||
 *   An array of theme names.
 | 
			
		||||
@@ -1608,13 +1620,13 @@ function theme_status_messages($variables) {
 | 
			
		||||
 * theme('link') for rendering the anchor tag.
 | 
			
		||||
 *
 | 
			
		||||
 * To optimize performance for sites that don't need custom theming of links,
 | 
			
		||||
 * the l() function includes an inline copy of this function, and uses that copy
 | 
			
		||||
 * if none of the enabled modules or the active theme implement any preprocess
 | 
			
		||||
 * or process functions or override this theme implementation.
 | 
			
		||||
 * the l() function includes an inline copy of this function, and uses that
 | 
			
		||||
 * copy if none of the enabled modules or the active theme implement any
 | 
			
		||||
 * preprocess or process functions or override this theme implementation.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $variables
 | 
			
		||||
 *   An associative array containing the keys 'text', 'path', and 'options'. See
 | 
			
		||||
 *   the l() function for information about these variables.
 | 
			
		||||
 *   An associative array containing the keys 'text', 'path', and 'options'.
 | 
			
		||||
 *   See the l() function for information about these variables.
 | 
			
		||||
 *
 | 
			
		||||
 * @see l()
 | 
			
		||||
 */
 | 
			
		||||
@@ -1635,15 +1647,16 @@ function theme_link($variables) {
 | 
			
		||||
 *       item in the links list.
 | 
			
		||||
 *     - html: (optional) Whether or not 'title' is HTML. If set, the title
 | 
			
		||||
 *       will not be passed through check_plain().
 | 
			
		||||
 *     - attributes: (optional) Attributes for the anchor, or for the <span> tag
 | 
			
		||||
 *       used in its place if no 'href' is supplied. If element 'class' is
 | 
			
		||||
 *     - attributes: (optional) Attributes for the anchor, or for the <span>
 | 
			
		||||
 *       tag used in its place if no 'href' is supplied. If element 'class' is
 | 
			
		||||
 *       included, it must be an array of one or more class names.
 | 
			
		||||
 *     If the 'href' element is supplied, the entire link array is passed to l()
 | 
			
		||||
 *     as its $options parameter.
 | 
			
		||||
 *     If the 'href' element is supplied, the entire link array is passed to
 | 
			
		||||
 *     l() as its $options parameter.
 | 
			
		||||
 *   - attributes: A keyed array of attributes for the UL containing the
 | 
			
		||||
 *     list of links.
 | 
			
		||||
 *   - heading: (optional) A heading to precede the links. May be an associative
 | 
			
		||||
 *     array or a string. If it's an array, it can have the following elements:
 | 
			
		||||
 *   - heading: (optional) A heading to precede the links. May be an
 | 
			
		||||
 *     associative array or a string. If it's an array, it can have the
 | 
			
		||||
 *     following elements:
 | 
			
		||||
 *     - text: The heading text.
 | 
			
		||||
 *     - level: The heading level (e.g. 'h2', 'h3').
 | 
			
		||||
 *     - class: (optional) An array of the CSS classes for the heading.
 | 
			
		||||
@@ -1747,8 +1760,8 @@ function theme_links($variables) {
 | 
			
		||||
 *     attribute to be omitted in some cases. Therefore, this variable defaults
 | 
			
		||||
 *     to an empty string, but can be set to NULL for the attribute to be
 | 
			
		||||
 *     omitted. Usually, neither omission nor an empty string satisfies
 | 
			
		||||
 *     accessibility requirements, so it is strongly encouraged for code calling
 | 
			
		||||
 *     theme('image') to pass a meaningful value for this variable.
 | 
			
		||||
 *     accessibility requirements, so it is strongly encouraged for code
 | 
			
		||||
 *     calling theme('image') to pass a meaningful value for this variable.
 | 
			
		||||
 *     - http://www.w3.org/TR/REC-html40/struct/objects.html#h-13.8
 | 
			
		||||
 *     - http://www.w3.org/TR/xhtml1/dtds.html
 | 
			
		||||
 *     - http://dev.w3.org/html5/spec/Overview.html#alt
 | 
			
		||||
@@ -2005,7 +2018,8 @@ function theme_table($variables) {
 | 
			
		||||
 *
 | 
			
		||||
 * @param $variables
 | 
			
		||||
 *   An associative array containing:
 | 
			
		||||
 *   - style: Set to either 'asc' or 'desc', this determines which icon to show.
 | 
			
		||||
 *   - style: Set to either 'asc' or 'desc', this determines which icon to
 | 
			
		||||
 *     show.
 | 
			
		||||
 */
 | 
			
		||||
function theme_tablesort_indicator($variables) {
 | 
			
		||||
  if ($variables['style'] == "asc") {
 | 
			
		||||
@@ -2148,7 +2162,8 @@ function theme_feed_icon($variables) {
 | 
			
		||||
 *       - script: To load JavaScript.
 | 
			
		||||
 *     - #attributes: (optional) An array of HTML attributes to apply to the
 | 
			
		||||
 *       tag.
 | 
			
		||||
 *     - #value: (optional) A string containing tag content, such as inline CSS.
 | 
			
		||||
 *     - #value: (optional) A string containing tag content, such as inline
 | 
			
		||||
 *       CSS.
 | 
			
		||||
 *     - #value_prefix: (optional) A string to prepend to #value, e.g. a CDATA
 | 
			
		||||
 *       wrapper prefix.
 | 
			
		||||
 *     - #value_suffix: (optional) A string to append to #value, e.g. a CDATA
 | 
			
		||||
@@ -2316,8 +2331,9 @@ function template_preprocess(&$variables, $hook) {
 | 
			
		||||
  global $user;
 | 
			
		||||
  static $count = array();
 | 
			
		||||
 | 
			
		||||
  // Track run count for each hook to provide zebra striping.
 | 
			
		||||
  // See "template_preprocess_block()" which provides the same feature specific to blocks.
 | 
			
		||||
  // Track run count for each hook to provide zebra striping. See
 | 
			
		||||
  // "template_preprocess_block()" which provides the same feature specific to
 | 
			
		||||
  // blocks.
 | 
			
		||||
  $count[$hook] = isset($count[$hook]) && is_int($count[$hook]) ? $count[$hook] : 1;
 | 
			
		||||
  $variables['zebra'] = ($count[$hook] % 2) ? 'odd' : 'even';
 | 
			
		||||
  $variables['id'] = $count[$hook]++;
 | 
			
		||||
@@ -2677,13 +2693,13 @@ function theme_get_suggestions($args, $base, $delimiter = '__') {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The variables array generated here is a mirror of template_preprocess_page().
 | 
			
		||||
 * This preprocessor will run its course when theme_maintenance_page() is
 | 
			
		||||
 * invoked.
 | 
			
		||||
 * Process variables for maintenance-page.tpl.php.
 | 
			
		||||
 *
 | 
			
		||||
 * An alternate template file of "maintenance-page--offline.tpl.php" can be
 | 
			
		||||
 * used when the database is offline to hide errors and completely replace the
 | 
			
		||||
 * content.
 | 
			
		||||
 * The variables array generated here is a mirror of
 | 
			
		||||
 * template_preprocess_page(). This preprocessor will run its course when
 | 
			
		||||
 * theme_maintenance_page() is invoked. An alternate template file of
 | 
			
		||||
 * maintenance-page--offline.tpl.php can be used when the database is offline to
 | 
			
		||||
 * hide errors and completely replace the content.
 | 
			
		||||
 *
 | 
			
		||||
 * The $variables array contains the following arguments:
 | 
			
		||||
 * - $content
 | 
			
		||||
@@ -2777,10 +2793,13 @@ function template_preprocess_maintenance_page(&$variables) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Theme process function for theme_maintenance_field().
 | 
			
		||||
 *
 | 
			
		||||
 * The variables array generated here is a mirror of template_process_html().
 | 
			
		||||
 * This processor will run its course when theme_maintenance_page() is invoked.
 | 
			
		||||
 *
 | 
			
		||||
 * @see maintenance-page.tpl.php
 | 
			
		||||
 * @see template_process_html()
 | 
			
		||||
 */
 | 
			
		||||
function template_process_maintenance_page(&$variables) {
 | 
			
		||||
  $variables['head']    = drupal_get_html_head();
 | 
			
		||||
@@ -2792,7 +2811,7 @@ function template_process_maintenance_page(&$variables) {
 | 
			
		||||
/**
 | 
			
		||||
 * Preprocess variables for region.tpl.php
 | 
			
		||||
 *
 | 
			
		||||
 * Prepare the values passed to the theme_region function to be passed into a
 | 
			
		||||
 * Prepares the values passed to the theme_region function to be passed into a
 | 
			
		||||
 * pluggable template engine. Uses the region name to generate a template file
 | 
			
		||||
 * suggestions. If none are found, the default region.tpl.php is used.
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
@@ -10,9 +10,9 @@
 | 
			
		||||
 *
 | 
			
		||||
 * Used for site installs, updates and when the site is in maintenance mode.
 | 
			
		||||
 * It also applies when the database is unavailable or bootstrap was not
 | 
			
		||||
 * complete. Seven is always used for the initial install and update operations.
 | 
			
		||||
 * In other cases, Bartik is used, but this can be overridden by setting a
 | 
			
		||||
 * "maintenance_theme" key in the $conf variable in settings.php.
 | 
			
		||||
 * complete. Seven is always used for the initial install and update
 | 
			
		||||
 * operations. In other cases, Bartik is used, but this can be overridden by
 | 
			
		||||
 * setting a "maintenance_theme" key in the $conf variable in settings.php.
 | 
			
		||||
 */
 | 
			
		||||
function _drupal_maintenance_theme() {
 | 
			
		||||
  global $theme, $theme_key, $conf;
 | 
			
		||||
@@ -85,7 +85,7 @@ function _drupal_maintenance_theme() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This builds the registry when the site needs to bypass any database calls.
 | 
			
		||||
 * Builds the registry when the site needs to bypass any database calls.
 | 
			
		||||
 */
 | 
			
		||||
function _theme_load_offline_registry($theme, $base_theme = NULL, $theme_engine = NULL) {
 | 
			
		||||
  return _theme_build_registry($theme, $base_theme, $theme_engine);
 | 
			
		||||
@@ -160,7 +160,7 @@ function theme_update_page($variables) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns HTML for a report of the results from an operation run via authorize.php.
 | 
			
		||||
 * Returns HTML for a results report of an operation run by authorize.php.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $variables
 | 
			
		||||
 *   An associative array containing:
 | 
			
		||||
 
 | 
			
		||||
@@ -113,13 +113,13 @@ function token_replace($text, array $data = array(), array $options = array()) {
 | 
			
		||||
 */
 | 
			
		||||
function token_scan($text) {
 | 
			
		||||
  // Matches tokens with the following pattern: [$type:$name]
 | 
			
		||||
  // $type and $name may not contain  [ ] or whitespace characters.
 | 
			
		||||
  // $type may not contain : characters, but $name may.
 | 
			
		||||
  // $type and $name may not contain  [ ] characters.
 | 
			
		||||
  // $type may not contain : or whitespace characters, but $name may.
 | 
			
		||||
  preg_match_all('/
 | 
			
		||||
    \[             # [ - pattern start
 | 
			
		||||
    ([^\s\[\]:]*)  # match $type not containing whitespace : [ or ]
 | 
			
		||||
    :              # : - separator
 | 
			
		||||
    ([^\s\[\]]*)   # match $name not containing whitespace [ or ]
 | 
			
		||||
    ([^\[\]]*)     # match $name not containing [ or ]
 | 
			
		||||
    \]             # ] - pattern end
 | 
			
		||||
    /x', $text, $matches);
 | 
			
		||||
 | 
			
		||||
@@ -190,10 +190,10 @@ function token_generate($type, array $tokens, array $data = array(), array $opti
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Given a list of tokens, returns those that begin with a specific prefix.
 | 
			
		||||
 * Returns a list of tokens that begin with a specific prefix.
 | 
			
		||||
 *
 | 
			
		||||
 * Used to extract a group of 'chained' tokens (such as [node:author:name]) from
 | 
			
		||||
 * the full list of tokens found in text. For example:
 | 
			
		||||
 * Used to extract a group of 'chained' tokens (such as [node:author:name])
 | 
			
		||||
 * from the full list of tokens found in text. For example:
 | 
			
		||||
 * @code
 | 
			
		||||
 *   $data = array(
 | 
			
		||||
 *     'author:name' => '[node:author:name]',
 | 
			
		||||
@@ -230,8 +230,10 @@ function token_find_with_prefix(array $tokens, $prefix, $delimiter = ':') {
 | 
			
		||||
/**
 | 
			
		||||
 * Returns metadata describing supported tokens.
 | 
			
		||||
 *
 | 
			
		||||
 * The metadata array contains token type, name, and description data as well as
 | 
			
		||||
 * an optional pointer indicating that the token chains to another set of tokens.
 | 
			
		||||
 * The metadata array contains token type, name, and description data as well
 | 
			
		||||
 * as an optional pointer indicating that the token chains to another set of
 | 
			
		||||
 * tokens.
 | 
			
		||||
 *
 | 
			
		||||
 * For example:
 | 
			
		||||
 * @code
 | 
			
		||||
 *   $data['types']['node'] = array(
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,10 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @file
 | 
			
		||||
* Provides Unicode-related conversions and operations.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Indicates an error during check for PHP unicode support.
 | 
			
		||||
 */
 | 
			
		||||
@@ -19,8 +24,6 @@ define('UNICODE_MULTIBYTE', 1);
 | 
			
		||||
/**
 | 
			
		||||
 * Matches Unicode characters that are word boundaries.
 | 
			
		||||
 *
 | 
			
		||||
 * @see http://unicode.org/glossary
 | 
			
		||||
 *
 | 
			
		||||
 * Characters with the following General_category (gc) property values are used
 | 
			
		||||
 * as word boundaries. While this does not fully conform to the Word Boundaries
 | 
			
		||||
 * algorithm described in http://unicode.org/reports/tr29, as PCRE does not
 | 
			
		||||
@@ -39,6 +42,8 @@ define('UNICODE_MULTIBYTE', 1);
 | 
			
		||||
 * Note that the PCRE property matcher is not used because we wanted to be
 | 
			
		||||
 * compatible with Unicode 5.2.0 regardless of the PCRE version used (and any
 | 
			
		||||
 * bugs in PCRE property tables).
 | 
			
		||||
 *
 | 
			
		||||
 * @see http://unicode.org/glossary
 | 
			
		||||
 */
 | 
			
		||||
define('PREG_CLASS_UNICODE_WORD_BOUNDARY',
 | 
			
		||||
  '\x{0}-\x{2F}\x{3A}-\x{40}\x{5B}-\x{60}\x{7B}-\x{A9}\x{AB}-\x{B1}\x{B4}' .
 | 
			
		||||
@@ -125,7 +130,7 @@ function _unicode_check() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return Unicode library status and errors.
 | 
			
		||||
 * Returns Unicode library status and errors.
 | 
			
		||||
 */
 | 
			
		||||
function unicode_requirements() {
 | 
			
		||||
  // Ensure translations don't break during installation.
 | 
			
		||||
@@ -157,14 +162,14 @@ function unicode_requirements() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Prepare a new XML parser.
 | 
			
		||||
 * Prepares 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 4's XML parser doesn't
 | 
			
		||||
 * check the input encoding itself. "Starting from PHP 5, the input encoding is
 | 
			
		||||
 * automatically detected, so that the encoding parameter specifies only the
 | 
			
		||||
 * output encoding."
 | 
			
		||||
 * 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 4's XML parser
 | 
			
		||||
 * doesn't check the input encoding itself. "Starting from PHP 5, the input
 | 
			
		||||
 * encoding is automatically detected, so that the encoding parameter specifies
 | 
			
		||||
 * only the output encoding."
 | 
			
		||||
 *
 | 
			
		||||
 * This is also where unsupported encodings will be converted. Callers should
 | 
			
		||||
 * take this into account: $data might have been changed after the call.
 | 
			
		||||
@@ -213,7 +218,7 @@ function drupal_xml_parser_create(&$data) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Convert data to UTF-8
 | 
			
		||||
 * Converts data to UTF-8.
 | 
			
		||||
 *
 | 
			
		||||
 * Requires the iconv, GNU recode or mbstring PHP extension.
 | 
			
		||||
 *
 | 
			
		||||
@@ -244,15 +249,15 @@ function drupal_convert_to_utf8($data, $encoding) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Truncate a UTF-8-encoded string safely to a number of bytes.
 | 
			
		||||
 * Truncates a UTF-8-encoded string safely to a number of bytes.
 | 
			
		||||
 *
 | 
			
		||||
 * If the end position is in the middle of a UTF-8 sequence, it scans backwards
 | 
			
		||||
 * until the beginning of the byte sequence.
 | 
			
		||||
 *
 | 
			
		||||
 * Use this function whenever you want to chop off a string at an unsure
 | 
			
		||||
 * location. On the other hand, if you're sure that you're splitting on a
 | 
			
		||||
 * character boundary (e.g. after using strpos() or similar), you can safely use
 | 
			
		||||
 * substr() instead.
 | 
			
		||||
 * character boundary (e.g. after using strpos() or similar), you can safely
 | 
			
		||||
 * use substr() instead.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $string
 | 
			
		||||
 *   The string to truncate.
 | 
			
		||||
@@ -306,7 +311,7 @@ function drupal_truncate_bytes($string, $len) {
 | 
			
		||||
 *   boundaries, giving you "See myverylongurl..." (assuming you had set
 | 
			
		||||
 *   $add_ellipses to TRUE).
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 * @return string
 | 
			
		||||
 *   The truncated string.
 | 
			
		||||
 */
 | 
			
		||||
function truncate_utf8($string, $max_length, $wordsafe = FALSE, $add_ellipsis = FALSE, $min_wordsafe_length = 1) {
 | 
			
		||||
@@ -356,8 +361,7 @@ function truncate_utf8($string, $max_length, $wordsafe = FALSE, $add_ellipsis =
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Encodes MIME/HTTP header values that contain non-ASCII, UTF-8 encoded
 | 
			
		||||
 * characters.
 | 
			
		||||
 * Encodes MIME/HTTP header values that contain incorrectly encoded characters.
 | 
			
		||||
 *
 | 
			
		||||
 * For example, mime_header_encode('tést.txt') returns "=?UTF-8?B?dMOpc3QudHh0?=".
 | 
			
		||||
 *
 | 
			
		||||
@@ -369,6 +373,14 @@ function truncate_utf8($string, $max_length, $wordsafe = FALSE, $add_ellipsis =
 | 
			
		||||
 *   each chunk starts and ends on a character boundary.
 | 
			
		||||
 * - Using \n as the chunk separator may cause problems on some systems and may
 | 
			
		||||
 *   have to be changed to \r\n or \r.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $string
 | 
			
		||||
 *   The header to encode.
 | 
			
		||||
 *
 | 
			
		||||
 * @return string
 | 
			
		||||
 *   The mime-encoded header.
 | 
			
		||||
 *
 | 
			
		||||
 * @see mime_header_decode()
 | 
			
		||||
 */
 | 
			
		||||
function mime_header_encode($string) {
 | 
			
		||||
  if (preg_match('/[^\x20-\x7E]/', $string)) {
 | 
			
		||||
@@ -388,7 +400,15 @@ function mime_header_encode($string) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Complement to mime_header_encode
 | 
			
		||||
 * Decodes MIME/HTTP encoded header values.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $header
 | 
			
		||||
 *   The header to decode.
 | 
			
		||||
 *
 | 
			
		||||
 * @return string
 | 
			
		||||
 *   The mime-decoded header.
 | 
			
		||||
 *
 | 
			
		||||
 * @see mime_header_encode()
 | 
			
		||||
 */
 | 
			
		||||
function mime_header_decode($header) {
 | 
			
		||||
  // First step: encoded chunks followed by other encoded chunks (need to collapse whitespace)
 | 
			
		||||
@@ -398,7 +418,17 @@ function mime_header_decode($header) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Helper function to mime_header_decode
 | 
			
		||||
 * Decodes encoded header data passed from mime_header_decode().
 | 
			
		||||
 *
 | 
			
		||||
 * Callback for preg_replace_callback() within mime_header_decode().
 | 
			
		||||
 *
 | 
			
		||||
 * @param $matches
 | 
			
		||||
 *   The array of matches from preg_replace_callback().
 | 
			
		||||
 *
 | 
			
		||||
 * @return string
 | 
			
		||||
 *   The mime-decoded string.
 | 
			
		||||
 *
 | 
			
		||||
 * @see mime_header_decode()
 | 
			
		||||
 */
 | 
			
		||||
function _mime_header_decode($matches) {
 | 
			
		||||
  // Regexp groups:
 | 
			
		||||
@@ -415,9 +445,9 @@ function _mime_header_decode($matches) {
 | 
			
		||||
/**
 | 
			
		||||
 * Decodes all HTML entities (including numerical ones) to regular UTF-8 bytes.
 | 
			
		||||
 *
 | 
			
		||||
 * Double-escaped entities will only be decoded once ("&lt;" becomes "<",
 | 
			
		||||
 * not "<"). Be careful when using this function, as decode_entities can revert
 | 
			
		||||
 * previous sanitization efforts (<script> will become <script>).
 | 
			
		||||
 * Double-escaped entities will only be decoded once ("&lt;" becomes "<"
 | 
			
		||||
 * , not "<"). Be careful when using this function, as decode_entities can
 | 
			
		||||
 * revert previous sanitization efforts (<script> will become <script>).
 | 
			
		||||
 *
 | 
			
		||||
 * @param $text
 | 
			
		||||
 *   The text to decode entities in.
 | 
			
		||||
@@ -430,8 +460,15 @@ function decode_entities($text) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Count the amount of characters in a UTF-8 string. This is less than or
 | 
			
		||||
 * equal to the byte count.
 | 
			
		||||
 * Counts the number of characters in a UTF-8 string.
 | 
			
		||||
 *
 | 
			
		||||
 * This is less than or equal to the byte count.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $text
 | 
			
		||||
 *   The string to run the operation on.
 | 
			
		||||
 *
 | 
			
		||||
 * @return integer
 | 
			
		||||
 *   The length of the string.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup php_wrappers
 | 
			
		||||
 */
 | 
			
		||||
@@ -449,6 +486,12 @@ function drupal_strlen($text) {
 | 
			
		||||
/**
 | 
			
		||||
 * Uppercase a UTF-8 string.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $text
 | 
			
		||||
 *   The string to run the operation on.
 | 
			
		||||
 *
 | 
			
		||||
 * @return string
 | 
			
		||||
 *   The string in uppercase.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup php_wrappers
 | 
			
		||||
 */
 | 
			
		||||
function drupal_strtoupper($text) {
 | 
			
		||||
@@ -468,6 +511,12 @@ function drupal_strtoupper($text) {
 | 
			
		||||
/**
 | 
			
		||||
 * Lowercase a UTF-8 string.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $text
 | 
			
		||||
 *   The string to run the operation on.
 | 
			
		||||
 *
 | 
			
		||||
 * @return string
 | 
			
		||||
 *   The string in lowercase.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup php_wrappers
 | 
			
		||||
 */
 | 
			
		||||
function drupal_strtolower($text) {
 | 
			
		||||
@@ -485,15 +534,28 @@ function drupal_strtolower($text) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Helper function for case conversion of Latin-1.
 | 
			
		||||
 * Used for flipping U+C0-U+DE to U+E0-U+FD and back.
 | 
			
		||||
 * Flips U+C0-U+DE to U+E0-U+FD and back.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $matches
 | 
			
		||||
 *   An array of matches.
 | 
			
		||||
 *
 | 
			
		||||
 * @return array
 | 
			
		||||
 *   The Latin-1 version of the array of matches.
 | 
			
		||||
 *
 | 
			
		||||
 * @see drupal_strtolower()
 | 
			
		||||
 */
 | 
			
		||||
function _unicode_caseflip($matches) {
 | 
			
		||||
  return $matches[0][0] . chr(ord($matches[0][1]) ^ 32);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Capitalize the first letter of a UTF-8 string.
 | 
			
		||||
 * Capitalizes the first letter of a UTF-8 string.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $text
 | 
			
		||||
 *   The string to convert.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The string with the first letter as uppercase.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup php_wrappers
 | 
			
		||||
 */
 | 
			
		||||
@@ -503,12 +565,21 @@ function drupal_ucfirst($text) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Cut off a piece of a string based on character indices and counts. Follows
 | 
			
		||||
 * the same behavior as PHP's own substr() function.
 | 
			
		||||
 * Cuts off a piece of a string based on character indices and counts.
 | 
			
		||||
 *
 | 
			
		||||
 * Note that for cutting off a string at a known character/substring
 | 
			
		||||
 * location, the usage of PHP's normal strpos/substr is safe and
 | 
			
		||||
 * much faster.
 | 
			
		||||
 * Follows the same behavior as PHP's own substr() function. Note that for
 | 
			
		||||
 * cutting off a string at a known character/substring location, the usage of
 | 
			
		||||
 * PHP's normal strpos/substr is safe and much faster.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $text
 | 
			
		||||
 *   The input string.
 | 
			
		||||
 * @param $start
 | 
			
		||||
 *   The position at which to start reading.
 | 
			
		||||
 * @param $length
 | 
			
		||||
 *   The number of characters to read.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The shortened string.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup php_wrappers
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@ function update_fix_compatibility() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Helper function to test compatibility of a module or theme.
 | 
			
		||||
 * Tests the compatibility of a module or theme.
 | 
			
		||||
 */
 | 
			
		||||
function update_check_incompatibility($name, $type = 'module') {
 | 
			
		||||
  static $themes, $modules;
 | 
			
		||||
@@ -908,7 +908,7 @@ function update_get_d6_session_name() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Perform one update and store the results for display on finished page.
 | 
			
		||||
 * Performs one update and stores the results for display on the results page.
 | 
			
		||||
 *
 | 
			
		||||
 * If an update function completes successfully, it should return a message
 | 
			
		||||
 * as a string indicating success, for example:
 | 
			
		||||
@@ -1008,7 +1008,7 @@ function update_do_one($module, $number, $dependency_map, &$context) {
 | 
			
		||||
class DrupalUpdateException extends Exception { }
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Start the database update batch process.
 | 
			
		||||
 * Starts the database update batch process.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $start
 | 
			
		||||
 *   An array whose keys contain the names of modules to be updated during the
 | 
			
		||||
@@ -1078,7 +1078,7 @@ function update_batch($start, $redirect = NULL, $url = NULL, $batch = array(), $
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Finish the update process and store results for eventual display.
 | 
			
		||||
 * Finishes the update process and stores the results for eventual display.
 | 
			
		||||
 *
 | 
			
		||||
 * After the updates run, all caches are flushed. The update results are
 | 
			
		||||
 * stored into the session (for example, to be displayed on the update results
 | 
			
		||||
@@ -1115,7 +1115,7 @@ function update_finished($success, $results, $operations) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return a list of all the pending database updates.
 | 
			
		||||
 * Returns a list of all the pending database updates.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   An associative array keyed by module name which contains all information
 | 
			
		||||
@@ -1409,7 +1409,7 @@ function update_already_performed($module, $number) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Invoke hook_update_dependencies() in all installed modules.
 | 
			
		||||
 * Invokes hook_update_dependencies() in all installed modules.
 | 
			
		||||
 *
 | 
			
		||||
 * This function is similar to module_invoke_all(), with the main difference
 | 
			
		||||
 * that it does not require that a module be enabled to invoke its hook, only
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@
 | 
			
		||||
 *   The variable to export.
 | 
			
		||||
 * @param $prefix
 | 
			
		||||
 *   A prefix that will be added at the beginning of every lines of the output.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The variable exported in a way compatible to Drupal's coding standards.
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -6,12 +6,12 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
define('MAINTENANCE_MODE', 'install');
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -396,7 +396,7 @@ Drupal.ajax.prototype.success = function (response, status) {
 | 
			
		||||
  Drupal.freezeHeight();
 | 
			
		||||
 | 
			
		||||
  for (var i in response) {
 | 
			
		||||
    if (response[i]['command'] && this.commands[response[i]['command']]) {
 | 
			
		||||
    if (response.hasOwnProperty(i) && response[i]['command'] && this.commands[response[i]['command']]) {
 | 
			
		||||
      this.commands[response[i]['command']](this, response[i], status);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -114,7 +114,6 @@ Drupal.jsAC.prototype.onkeyup = function (input, e) {
 | 
			
		||||
 */
 | 
			
		||||
Drupal.jsAC.prototype.select = function (node) {
 | 
			
		||||
  this.input.value = $(node).data('autocompleteValue');
 | 
			
		||||
  $(this.input).trigger('autocompleteSelect', [node]);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -168,7 +167,7 @@ Drupal.jsAC.prototype.unhighlight = function (node) {
 | 
			
		||||
Drupal.jsAC.prototype.hidePopup = function (keycode) {
 | 
			
		||||
  // Select item if the right key or mousebutton was pressed.
 | 
			
		||||
  if (this.selected && ((keycode && keycode != 46 && keycode != 8 && keycode != 27) || !keycode)) {
 | 
			
		||||
    this.select(this.selected);
 | 
			
		||||
    this.input.value = $(this.selected).data('autocompleteValue');
 | 
			
		||||
  }
 | 
			
		||||
  // Hide popup.
 | 
			
		||||
  var popup = this.popup;
 | 
			
		||||
@@ -221,7 +220,7 @@ Drupal.jsAC.prototype.found = function (matches) {
 | 
			
		||||
  for (key in matches) {
 | 
			
		||||
    $('<li></li>')
 | 
			
		||||
      .html($('<div></div>').html(matches[key]))
 | 
			
		||||
      .mousedown(function () { ac.hidePopup(this); })
 | 
			
		||||
      .mousedown(function () { ac.select(this); })
 | 
			
		||||
      .mouseover(function () { ac.highlight(this); })
 | 
			
		||||
      .mouseout(function () { ac.unhighlight(this); })
 | 
			
		||||
      .data('autocompleteValue', key)
 | 
			
		||||
 
 | 
			
		||||
@@ -80,7 +80,7 @@ Drupal.behaviors.machineName = {
 | 
			
		||||
      // changes, but only if there is no machine name yet; i.e., only upon
 | 
			
		||||
      // initial creation, not when editing.
 | 
			
		||||
      if ($target.val() == '') {
 | 
			
		||||
        $source.bind('keyup.machineName change.machineName', function () {
 | 
			
		||||
        $source.bind('keyup.machineName change.machineName input.machineName', function () {
 | 
			
		||||
          machine = self.transliterate($(this).val(), options);
 | 
			
		||||
          // Set the machine name to the transliterated value.
 | 
			
		||||
          if (machine != '') {
 | 
			
		||||
 
 | 
			
		||||
@@ -126,7 +126,7 @@ Drupal.tableHeader.prototype.eventhandlerRecalculateStickyHeader = function (eve
 | 
			
		||||
        $stickyCell.css('display', 'none');
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    this.stickyTable.css('width', this.originalTable.css('width'));
 | 
			
		||||
    this.stickyTable.css('width', this.originalTable.outerWidth());
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,6 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Right-to-Left styles for theme in the Aggregator module.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#aggregator .feed-source .feed-icon {
 | 
			
		||||
  float: left;
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,11 @@
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * Admin page callbacks for the aggregator module.
 | 
			
		||||
 * Administration page callbacks for the Aggregator module.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Menu callback; displays the aggregator administration page.
 | 
			
		||||
 * Page callback: Displays the Aggregator module administration page.
 | 
			
		||||
 */
 | 
			
		||||
function aggregator_admin_overview() {
 | 
			
		||||
  return aggregator_view();
 | 
			
		||||
@@ -16,7 +16,7 @@ function aggregator_admin_overview() {
 | 
			
		||||
 * Displays the aggregator administration page.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The page HTML.
 | 
			
		||||
 *   A HTML-formatted string with administration page content.
 | 
			
		||||
 */
 | 
			
		||||
function aggregator_view() {
 | 
			
		||||
  $result = db_query('SELECT f.fid, f.title, f.url, f.refresh, f.checked, f.link, f.description, f.hash, f.etag, f.modified, f.image, f.block, COUNT(i.iid) AS items FROM {aggregator_feed} f LEFT JOIN {aggregator_item} i ON f.fid = i.fid GROUP BY f.fid, f.title, f.url, f.refresh, f.checked, f.link, f.description, f.hash, f.etag, f.modified, f.image, f.block ORDER BY f.title');
 | 
			
		||||
@@ -56,8 +56,8 @@ function aggregator_view() {
 | 
			
		||||
 * Form constructor for adding and editing feed sources.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $feed
 | 
			
		||||
 *   If editing a feed, the feed to edit as a PHP stdClass value; if adding a
 | 
			
		||||
 *   new feed, NULL.
 | 
			
		||||
 *   (optional) If editing a feed, the feed to edit as a PHP stdClass value; if
 | 
			
		||||
 *   adding a new feed, NULL. Defaults to NULL.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup forms
 | 
			
		||||
 * @see aggregator_form_feed_validate()
 | 
			
		||||
@@ -165,6 +165,7 @@ function aggregator_form_feed_validate($form, &$form_state) {
 | 
			
		||||
 * Form submission handler for aggregator_form_feed().
 | 
			
		||||
 *
 | 
			
		||||
 * @see aggregator_form_feed_validate()
 | 
			
		||||
 *
 | 
			
		||||
 * @todo Add delete confirmation dialog.
 | 
			
		||||
 */
 | 
			
		||||
function aggregator_form_feed_submit($form, &$form_state) {
 | 
			
		||||
@@ -398,7 +399,7 @@ function _aggregator_parse_opml($opml) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Menu callback; refreshes a feed, then redirects to the overview page.
 | 
			
		||||
 * Page callback: Refreshes a feed, then redirects to the overview page.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $feed
 | 
			
		||||
 *   An object describing the feed to be refreshed.
 | 
			
		||||
@@ -590,6 +591,7 @@ function aggregator_form_category_validate($form, &$form_state) {
 | 
			
		||||
 * Form submission handler for aggregator_form_category().
 | 
			
		||||
 *
 | 
			
		||||
 * @see aggregator_form_category_validate()
 | 
			
		||||
 *
 | 
			
		||||
 * @todo Add delete confirmation dialog.
 | 
			
		||||
 */
 | 
			
		||||
function aggregator_form_category_submit($form, &$form_state) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,6 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Styles for theme in the Aggregator module.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#aggregator .feed-source .feed-title {
 | 
			
		||||
  margin-top: 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,8 @@ files[] = aggregator.test
 | 
			
		||||
configure = admin/config/services/aggregator/settings
 | 
			
		||||
stylesheets[all][] = aggregator.css
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -266,13 +266,13 @@ function aggregator_menu() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Title callback: Returns a title for aggregatory category pages.
 | 
			
		||||
 * Title callback: Returns a title for aggregator category pages.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $category
 | 
			
		||||
 *   An aggregator category.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   An aggregator category title.
 | 
			
		||||
 *   A string with the aggregator category title.
 | 
			
		||||
 */
 | 
			
		||||
function _aggregator_category_title($category) {
 | 
			
		||||
  return $category['title'];
 | 
			
		||||
@@ -723,7 +723,7 @@ function theme_aggregator_block_item($variables) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Safely renders HTML content, as allowed.
 | 
			
		||||
 * Renders the HTML content safely, as allowed.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $value
 | 
			
		||||
 *   The content to be filtered.
 | 
			
		||||
@@ -739,7 +739,7 @@ function aggregator_filter_xss($value) {
 | 
			
		||||
 * Checks and sanitizes the aggregator configuration.
 | 
			
		||||
 *
 | 
			
		||||
 * Goes through all fetchers, parsers and processors and checks whether they
 | 
			
		||||
 * are available. If one is missing resets to standard configuration.
 | 
			
		||||
 * are available. If one is missing, resets to standard configuration.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   TRUE if this function resets the configuration; FALSE if not.
 | 
			
		||||
@@ -775,7 +775,7 @@ function aggregator_sanitize_configuration() {
 | 
			
		||||
 *   Items count.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   Plural-formatted "@count items"
 | 
			
		||||
 *   A string that is plural-formatted as "@count items".
 | 
			
		||||
 */
 | 
			
		||||
function _aggregator_items($count) {
 | 
			
		||||
  return format_plural($count, '1 item', '@count items');
 | 
			
		||||
 
 | 
			
		||||
@@ -2,14 +2,14 @@
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * User page callbacks for the aggregator module.
 | 
			
		||||
 * User page callbacks for the Aggregator module.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Menu callback; displays the most recent items gathered from any feed.
 | 
			
		||||
 * Page callback: Displays the most recent items gathered from any feed.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The items HTML.
 | 
			
		||||
 *   The rendered list of items for the feed.
 | 
			
		||||
 */
 | 
			
		||||
function aggregator_page_last() {
 | 
			
		||||
  drupal_add_feed('aggregator/rss', variable_get('site_name', 'Drupal') . ' ' . t('aggregator'));
 | 
			
		||||
@@ -20,13 +20,15 @@ function aggregator_page_last() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Menu callback; displays all the items captured from a particular feed.
 | 
			
		||||
 * Page callback: Displays all the items captured from the particular feed.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $feed
 | 
			
		||||
 *   The feed for which to display all items.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The rendered list of items for a feed.
 | 
			
		||||
 *
 | 
			
		||||
 * @see aggregator_menu()
 | 
			
		||||
 */
 | 
			
		||||
function aggregator_page_source($feed) {
 | 
			
		||||
  drupal_set_title($feed->title);
 | 
			
		||||
@@ -40,13 +42,13 @@ function aggregator_page_source($feed) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Menu callback; displays a form with all items captured from a feed.
 | 
			
		||||
 * Page callback: Displays a form with all items captured from a feed.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $feed
 | 
			
		||||
 *   The feed for which to list all the aggregated items.
 | 
			
		||||
 *   The feed for which to list all of the aggregated items.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The rendered list of items for a feed.
 | 
			
		||||
 *   The rendered list of items for the feed.
 | 
			
		||||
 *
 | 
			
		||||
 * @see aggregator_page_source()
 | 
			
		||||
 */
 | 
			
		||||
@@ -55,13 +57,13 @@ function aggregator_page_source_form($form, $form_state, $feed) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Menu callback; displays all the items aggregated in a particular category.
 | 
			
		||||
 * Page callback: Displays all the items aggregated in a particular category.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $category
 | 
			
		||||
 *   The category for which to list all the aggregated items.
 | 
			
		||||
 *   The category for which to list all of the aggregated items.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
*   The rendered list of items for a category.
 | 
			
		||||
 *   The rendered list of items for the feed.
 | 
			
		||||
 */
 | 
			
		||||
function aggregator_page_category($category) {
 | 
			
		||||
  drupal_add_feed('aggregator/rss/' . $category['cid'], variable_get('site_name', 'Drupal') . ' ' . t('aggregator - @title', array('@title' => $category['title'])));
 | 
			
		||||
@@ -74,13 +76,13 @@ function aggregator_page_category($category) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Menu callback; displays a form containing items aggregated in a category.
 | 
			
		||||
 * Page callback: Displays a form containing items aggregated in a category.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $category
 | 
			
		||||
 *   The category for which to list all the aggregated items.
 | 
			
		||||
 *   The category for which to list all of the aggregated items.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
*   The rendered list of items for a category.
 | 
			
		||||
 *   The rendered list of items for the feed.
 | 
			
		||||
 *
 | 
			
		||||
 * @see aggregator_page_category()
 | 
			
		||||
 */
 | 
			
		||||
@@ -166,7 +168,7 @@ function aggregator_feed_items_load($type, $data = NULL) {
 | 
			
		||||
 *   The feed source URL.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The rendered list of items for a feed.
 | 
			
		||||
 *   The rendered list of items for the feed.
 | 
			
		||||
 */
 | 
			
		||||
function _aggregator_page_list($items, $op, $feed_source = '') {
 | 
			
		||||
  if (user_access('administer news feeds') && ($op == 'categorize')) {
 | 
			
		||||
@@ -191,10 +193,14 @@ function _aggregator_page_list($items, $op, $feed_source = '') {
 | 
			
		||||
 * @param $items
 | 
			
		||||
 *   An array of the feed items.
 | 
			
		||||
 * @param $feed_source
 | 
			
		||||
 *   The feed source URL.
 | 
			
		||||
 *   (optional) The feed source URL. Defaults to an empty string.
 | 
			
		||||
 *
 | 
			
		||||
 * @return array
 | 
			
		||||
 *   An array of FAPI elements.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup forms
 | 
			
		||||
 * @see aggregator_categorize_items_submit()
 | 
			
		||||
 * @see theme_aggregator_categorize_items()
 | 
			
		||||
 * @ingroup forms
 | 
			
		||||
 */
 | 
			
		||||
function aggregator_categorize_items($items, $feed_source = '') {
 | 
			
		||||
  $form['#submit'][] = 'aggregator_categorize_items_submit';
 | 
			
		||||
@@ -334,7 +340,12 @@ function template_preprocess_aggregator_item(&$variables) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Menu callback; displays all the feeds used by the aggregator.
 | 
			
		||||
 * Page callback: Displays all the feeds used by the aggregator.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   An HTML-formatted string.
 | 
			
		||||
 *
 | 
			
		||||
 * @see aggregator_menu()
 | 
			
		||||
 */
 | 
			
		||||
function aggregator_page_sources() {
 | 
			
		||||
  $result = db_query('SELECT f.fid, f.title, f.description, f.image, MAX(i.timestamp) AS last FROM {aggregator_feed} f LEFT JOIN {aggregator_item} i ON f.fid = i.fid GROUP BY f.fid, f.title, f.description, f.image ORDER BY last DESC, f.title');
 | 
			
		||||
@@ -358,7 +369,12 @@ function aggregator_page_sources() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Menu callback; displays all the categories used by the aggregator.
 | 
			
		||||
 * Page callback: Displays all the categories used by the Aggregator module.
 | 
			
		||||
 *
 | 
			
		||||
 * @return string
 | 
			
		||||
 *   An HTML formatted string.
 | 
			
		||||
 *
 | 
			
		||||
 * @see aggregator_menu()
 | 
			
		||||
 */
 | 
			
		||||
function aggregator_page_categories() {
 | 
			
		||||
  $result = db_query('SELECT c.cid, c.title, c.description FROM {aggregator_category} c LEFT JOIN {aggregator_category_item} ci ON c.cid = ci.cid LEFT JOIN {aggregator_item} i ON ci.iid = i.iid GROUP BY c.cid, c.title, c.description');
 | 
			
		||||
@@ -380,7 +396,10 @@ function aggregator_page_categories() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Menu callback; generate an RSS 0.92 feed of aggregator items or categories.
 | 
			
		||||
 * Page callback: Generates an RSS 0.92 feed of aggregator items or categories.
 | 
			
		||||
 *
 | 
			
		||||
 * @return string
 | 
			
		||||
 *   An HTML formatted string.
 | 
			
		||||
 */
 | 
			
		||||
function aggregator_page_rss() {
 | 
			
		||||
  $result = NULL;
 | 
			
		||||
@@ -448,12 +467,14 @@ function theme_aggregator_page_rss($variables) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Menu callback; generates an OPML representation of all feeds.
 | 
			
		||||
 * Page callback: Generates an OPML representation of all feeds.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $cid
 | 
			
		||||
 *   If set, feeds are exported only from a category with this ID. Otherwise, all feeds are exported.
 | 
			
		||||
 *   (optional) If set, feeds are exported only from a category with this ID.
 | 
			
		||||
 *   Otherwise, all feeds are exported. Defaults to NULL.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The output XML.
 | 
			
		||||
 *   An OPML formatted string.
 | 
			
		||||
 */
 | 
			
		||||
function aggregator_page_opml($cid = NULL) {
 | 
			
		||||
  if ($cid) {
 | 
			
		||||
@@ -468,14 +489,12 @@ function aggregator_page_opml($cid = NULL) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Prints the OPML page for a feed.
 | 
			
		||||
 * Prints the OPML page for the feed.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $variables
 | 
			
		||||
 *   An associative array containing:
 | 
			
		||||
 *   - feeds: An array of the feeds to theme.
 | 
			
		||||
 *
 | 
			
		||||
 * @return void
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup themeable
 | 
			
		||||
 */
 | 
			
		||||
function theme_aggregator_page_opml($variables) {
 | 
			
		||||
 
 | 
			
		||||
@@ -131,6 +131,12 @@ function aggregator_form_aggregator_admin_form_alter(&$form, $form_state) {
 | 
			
		||||
 *
 | 
			
		||||
 * Callback for drupal_map_assoc() within
 | 
			
		||||
 * aggregator_form_aggregator_admin_form_alter().
 | 
			
		||||
 *
 | 
			
		||||
 * @param $length
 | 
			
		||||
 *   The desired length of teaser text, in bytes.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   A translated string explaining the teaser string length.
 | 
			
		||||
 */
 | 
			
		||||
function _aggregator_characters($length) {
 | 
			
		||||
  return ($length == 0) ? t('Unlimited') : format_plural($length, '1 character', '@count characters');
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,9 @@
 | 
			
		||||
 * Tests for aggregator.module.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Defines a base class for testing the Aggregator module.
 | 
			
		||||
 */
 | 
			
		||||
class AggregatorTestCase extends DrupalWebTestCase {
 | 
			
		||||
  function setUp() {
 | 
			
		||||
    parent::setUp('aggregator', 'aggregator_test');
 | 
			
		||||
@@ -13,10 +16,15 @@ class AggregatorTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create an aggregator feed (simulate form submission on admin/config/services/aggregator/add/feed).
 | 
			
		||||
   * Creates an aggregator feed.
 | 
			
		||||
   *
 | 
			
		||||
   * This method simulates the form submission on path
 | 
			
		||||
   * admin/config/services/aggregator/add/feed.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $feed_url
 | 
			
		||||
   *   If given, feed will be created with this URL, otherwise /rss.xml will be used.
 | 
			
		||||
   *   (optional) If given, feed will be created with this URL, otherwise
 | 
			
		||||
   *   /rss.xml will be used. Defaults to NULL.
 | 
			
		||||
   *
 | 
			
		||||
   * @return $feed
 | 
			
		||||
   *   Full feed object if possible.
 | 
			
		||||
   *
 | 
			
		||||
@@ -33,7 +41,7 @@ class AggregatorTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Delete an aggregator feed.
 | 
			
		||||
   * Deletes an aggregator feed.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $feed
 | 
			
		||||
   *   Feed object representing the feed.
 | 
			
		||||
@@ -44,10 +52,11 @@ class AggregatorTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Return a randomly generated feed edit array.
 | 
			
		||||
   * Returns a randomly generated feed edit array.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $feed_url
 | 
			
		||||
   *   If given, feed will be created with this URL, otherwise /rss.xml will be used.
 | 
			
		||||
   *   (optional) If given, feed will be created with this URL, otherwise
 | 
			
		||||
   *   /rss.xml will be used. Defaults to NULL.
 | 
			
		||||
   * @return
 | 
			
		||||
   *   A feed array.
 | 
			
		||||
   */
 | 
			
		||||
@@ -68,7 +77,7 @@ class AggregatorTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Return the count of the randomly created feed array.
 | 
			
		||||
   * Returns the count of the randomly created feed array.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   Number of feed items on default feed created by createFeed().
 | 
			
		||||
@@ -80,10 +89,13 @@ class AggregatorTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Update feed items (simulate click to admin/config/services/aggregator/update/$fid).
 | 
			
		||||
   * Updates the feed items.
 | 
			
		||||
   *
 | 
			
		||||
   * This method simulates a click to
 | 
			
		||||
   * admin/config/services/aggregator/update/$fid.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $feed
 | 
			
		||||
   *   Feed object representing the feed.
 | 
			
		||||
   *   Feed object representing the feed, passed by reference.
 | 
			
		||||
   * @param $expected_count
 | 
			
		||||
   *   Expected number of feed items.
 | 
			
		||||
   */
 | 
			
		||||
@@ -112,7 +124,7 @@ class AggregatorTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Confirm item removal from a feed.
 | 
			
		||||
   * Confirms an item removal from a feed.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $feed
 | 
			
		||||
   *   Feed object representing the feed.
 | 
			
		||||
@@ -123,7 +135,7 @@ class AggregatorTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Add and remove feed items and ensure that the count is zero.
 | 
			
		||||
   * Adds and removes feed items and ensure that the count is zero.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $feed
 | 
			
		||||
   *   Feed object representing the feed.
 | 
			
		||||
@@ -140,7 +152,7 @@ class AggregatorTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Pull feed categories from aggregator_category_feed table.
 | 
			
		||||
   * Pulls feed categories from {aggregator_category_feed} table.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $feed
 | 
			
		||||
   *   Feed object representing the feed.
 | 
			
		||||
@@ -154,7 +166,11 @@ class AggregatorTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Pull categories from aggregator_category table.
 | 
			
		||||
   * Pulls categories from {aggregator_category} table.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   An associative array keyed by category ID and values are set to the
 | 
			
		||||
   *   category names.
 | 
			
		||||
   */
 | 
			
		||||
  function getCategories() {
 | 
			
		||||
    $categories = array();
 | 
			
		||||
@@ -165,14 +181,14 @@ class AggregatorTestCase extends DrupalWebTestCase {
 | 
			
		||||
    return $categories;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Check if the feed name and URL is unique.
 | 
			
		||||
   * Checks whether the feed name and URL are unique.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $feed_name
 | 
			
		||||
   *   String containing the feed name to check.
 | 
			
		||||
   * @param $feed_url
 | 
			
		||||
   *   String containing the feed URL to check.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   TRUE if feed is unique.
 | 
			
		||||
   */
 | 
			
		||||
@@ -182,10 +198,11 @@ class AggregatorTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a valid OPML file from an array of feeds.
 | 
			
		||||
   * Creates a valid OPML file from an array of feeds.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $feeds
 | 
			
		||||
   *   An array of feeds.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   Path to valid OPML file.
 | 
			
		||||
   */
 | 
			
		||||
@@ -223,7 +240,7 @@ EOF;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create an invalid OPML file.
 | 
			
		||||
   * Creates an invalid OPML file.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   Path to invalid OPML file.
 | 
			
		||||
@@ -240,7 +257,7 @@ EOF;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a valid but empty OPML file.
 | 
			
		||||
   * Creates a valid but empty OPML file.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   Path to empty OPML file.
 | 
			
		||||
@@ -275,7 +292,7 @@ EOF;
 | 
			
		||||
   * Creates sample article nodes.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $count
 | 
			
		||||
   *   (optional) The number of nodes to generate.
 | 
			
		||||
   *   (optional) The number of nodes to generate. Defaults to five.
 | 
			
		||||
   */
 | 
			
		||||
  function createSampleNodes($count = 5) {
 | 
			
		||||
    $langcode = LANGUAGE_NONE;
 | 
			
		||||
@@ -290,7 +307,7 @@ EOF;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests aggregator configuration settings.
 | 
			
		||||
 * Tests functionality of the configuration settings in the Aggregator module.
 | 
			
		||||
 */
 | 
			
		||||
class AggregatorConfigurationTestCase extends AggregatorTestCase {
 | 
			
		||||
  public static function getInfo() {
 | 
			
		||||
@@ -321,6 +338,9 @@ class AggregatorConfigurationTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests adding aggregator feeds.
 | 
			
		||||
 */
 | 
			
		||||
class AddFeedTestCase extends AggregatorTestCase {
 | 
			
		||||
  public static function getInfo() {
 | 
			
		||||
    return array(
 | 
			
		||||
@@ -331,7 +351,7 @@ class AddFeedTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a feed, ensure that it is unique, check the source, and delete the feed.
 | 
			
		||||
   * Creates and ensures that a feed is unique, checks source, and deletes feed.
 | 
			
		||||
   */
 | 
			
		||||
  function testAddFeed() {
 | 
			
		||||
    $feed = $this->createFeed();
 | 
			
		||||
@@ -381,6 +401,9 @@ class AddFeedTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests the categorize feed functionality in the Aggregator module.
 | 
			
		||||
 */
 | 
			
		||||
class CategorizeFeedTestCase extends AggregatorTestCase {
 | 
			
		||||
  public static function getInfo() {
 | 
			
		||||
    return array(
 | 
			
		||||
@@ -391,7 +414,7 @@ class CategorizeFeedTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a feed and make sure you can add more than one category to it.
 | 
			
		||||
   * Creates a feed and makes sure you can add more than one category to it.
 | 
			
		||||
   */
 | 
			
		||||
  function testCategorizeFeed() {
 | 
			
		||||
 | 
			
		||||
@@ -424,6 +447,9 @@ class CategorizeFeedTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests functionality of updating the feed in the Aggregator module.
 | 
			
		||||
 */
 | 
			
		||||
class UpdateFeedTestCase extends AggregatorTestCase {
 | 
			
		||||
  public static function getInfo() {
 | 
			
		||||
    return array(
 | 
			
		||||
@@ -434,7 +460,7 @@ class UpdateFeedTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a feed and attempt to update it.
 | 
			
		||||
   * Creates a feed and attempts to update it.
 | 
			
		||||
   */
 | 
			
		||||
  function testUpdateFeed() {
 | 
			
		||||
    $remamining_fields = array('title', 'url', '');
 | 
			
		||||
@@ -466,6 +492,9 @@ class UpdateFeedTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests functionality for removing feeds in the Aggregator module.
 | 
			
		||||
 */
 | 
			
		||||
class RemoveFeedTestCase extends AggregatorTestCase {
 | 
			
		||||
  public static function getInfo() {
 | 
			
		||||
    return array(
 | 
			
		||||
@@ -476,7 +505,7 @@ class RemoveFeedTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Remove a feed and ensure that all it services are removed.
 | 
			
		||||
   * Removes a feed and ensures that all of its services are removed.
 | 
			
		||||
   */
 | 
			
		||||
  function testRemoveFeed() {
 | 
			
		||||
    $feed = $this->createFeed();
 | 
			
		||||
@@ -494,6 +523,9 @@ class RemoveFeedTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests functionality of updating a feed item in the Aggregator module.
 | 
			
		||||
 */
 | 
			
		||||
class UpdateFeedItemTestCase extends AggregatorTestCase {
 | 
			
		||||
  public static function getInfo() {
 | 
			
		||||
    return array(
 | 
			
		||||
@@ -504,7 +536,7 @@ class UpdateFeedItemTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test running "update items" from the 'admin/config/services/aggregator' page.
 | 
			
		||||
   * Tests running "update items" from 'admin/config/services/aggregator' page.
 | 
			
		||||
   */
 | 
			
		||||
  function testUpdateFeedItem() {
 | 
			
		||||
    $this->createSampleNodes();
 | 
			
		||||
@@ -564,7 +596,7 @@ class RemoveFeedItemTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test running "remove items" from the 'admin/config/services/aggregator' page.
 | 
			
		||||
   * Tests running "remove items" from 'admin/config/services/aggregator' page.
 | 
			
		||||
   */
 | 
			
		||||
  function testRemoveFeedItem() {
 | 
			
		||||
    // Create a bunch of test feeds.
 | 
			
		||||
@@ -592,6 +624,9 @@ class RemoveFeedItemTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests categorization functionality in the Aggregator module.
 | 
			
		||||
 */
 | 
			
		||||
class CategorizeFeedItemTestCase extends AggregatorTestCase {
 | 
			
		||||
  public static function getInfo() {
 | 
			
		||||
    return array(
 | 
			
		||||
@@ -602,6 +637,8 @@ class CategorizeFeedItemTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Checks that children of a feed inherit a defined category.
 | 
			
		||||
   *
 | 
			
		||||
   * If a feed has a category, make sure that the children inherit that
 | 
			
		||||
   * categorization.
 | 
			
		||||
   */
 | 
			
		||||
@@ -649,6 +686,9 @@ class CategorizeFeedItemTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests importing feeds from OPML functionality for the Aggregator module.
 | 
			
		||||
 */
 | 
			
		||||
class ImportOPMLTestCase extends AggregatorTestCase {
 | 
			
		||||
  public static function getInfo() {
 | 
			
		||||
    return array(
 | 
			
		||||
@@ -659,7 +699,7 @@ class ImportOPMLTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Open OPML import form.
 | 
			
		||||
   * Opens OPML import form.
 | 
			
		||||
   */
 | 
			
		||||
  function openImportForm() {
 | 
			
		||||
    db_delete('aggregator_category')->execute();
 | 
			
		||||
@@ -681,7 +721,7 @@ class ImportOPMLTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Submit form filled with invalid fields.
 | 
			
		||||
   * Submits form filled with invalid fields.
 | 
			
		||||
   */
 | 
			
		||||
  function validateImportFormFields() {
 | 
			
		||||
    $before = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
 | 
			
		||||
@@ -707,7 +747,7 @@ class ImportOPMLTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Submit form with invalid, empty and valid OPML files.
 | 
			
		||||
   * Submits form with invalid, empty, and valid OPML files.
 | 
			
		||||
   */
 | 
			
		||||
  function submitImportForm() {
 | 
			
		||||
    $before = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
 | 
			
		||||
@@ -766,6 +806,9 @@ class ImportOPMLTestCase extends AggregatorTestCase {
 | 
			
		||||
    $this->assertTrue($category, 'Categories are correct.');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the import of an OPML file.
 | 
			
		||||
   */
 | 
			
		||||
  function testOPMLImport() {
 | 
			
		||||
    $this->openImportForm();
 | 
			
		||||
    $this->validateImportFormFields();
 | 
			
		||||
@@ -773,6 +816,9 @@ class ImportOPMLTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests functionality of the cron process in the Aggregator module.
 | 
			
		||||
 */
 | 
			
		||||
class AggregatorCronTestCase extends AggregatorTestCase {
 | 
			
		||||
  public static function getInfo() {
 | 
			
		||||
    return array(
 | 
			
		||||
@@ -783,7 +829,7 @@ class AggregatorCronTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Add feeds update them on cron.
 | 
			
		||||
   * Adds feeds and updates them via cron process.
 | 
			
		||||
   */
 | 
			
		||||
  public function testCron() {
 | 
			
		||||
    // Create feed and test basic updating on cron.
 | 
			
		||||
@@ -819,6 +865,9 @@ class AggregatorCronTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests rendering functionality in the Aggregator module.
 | 
			
		||||
 */
 | 
			
		||||
class AggregatorRenderingTestCase extends AggregatorTestCase {
 | 
			
		||||
  public static function getInfo() {
 | 
			
		||||
    return array(
 | 
			
		||||
@@ -829,9 +878,9 @@ class AggregatorRenderingTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Add a feed block to the page and checks its links.
 | 
			
		||||
   * Adds a feed block to the page and checks its links.
 | 
			
		||||
   *
 | 
			
		||||
   * TODO: Test the category block as well.
 | 
			
		||||
   * @todo Test the category block as well.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockLinks() {
 | 
			
		||||
    // Create feed.
 | 
			
		||||
@@ -890,7 +939,7 @@ class AggregatorRenderingTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a feed and check that feed's page.
 | 
			
		||||
   * Creates a feed and checks that feed's page.
 | 
			
		||||
   */
 | 
			
		||||
  public function testFeedPage() {
 | 
			
		||||
    // Increase the number of items published in the rss.xml feed so we have
 | 
			
		||||
@@ -913,7 +962,7 @@ class AggregatorRenderingTestCase extends AggregatorTestCase {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests for feed parsing.
 | 
			
		||||
 * Tests feed parsing in the Aggregator module.
 | 
			
		||||
 */
 | 
			
		||||
class FeedParserTestCase extends AggregatorTestCase {
 | 
			
		||||
  public static function getInfo() {
 | 
			
		||||
@@ -933,7 +982,7 @@ class FeedParserTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test a feed that uses the RSS 0.91 format.
 | 
			
		||||
   * Tests a feed that uses the RSS 0.91 format.
 | 
			
		||||
   */
 | 
			
		||||
  function testRSS091Sample() {
 | 
			
		||||
    $feed = $this->createFeed($this->getRSS091Sample());
 | 
			
		||||
@@ -955,7 +1004,7 @@ class FeedParserTestCase extends AggregatorTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test a feed that uses the Atom format.
 | 
			
		||||
   * Tests a feed that uses the Atom format.
 | 
			
		||||
   */
 | 
			
		||||
  function testAtomSample() {
 | 
			
		||||
    $feed = $this->createFeed($this->getAtomSample());
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,8 @@ version = VERSION
 | 
			
		||||
core = 7.x
 | 
			
		||||
hidden = TRUE
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,8 @@ core = 7.x
 | 
			
		||||
files[] = block.test
 | 
			
		||||
configure = admin/structure/block
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -740,7 +740,7 @@ function _block_load_blocks() {
 | 
			
		||||
/**
 | 
			
		||||
 * Implements hook_block_list_alter().
 | 
			
		||||
 *
 | 
			
		||||
 * Checks the page, user role, and user-specific visibilty settings.
 | 
			
		||||
 * Checks the page, user role, and user-specific visibility settings.
 | 
			
		||||
 * Removes the block if the visibility conditions are not met.
 | 
			
		||||
 */
 | 
			
		||||
function block_block_list_alter(&$blocks) {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,8 @@ version = VERSION
 | 
			
		||||
core = 7.x
 | 
			
		||||
hidden = TRUE
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,8 +13,8 @@ regions[footer] = Footer
 | 
			
		||||
regions[highlighted] = Highlighted
 | 
			
		||||
regions[help] = Help
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,8 @@ version = VERSION
 | 
			
		||||
core = 7.x
 | 
			
		||||
files[] = blog.test
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,7 @@
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * Right-to-Left styling for the Book module.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
.book-navigation .menu {
 | 
			
		||||
  padding: 1em 3em 0 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,16 @@
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * Admin page callbacks for the book module.
 | 
			
		||||
 * Administration page callbacks for the Book module.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns an administrative overview of all books.
 | 
			
		||||
 *
 | 
			
		||||
 * @return string
 | 
			
		||||
 *   A HTML-formatted string with the administrative page content.
 | 
			
		||||
 *
 | 
			
		||||
 * @see book_menu()
 | 
			
		||||
 */
 | 
			
		||||
function book_admin_overview() {
 | 
			
		||||
  $rows = array();
 | 
			
		||||
@@ -53,6 +58,8 @@ function book_admin_settings() {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Form validation handler for book_admin_settings().
 | 
			
		||||
 *
 | 
			
		||||
 * @see book_admin_settings_submit()
 | 
			
		||||
 */
 | 
			
		||||
function book_admin_settings_validate($form, &$form_state) {
 | 
			
		||||
  $child_type = $form_state['values']['book_child_type'];
 | 
			
		||||
@@ -149,7 +156,7 @@ function book_admin_edit_submit($form, &$form_state) {
 | 
			
		||||
 * @param $node
 | 
			
		||||
 *   The node of the top-level page in the book.
 | 
			
		||||
 * @param $form
 | 
			
		||||
 *   The form that is being modified.
 | 
			
		||||
 *   The form that is being modified, passed by reference.
 | 
			
		||||
 *
 | 
			
		||||
 * @see book_admin_edit()
 | 
			
		||||
 */
 | 
			
		||||
@@ -184,10 +191,10 @@ function _book_admin_table($node, &$form) {
 | 
			
		||||
 * @param $tree
 | 
			
		||||
 *   A subtree of the book menu hierarchy.
 | 
			
		||||
 * @param $form
 | 
			
		||||
 *   The form that is being modified.
 | 
			
		||||
 *   The form that is being modified, passed by reference.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The form that is being modified.
 | 
			
		||||
 *   The modified form array.
 | 
			
		||||
 *
 | 
			
		||||
 * @see book_admin_edit()
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,7 @@
 | 
			
		||||
 /**
 | 
			
		||||
  * @file
 | 
			
		||||
  * Styling for the Book module.
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
.book-navigation .menu {
 | 
			
		||||
  border-top: 1px solid #888;
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,8 @@ files[] = book.test
 | 
			
		||||
configure = admin/content/book/settings
 | 
			
		||||
stylesheets[all][] = book.css
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,6 @@
 | 
			
		||||
 * Javascript behaviors for the Book module.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
(function ($) {
 | 
			
		||||
 | 
			
		||||
Drupal.behaviors.bookFieldsetSummaries = {
 | 
			
		||||
 
 | 
			
		||||
@@ -221,6 +221,9 @@ function _book_outline_remove_access($node) {
 | 
			
		||||
 *
 | 
			
		||||
 * A node can be removed from a book if it is actually in a book and it either
 | 
			
		||||
 * is not a top-level page or is a top-level page with no children.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $node
 | 
			
		||||
 *   The node to remove from the outline.
 | 
			
		||||
 */
 | 
			
		||||
function _book_node_is_removable($node) {
 | 
			
		||||
  return (!empty($node->book['bid']) && (($node->book['bid'] != $node->nid) || !$node->book['has_children']));
 | 
			
		||||
@@ -734,7 +737,7 @@ function book_get_flat_menu($book_link) {
 | 
			
		||||
 * @param $tree
 | 
			
		||||
 *   A tree of menu links in an array.
 | 
			
		||||
 * @param $flat
 | 
			
		||||
 *   A flat array of the menu links from $tree.
 | 
			
		||||
 *   A flat array of the menu links from $tree, passed by reference.
 | 
			
		||||
 *
 | 
			
		||||
 * @see book_get_flat_menu().
 | 
			
		||||
 */
 | 
			
		||||
@@ -1062,8 +1065,9 @@ function _book_link_defaults($nid) {
 | 
			
		||||
 * to the structured data but can also simply iterate over all elements and
 | 
			
		||||
 * render them (as in the default template).
 | 
			
		||||
 *
 | 
			
		||||
 * The $variables array contains the following elements:
 | 
			
		||||
 * - book_menus
 | 
			
		||||
 * @param $variables
 | 
			
		||||
 *   An associative array containing the following key:
 | 
			
		||||
 *   - book_menus
 | 
			
		||||
 *
 | 
			
		||||
 * @see book-all-books-block.tpl.php
 | 
			
		||||
 */
 | 
			
		||||
@@ -1079,8 +1083,9 @@ function template_preprocess_book_all_books_block(&$variables) {
 | 
			
		||||
/**
 | 
			
		||||
 * Processes variables for book-navigation.tpl.php.
 | 
			
		||||
 *
 | 
			
		||||
 * The $variables array contains the following elements:
 | 
			
		||||
 * - book_link
 | 
			
		||||
 * @param $variables
 | 
			
		||||
 *   An associative array containing the following key:
 | 
			
		||||
 *   - book_link
 | 
			
		||||
 *
 | 
			
		||||
 * @see book-navigation.tpl.php
 | 
			
		||||
 */
 | 
			
		||||
@@ -1151,8 +1156,9 @@ function template_preprocess_book_navigation(&$variables) {
 | 
			
		||||
 *   Reference to the table of contents array. This is modified in place, so the
 | 
			
		||||
 *   function does not have a return value.
 | 
			
		||||
 * @param $exclude
 | 
			
		||||
 *   Optional array of menu link ID values. Any link whose menu link ID is in
 | 
			
		||||
 *   this array will be excluded (along with its children).
 | 
			
		||||
 *   (optional) An array of menu link ID values. Any link whose menu link ID is
 | 
			
		||||
 *   in this array will be excluded (along with its children). Defaults to an
 | 
			
		||||
 *   empty array.
 | 
			
		||||
 * @param $depth_limit
 | 
			
		||||
 *   Any link deeper than this value will be excluded (along with its children).
 | 
			
		||||
 */
 | 
			
		||||
@@ -1198,10 +1204,11 @@ function book_toc($bid, $depth_limit, $exclude = array()) {
 | 
			
		||||
/**
 | 
			
		||||
 * Processes variables for book-export-html.tpl.php.
 | 
			
		||||
 *
 | 
			
		||||
 * The $variables array contains the following elements:
 | 
			
		||||
 * - title
 | 
			
		||||
 * - contents
 | 
			
		||||
 * - depth
 | 
			
		||||
 * @param $variables
 | 
			
		||||
 *   An associative array containing the following keys:
 | 
			
		||||
 *   - title
 | 
			
		||||
 *   - contents
 | 
			
		||||
 *   - depth
 | 
			
		||||
 *
 | 
			
		||||
 * @see book-export-html.tpl.php
 | 
			
		||||
 */
 | 
			
		||||
@@ -1261,7 +1268,8 @@ function book_export_traverse($tree, $visit_func) {
 | 
			
		||||
 * @param $node
 | 
			
		||||
 *   The node that will be output.
 | 
			
		||||
 * @param $children
 | 
			
		||||
 *   All the rendered child nodes within the current node.
 | 
			
		||||
 *   (optional) All the rendered child nodes within the current node. Defaults
 | 
			
		||||
 *   to an empty string.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   The HTML generated for the given node.
 | 
			
		||||
@@ -1280,9 +1288,10 @@ function book_node_export($node, $children = '') {
 | 
			
		||||
/**
 | 
			
		||||
 * Processes variables for book-node-export-html.tpl.php.
 | 
			
		||||
 *
 | 
			
		||||
 * The $variables array contains the following elements:
 | 
			
		||||
 * - node
 | 
			
		||||
 * - children
 | 
			
		||||
 * @param $variables
 | 
			
		||||
 *   An associative array containing the following keys:
 | 
			
		||||
 *   - node
 | 
			
		||||
 *   - children
 | 
			
		||||
 *
 | 
			
		||||
 * @see book-node-export-html.tpl.php
 | 
			
		||||
 */
 | 
			
		||||
@@ -1294,6 +1303,12 @@ function template_preprocess_book_node_export_html(&$variables) {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Determine if a given node type is in the list of types allowed for books.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $type
 | 
			
		||||
 *   A node type.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   A Boolean TRUE if the node type can be included in books; otherwise, FALSE.
 | 
			
		||||
 */
 | 
			
		||||
function book_type_is_allowed($type) {
 | 
			
		||||
  return in_array($type, variable_get('book_allowed_types', array('book')));
 | 
			
		||||
@@ -1336,7 +1351,7 @@ function book_node_type_update($type) {
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   A menu link, with the link translated for rendering and data added from the
 | 
			
		||||
 *   {book} table.
 | 
			
		||||
 *   {book} table. FALSE if there is an error.
 | 
			
		||||
 */
 | 
			
		||||
function book_link_load($mlid) {
 | 
			
		||||
  if ($item = db_query("SELECT * FROM {menu_links} ml INNER JOIN {book} b ON b.mlid = ml.mlid LEFT JOIN {menu_router} m ON m.path = ml.router_path WHERE ml.mlid = :mlid", array(
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,11 @@
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Menu callback: Prints a listing of all books.
 | 
			
		||||
 *
 | 
			
		||||
 * @return string
 | 
			
		||||
 *   A HTML-formatted string with the listing of all books content.
 | 
			
		||||
 *
 | 
			
		||||
 * @see book_menu()
 | 
			
		||||
 */
 | 
			
		||||
function book_render() {
 | 
			
		||||
  $book_list = array();
 | 
			
		||||
@@ -36,6 +41,8 @@ function book_render() {
 | 
			
		||||
 * @return
 | 
			
		||||
 *   A string representing the node and its children in the book hierarchy in a
 | 
			
		||||
 *   format determined by the $type parameter.
 | 
			
		||||
 *
 | 
			
		||||
 * @see book_menu()
 | 
			
		||||
 */
 | 
			
		||||
function book_export($type, $nid) {
 | 
			
		||||
  // Check that the node exists and that the current user has access to it.
 | 
			
		||||
@@ -79,7 +86,6 @@ function book_export($type, $nid) {
 | 
			
		||||
 */
 | 
			
		||||
function book_export_html($nid) {
 | 
			
		||||
  if (user_access('access printer-friendly version')) {
 | 
			
		||||
    $export_data = array();
 | 
			
		||||
    $node = node_load($nid);
 | 
			
		||||
    if (isset($node->book)) {
 | 
			
		||||
      $tree = book_menu_subtree_data($node->book);
 | 
			
		||||
@@ -100,6 +106,11 @@ function book_export_html($nid) {
 | 
			
		||||
 *
 | 
			
		||||
 * @param $node
 | 
			
		||||
 *   The book node for which to show the outline.
 | 
			
		||||
 *
 | 
			
		||||
 * @return string
 | 
			
		||||
 *   A HTML-formatted string with the outline form for a single node.
 | 
			
		||||
 *
 | 
			
		||||
  * @see book_menu()
 | 
			
		||||
 */
 | 
			
		||||
function book_outline($node) {
 | 
			
		||||
  drupal_set_title($node->title);
 | 
			
		||||
 
 | 
			
		||||
@@ -5,14 +5,37 @@
 | 
			
		||||
 * Tests for book.module.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests the functionality of the Book module.
 | 
			
		||||
 */
 | 
			
		||||
class BookTestCase extends DrupalWebTestCase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * A book node.
 | 
			
		||||
   *
 | 
			
		||||
   * @var object
 | 
			
		||||
   */
 | 
			
		||||
  protected $book;
 | 
			
		||||
  // $book_author is a user with permission to create and edit books.
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * A user with permission to create and edit books.
 | 
			
		||||
   *
 | 
			
		||||
   * @var object
 | 
			
		||||
   */
 | 
			
		||||
  protected $book_author;
 | 
			
		||||
  // $web_user is a user with permission to view a book
 | 
			
		||||
  // and access the printer-friendly version.
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * A user with permission to view a book and access printer-friendly version.
 | 
			
		||||
   *
 | 
			
		||||
   * @var object
 | 
			
		||||
   */
 | 
			
		||||
  protected $web_user;
 | 
			
		||||
  // $admin_user is a user with permission to create and edit books and to administer blocks.
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * A user with permission to create and edit books and to administer blocks.
 | 
			
		||||
   *
 | 
			
		||||
   * @var object
 | 
			
		||||
   */
 | 
			
		||||
  protected $admin_user;
 | 
			
		||||
 | 
			
		||||
  public static function getInfo() {
 | 
			
		||||
@@ -36,7 +59,7 @@ class BookTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a new book with a page hierarchy.
 | 
			
		||||
   * Creates a new book with a page hierarchy.
 | 
			
		||||
   */
 | 
			
		||||
  function createBook() {
 | 
			
		||||
    // Create new book.
 | 
			
		||||
@@ -67,7 +90,7 @@ class BookTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test book functionality through node interfaces.
 | 
			
		||||
   * Tests book functionality through node interfaces.
 | 
			
		||||
   */
 | 
			
		||||
  function testBook() {
 | 
			
		||||
    // Create new book.
 | 
			
		||||
@@ -106,18 +129,20 @@ class BookTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Check the outline of sub-pages; previous, up, and next; and printer friendly version.
 | 
			
		||||
   * Checks the outline of sub-pages; previous, up, and next.
 | 
			
		||||
   *
 | 
			
		||||
   * Also checks the printer friendly version of the outline.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $node
 | 
			
		||||
   *   Node to check.
 | 
			
		||||
   * @param $nodes
 | 
			
		||||
   *   Nodes that should be in outline.
 | 
			
		||||
   * @param $previous
 | 
			
		||||
   *   Previous link node.
 | 
			
		||||
   *   (optional) Previous link node. Defaults to FALSE.
 | 
			
		||||
   * @param $up
 | 
			
		||||
   *   Up link node.
 | 
			
		||||
   *   (optional) Up link node. Defaults to FALSE.
 | 
			
		||||
   * @param $next
 | 
			
		||||
   *   Next link node.
 | 
			
		||||
   *   (optional) Next link node. Defaults to FALSE.
 | 
			
		||||
   * @param $breadcrumb
 | 
			
		||||
   *   The nodes that should be displayed in the breadcrumb.
 | 
			
		||||
   */
 | 
			
		||||
@@ -129,23 +154,23 @@ class BookTestCase extends DrupalWebTestCase {
 | 
			
		||||
 | 
			
		||||
    // Check outline structure.
 | 
			
		||||
    if ($nodes !== NULL) {
 | 
			
		||||
      $this->assertPattern($this->generateOutlinePattern($nodes), t('Node ' . $number . ' outline confirmed.'));
 | 
			
		||||
      $this->assertPattern($this->generateOutlinePattern($nodes), format_string('Node %number outline confirmed.', array('%number' => $number)));
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      $this->pass(t('Node ' . $number . ' doesn\'t have outline.'));
 | 
			
		||||
      $this->pass(format_string('Node %number does not have outline.', array('%number' => $number)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check previous, up, and next links.
 | 
			
		||||
    if ($previous) {
 | 
			
		||||
      $this->assertRaw(l('‹ ' . $previous->title, 'node/' . $previous->nid, array('attributes' => array('class' => array('page-previous'), 'title' => t('Go to previous page')))), t('Previous page link found.'));
 | 
			
		||||
      $this->assertRaw(l('‹ ' . $previous->title, 'node/' . $previous->nid, array('attributes' => array('class' => array('page-previous'), 'title' => t('Go to previous page')))), 'Previous page link found.');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ($up) {
 | 
			
		||||
      $this->assertRaw(l('up', 'node/' . $up->nid, array('attributes' => array('class' => array('page-up'), 'title' => t('Go to parent page')))), t('Up page link found.'));
 | 
			
		||||
      $this->assertRaw(l('up', 'node/' . $up->nid, array('attributes' => array('class' => array('page-up'), 'title' => t('Go to parent page')))), 'Up page link found.');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ($next) {
 | 
			
		||||
      $this->assertRaw(l($next->title . ' ›', 'node/' . $next->nid, array('attributes' => array('class' => array('page-next'), 'title' => t('Go to next page')))), t('Next page link found.'));
 | 
			
		||||
      $this->assertRaw(l($next->title . ' ›', 'node/' . $next->nid, array('attributes' => array('class' => array('page-next'), 'title' => t('Go to next page')))), 'Next page link found.');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Compute the expected breadcrumb.
 | 
			
		||||
@@ -163,20 +188,24 @@ class BookTestCase extends DrupalWebTestCase {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Compare expected and got breadcrumbs.
 | 
			
		||||
    $this->assertIdentical($expected_breadcrumb, $got_breadcrumb, t('The breadcrumb is correctly displayed on the page.'));
 | 
			
		||||
    $this->assertIdentical($expected_breadcrumb, $got_breadcrumb, 'The breadcrumb is correctly displayed on the page.');
 | 
			
		||||
 | 
			
		||||
    // Check printer friendly version.
 | 
			
		||||
    $this->drupalGet('book/export/html/' . $node->nid);
 | 
			
		||||
    $this->assertText($node->title, t('Printer friendly title found.'));
 | 
			
		||||
    $this->assertRaw(check_markup($node->body[LANGUAGE_NONE][0]['value'], $node->body[LANGUAGE_NONE][0]['format']), t('Printer friendly body found.'));
 | 
			
		||||
    $this->assertText($node->title, 'Printer friendly title found.');
 | 
			
		||||
    $this->assertRaw(check_markup($node->body[LANGUAGE_NONE][0]['value'], $node->body[LANGUAGE_NONE][0]['format']), 'Printer friendly body found.');
 | 
			
		||||
 | 
			
		||||
    $number++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a regular expression to check for the sub-nodes in the outline.
 | 
			
		||||
   * Creates a regular expression to check for the sub-nodes in the outline.
 | 
			
		||||
   *
 | 
			
		||||
   * @param array $nodes Nodes to check in outline.
 | 
			
		||||
   * @param array $nodes
 | 
			
		||||
   *   An array of nodes to check in outline.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   A regular expression that locates sub-nodes of the outline.
 | 
			
		||||
   */
 | 
			
		||||
  function generateOutlinePattern($nodes) {
 | 
			
		||||
    $outline = '';
 | 
			
		||||
@@ -188,10 +217,12 @@ class BookTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create book node.
 | 
			
		||||
   * Creates a book node.
 | 
			
		||||
   *
 | 
			
		||||
   * @param integer $book_nid Book node id or set to 'new' to create new book.
 | 
			
		||||
   * @param integer $parent Parent book reference id.
 | 
			
		||||
   * @param $book_nid
 | 
			
		||||
   *   A book node ID or set to 'new' to create a new book.
 | 
			
		||||
   * @param $parent
 | 
			
		||||
   *   (optional) Parent book reference ID. Defaults to NULL.
 | 
			
		||||
   */
 | 
			
		||||
  function createBookNode($book_nid, $parent = NULL) {
 | 
			
		||||
    // $number does not use drupal_static as it should not be reset
 | 
			
		||||
@@ -216,7 +247,7 @@ class BookTestCase extends DrupalWebTestCase {
 | 
			
		||||
 | 
			
		||||
    // Check to make sure the book node was created.
 | 
			
		||||
    $node = $this->drupalGetNodeByTitle($edit['title']);
 | 
			
		||||
    $this->assertNotNull(($node === FALSE ? NULL : $node), t('Book node found in database.'));
 | 
			
		||||
    $this->assertNotNull(($node === FALSE ? NULL : $node), 'Book node found in database.');
 | 
			
		||||
    $number++;
 | 
			
		||||
 | 
			
		||||
    return $node;
 | 
			
		||||
@@ -236,28 +267,28 @@ class BookTestCase extends DrupalWebTestCase {
 | 
			
		||||
 | 
			
		||||
    // Make sure each part of the book is there.
 | 
			
		||||
    foreach ($nodes as $node) {
 | 
			
		||||
      $this->assertText($node->title, t('Node title found in printer friendly version.'));
 | 
			
		||||
      $this->assertRaw(check_markup($node->body[LANGUAGE_NONE][0]['value'], $node->body[LANGUAGE_NONE][0]['format']), t('Node body found in printer friendly version.'));
 | 
			
		||||
      $this->assertText($node->title, 'Node title found in printer friendly version.');
 | 
			
		||||
      $this->assertRaw(check_markup($node->body[LANGUAGE_NONE][0]['value'], $node->body[LANGUAGE_NONE][0]['format']), 'Node body found in printer friendly version.');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Make sure we can't export an unsupported format.
 | 
			
		||||
    $this->drupalGet('book/export/foobar/' . $this->book->nid);
 | 
			
		||||
    $this->assertResponse('404', t('Unsupported export format returned "not found".'));
 | 
			
		||||
    $this->assertResponse('404', 'Unsupported export format returned "not found".');
 | 
			
		||||
 | 
			
		||||
    // Make sure we get a 404 on a not existing book node.
 | 
			
		||||
    $this->drupalGet('book/export/html/123');
 | 
			
		||||
    $this->assertResponse('404', t('Not existing book node returned "not found".'));
 | 
			
		||||
    $this->assertResponse('404', 'Not existing book node returned "not found".');
 | 
			
		||||
 | 
			
		||||
    // Make sure an anonymous user cannot view printer-friendly version.
 | 
			
		||||
    $this->drupalLogout();
 | 
			
		||||
 | 
			
		||||
    // Load the book and verify there is no printer-friendly version link.
 | 
			
		||||
    $this->drupalGet('node/' . $this->book->nid);
 | 
			
		||||
    $this->assertNoLink(t('Printer-friendly version'), t('Anonymous user is not shown link to printer-friendly version.'));
 | 
			
		||||
    $this->assertNoLink(t('Printer-friendly version'), 'Anonymous user is not shown link to printer-friendly version.');
 | 
			
		||||
 | 
			
		||||
    // Try getting the URL directly, and verify it fails.
 | 
			
		||||
    $this->drupalGet('book/export/html/' . $this->book->nid);
 | 
			
		||||
    $this->assertResponse('403', t('Anonymous user properly forbidden.'));
 | 
			
		||||
    $this->assertResponse('403', 'Anonymous user properly forbidden.');
 | 
			
		||||
 | 
			
		||||
    // Now grant anonymous users permission to view the printer-friendly
 | 
			
		||||
    // version and verify that node access restrictions still prevent them from
 | 
			
		||||
@@ -276,30 +307,30 @@ class BookTestCase extends DrupalWebTestCase {
 | 
			
		||||
    // Set block title to confirm that the interface is available.
 | 
			
		||||
    $block_title = $this->randomName(16);
 | 
			
		||||
    $this->drupalPost('admin/structure/block/manage/book/navigation/configure', array('title' => $block_title), t('Save block'));
 | 
			
		||||
    $this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
 | 
			
		||||
    $this->assertText(t('The block configuration has been saved.'), 'Block configuration set.');
 | 
			
		||||
 | 
			
		||||
    // Set the block to a region to confirm block is available.
 | 
			
		||||
    $edit = array();
 | 
			
		||||
    $edit['blocks[book_navigation][region]'] = 'footer';
 | 
			
		||||
    $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
 | 
			
		||||
    $this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
 | 
			
		||||
    $this->assertText(t('The block settings have been updated.'), 'Block successfully move to footer region.');
 | 
			
		||||
 | 
			
		||||
     // Give anonymous users the permission 'node test view'.
 | 
			
		||||
     $edit = array();
 | 
			
		||||
     $edit[DRUPAL_ANONYMOUS_RID . '[node test view]'] = TRUE;
 | 
			
		||||
     $this->drupalPost('admin/people/permissions/' . DRUPAL_ANONYMOUS_RID, $edit, t('Save permissions'));
 | 
			
		||||
     $this->assertText(t('The changes have been saved.'), t("Permission 'node test view' successfully assigned to anonymous users."));
 | 
			
		||||
     $this->assertText(t('The changes have been saved.'), "Permission 'node test view' successfully assigned to anonymous users.");
 | 
			
		||||
 | 
			
		||||
    // Test correct display of the block.
 | 
			
		||||
    $nodes = $this->createBook();
 | 
			
		||||
    $this->drupalGet('<front>');
 | 
			
		||||
    $this->assertText($block_title, t('Book navigation block is displayed.'));
 | 
			
		||||
    $this->assertText($this->book->title, t('Link to book root (@title) is displayed.', array('@title' => $nodes[0]->title)));
 | 
			
		||||
    $this->assertNoText($nodes[0]->title, t('No links to individual book pages are displayed.'));
 | 
			
		||||
    $this->assertText($block_title, 'Book navigation block is displayed.');
 | 
			
		||||
    $this->assertText($this->book->title, format_string('Link to book root (@title) is displayed.', array('@title' => $nodes[0]->title)));
 | 
			
		||||
    $this->assertNoText($nodes[0]->title, 'No links to individual book pages are displayed.');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test the book navigation block when an access module is enabled.
 | 
			
		||||
   * Tests the book navigation block when an access module is enabled.
 | 
			
		||||
   */
 | 
			
		||||
   function testNavigationBlockOnAccessModuleEnabled() {
 | 
			
		||||
     $this->drupalLogin($this->admin_user);
 | 
			
		||||
@@ -312,19 +343,19 @@ class BookTestCase extends DrupalWebTestCase {
 | 
			
		||||
     // Set block display to 'Show block only on book pages'.
 | 
			
		||||
     $edit['book_block_mode'] = 'book pages';
 | 
			
		||||
     $this->drupalPost('admin/structure/block/manage/book/navigation/configure', $edit, t('Save block'));
 | 
			
		||||
     $this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
 | 
			
		||||
     $this->assertText(t('The block configuration has been saved.'), 'Block configuration set.');
 | 
			
		||||
 | 
			
		||||
     // Set the block to a region to confirm block is available.
 | 
			
		||||
     $edit = array();
 | 
			
		||||
     $edit['blocks[book_navigation][region]'] = 'footer';
 | 
			
		||||
     $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
 | 
			
		||||
     $this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
 | 
			
		||||
     $this->assertText(t('The block settings have been updated.'), 'Block successfully move to footer region.');
 | 
			
		||||
 | 
			
		||||
     // Give anonymous users the permission 'node test view'.
 | 
			
		||||
     $edit = array();
 | 
			
		||||
     $edit[DRUPAL_ANONYMOUS_RID . '[node test view]'] = TRUE;
 | 
			
		||||
     $this->drupalPost('admin/people/permissions/' . DRUPAL_ANONYMOUS_RID, $edit, t('Save permissions'));
 | 
			
		||||
     $this->assertText(t('The changes have been saved.'), t('Permission \'node test view\' successfully assigned to anonymous users.'));
 | 
			
		||||
     $this->assertText(t('The changes have been saved.'), "Permission 'node test view' successfully assigned to anonymous users.");
 | 
			
		||||
 | 
			
		||||
     // Create a book.
 | 
			
		||||
     $this->createBook();
 | 
			
		||||
@@ -332,12 +363,12 @@ class BookTestCase extends DrupalWebTestCase {
 | 
			
		||||
     // Test correct display of the block to registered users.
 | 
			
		||||
     $this->drupalLogin($this->web_user);
 | 
			
		||||
     $this->drupalGet('node/' . $this->book->nid);
 | 
			
		||||
     $this->assertText($block_title, t('Book navigation block is displayed to registered users.'));
 | 
			
		||||
     $this->assertText($block_title, 'Book navigation block is displayed to registered users.');
 | 
			
		||||
     $this->drupalLogout();
 | 
			
		||||
 | 
			
		||||
     // Test correct display of the block to anonymous users.
 | 
			
		||||
     $this->drupalGet('node/' . $this->book->nid);
 | 
			
		||||
     $this->assertText($block_title, t('Book navigation block is displayed to anonymous users.'));
 | 
			
		||||
     $this->assertText($block_title, 'Book navigation block is displayed to anonymous users.');
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
@@ -350,10 +381,10 @@ class BookTestCase extends DrupalWebTestCase {
 | 
			
		||||
 | 
			
		||||
     // Test access to delete top-level and child book nodes.
 | 
			
		||||
     $this->drupalGet('node/' . $this->book->nid . '/outline/remove');
 | 
			
		||||
     $this->assertResponse('403', t('Deleting top-level book node properly forbidden.'));
 | 
			
		||||
     $this->assertResponse('403', 'Deleting top-level book node properly forbidden.');
 | 
			
		||||
     $this->drupalPost('node/' . $nodes[4]->nid . '/outline/remove', $edit, t('Remove'));
 | 
			
		||||
     $node4 = node_load($nodes[4]->nid, NULL, TRUE);
 | 
			
		||||
     $this->assertTrue(empty($node4->book), t('Deleting child book node properly allowed.'));
 | 
			
		||||
     $this->assertTrue(empty($node4->book), 'Deleting child book node properly allowed.');
 | 
			
		||||
 | 
			
		||||
     // Delete all child book nodes and retest top-level node deletion.
 | 
			
		||||
     foreach ($nodes as $node) {
 | 
			
		||||
@@ -362,6 +393,6 @@ class BookTestCase extends DrupalWebTestCase {
 | 
			
		||||
     node_delete_multiple($nids);
 | 
			
		||||
     $this->drupalPost('node/' . $this->book->nid . '/outline/remove', $edit, t('Remove'));
 | 
			
		||||
     $node = node_load($this->book->nid, NULL, TRUE);
 | 
			
		||||
     $this->assertTrue(empty($node->book), t('Deleting childless top-level book node properly allowed.'));
 | 
			
		||||
     $this->assertTrue(empty($node->book), 'Deleting childless top-level book node properly allowed.');
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,8 @@ version = VERSION
 | 
			
		||||
core = 7.x
 | 
			
		||||
files[] = color.test
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -98,13 +98,14 @@ function comment_admin_overview($form, &$form_state, $arg) {
 | 
			
		||||
    // Remove the first node title from the node_titles array and attach to
 | 
			
		||||
    // the comment.
 | 
			
		||||
    $comment->node_title = array_shift($node_titles);
 | 
			
		||||
    $comment_body = field_get_items('comment', $comment, 'comment_body');
 | 
			
		||||
    $options[$comment->cid] = array(
 | 
			
		||||
      'subject' => array(
 | 
			
		||||
        'data' => array(
 | 
			
		||||
          '#type' => 'link',
 | 
			
		||||
          '#title' => $comment->subject,
 | 
			
		||||
          '#href' => 'comment/' . $comment->cid,
 | 
			
		||||
          '#options' => array('attributes' => array('title' => truncate_utf8($comment->comment_body[LANGUAGE_NONE][0]['value'], 128)), 'fragment' => 'comment-' . $comment->cid),
 | 
			
		||||
          '#options' => array('attributes' => array('title' => truncate_utf8($comment_body[0]['value'], 128)), 'fragment' => 'comment-' . $comment->cid),
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
      'author' => theme('username', array('account' => $comment)),
 | 
			
		||||
 
 | 
			
		||||
@@ -9,8 +9,8 @@ files[] = comment.test
 | 
			
		||||
configure = admin/content/comment
 | 
			
		||||
stylesheets[all][] = comment.css
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2041,7 +2041,8 @@ function comment_form($form, &$form_state, $comment) {
 | 
			
		||||
 | 
			
		||||
  // Attach fields.
 | 
			
		||||
  $comment->node_type = 'comment_node_' . $node->type;
 | 
			
		||||
  field_attach_form('comment', $comment, $form, $form_state);
 | 
			
		||||
  $langcode = entity_language('comment', $comment);
 | 
			
		||||
  field_attach_form('comment', $comment, $form, $form_state, $langcode);
 | 
			
		||||
 | 
			
		||||
  return $form;
 | 
			
		||||
}
 | 
			
		||||
@@ -2066,7 +2067,8 @@ function comment_preview($comment) {
 | 
			
		||||
  $node = node_load($comment->nid);
 | 
			
		||||
 | 
			
		||||
  if (!form_get_errors()) {
 | 
			
		||||
    $comment->format = $comment->comment_body[LANGUAGE_NONE][0]['format'];
 | 
			
		||||
    $comment_body = field_get_items('comment', $comment, 'comment_body');
 | 
			
		||||
    $comment->format = $comment_body[0]['format'];
 | 
			
		||||
    // Attach the user and time information.
 | 
			
		||||
    if (!empty($comment->name)) {
 | 
			
		||||
      $account = user_load_by_name($comment->name);
 | 
			
		||||
@@ -2190,7 +2192,9 @@ function comment_submit($comment) {
 | 
			
		||||
    // 1) Filter it into HTML
 | 
			
		||||
    // 2) Strip out all HTML tags
 | 
			
		||||
    // 3) Convert entities back to plain-text.
 | 
			
		||||
    $comment_body = $comment->comment_body[LANGUAGE_NONE][0];
 | 
			
		||||
    $field = field_info_field('comment_body');
 | 
			
		||||
    $langcode = field_is_translatable('comment', $field) ? entity_language('comment', $comment) : LANGUAGE_NONE;
 | 
			
		||||
    $comment_body = $comment->comment_body[$langcode][0];
 | 
			
		||||
    if (isset($comment_body['format'])) {
 | 
			
		||||
      $comment_text = check_markup($comment_body['value'], $comment_body['format']);
 | 
			
		||||
    }
 | 
			
		||||
@@ -2284,8 +2288,16 @@ function template_preprocess_comment(&$variables) {
 | 
			
		||||
  $variables['comment']   = $comment;
 | 
			
		||||
  $variables['node']      = $node;
 | 
			
		||||
  $variables['author']    = theme('username', array('account' => $comment));
 | 
			
		||||
 | 
			
		||||
  $variables['created']   = format_date($comment->created);
 | 
			
		||||
  $variables['changed']   = format_date($comment->changed);
 | 
			
		||||
 | 
			
		||||
  // Avoid calling format_date() twice on the same timestamp.
 | 
			
		||||
  if ($comment->changed == $comment->created) {
 | 
			
		||||
    $variables['changed'] = $variables['created'];
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    $variables['changed'] = format_date($comment->changed);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  $variables['new']       = !empty($comment->new) ? t('new') : '';
 | 
			
		||||
  $variables['picture']   = theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', array('account' => $comment)) : '';
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,8 @@ core = 7.x
 | 
			
		||||
files[] = contact.test
 | 
			
		||||
configure = admin/structure/contact
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,8 @@ version = VERSION
 | 
			
		||||
core = 7.x
 | 
			
		||||
files[] = contextual.test
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,8 @@ files[] = dashboard.test
 | 
			
		||||
dependencies[] = block
 | 
			
		||||
configure = admin/dashboard/customize
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,7 @@
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * Right-to-Left styling for the Database Logging module.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
.form-item-type,
 | 
			
		||||
.form-item-severity {
 | 
			
		||||
 
 | 
			
		||||
@@ -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 because events from this page have no detail view.
 | 
			
		||||
 * Messages are not truncated on this page because events detailed herein do not
 | 
			
		||||
 * have links to a detailed view.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $type
 | 
			
		||||
 *   type of dblog events to display.
 | 
			
		||||
 * @param string $type
 | 
			
		||||
 *   Type of database log events to display (e.g., 'search').
 | 
			
		||||
 *
 | 
			
		||||
 * @return array
 | 
			
		||||
 *   A build array in the format expected by drupal_render().
 | 
			
		||||
 *
 | 
			
		||||
 * @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.
 | 
			
		||||
 *
 | 
			
		||||
 * @see dblog_filter_form_validate()
 | 
			
		||||
 * @see dblog_filter_form_submit()
 | 
			
		||||
 * @see dblog_overview()
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup forms
 | 
			
		||||
 * @see dblog_filter_form_submit()
 | 
			
		||||
 * @see dblog_filter_form_validate()
 | 
			
		||||
 */
 | 
			
		||||
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();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,8 @@
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * Admin styles for the Database Logging module.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
.form-item-type,
 | 
			
		||||
.form-item-severity {
 | 
			
		||||
  float: left; /* LTR */
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,8 @@ version = VERSION
 | 
			
		||||
core = 7.x
 | 
			
		||||
files[] = dblog.test
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -85,6 +85,7 @@ function dblog_schema() {
 | 
			
		||||
    'indexes' => array(
 | 
			
		||||
      'type' => array('type'),
 | 
			
		||||
      'uid' => array('uid'),
 | 
			
		||||
      'severity' => array('severity'),
 | 
			
		||||
    ),
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
@@ -140,3 +141,19 @@ function dblog_update_7001() {
 | 
			
		||||
/**
 | 
			
		||||
 * @} End of "addtogroup updates-6.x-to-7.x".
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @addtogroup updates-7.x-extra
 | 
			
		||||
 * @{
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add an index to the severity column in the watchdog database table.
 | 
			
		||||
 */
 | 
			
		||||
function dblog_update_7002() {
 | 
			
		||||
  db_add_index('watchdog', 'severity', array('severity'));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @} End of "addtogroup updates-7.x-extra".
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -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(
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,23 @@
 | 
			
		||||
 * Tests for dblog.module.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests logging messages to the database.
 | 
			
		||||
 */
 | 
			
		||||
class DBLogTestCase extends DrupalWebTestCase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * A user with some relevent administrative permissions.
 | 
			
		||||
   *
 | 
			
		||||
   * @var object
 | 
			
		||||
   */
 | 
			
		||||
  protected $big_user;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * A user without any permissions.
 | 
			
		||||
   *
 | 
			
		||||
   * @var object
 | 
			
		||||
   */
 | 
			
		||||
  protected $any_user;
 | 
			
		||||
 | 
			
		||||
  public static function getInfo() {
 | 
			
		||||
@@ -28,7 +43,11 @@ class DBLogTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Login users, create dblog events, and test dblog functionality through the admin and user interfaces.
 | 
			
		||||
   * Tests Database Logging module functionality through interfaces.
 | 
			
		||||
   *
 | 
			
		||||
   * First logs in users, then creates database log events, and finally tests
 | 
			
		||||
   * Database Logging module functionality through both the admin and user
 | 
			
		||||
   * interfaces.
 | 
			
		||||
   */
 | 
			
		||||
  function testDBLog() {
 | 
			
		||||
    // Login the admin user.
 | 
			
		||||
@@ -46,12 +65,13 @@ class DBLogTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Verify setting of the dblog row limit.
 | 
			
		||||
   * Verifies setting of the database log row limit.
 | 
			
		||||
   *
 | 
			
		||||
   * @param integer $count Log row limit.
 | 
			
		||||
   * @param int $row_limit
 | 
			
		||||
   *   The row limit.
 | 
			
		||||
   */
 | 
			
		||||
  private function verifyRowLimit($row_limit) {
 | 
			
		||||
    // Change the dblog row limit.
 | 
			
		||||
    // Change the database log row limit.
 | 
			
		||||
    $edit = array();
 | 
			
		||||
    $edit['dblog_row_limit'] = $row_limit;
 | 
			
		||||
    $this->drupalPost('admin/config/development/logging', $edit, t('Save configuration'));
 | 
			
		||||
@@ -66,33 +86,35 @@ class DBLogTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Verify cron applies the dblog row limit.
 | 
			
		||||
   * Verifies that cron correctly applies the database log row limit.
 | 
			
		||||
   *
 | 
			
		||||
   * @param integer $count Log row limit.
 | 
			
		||||
   * @param int $row_limit
 | 
			
		||||
   *   The row limit.
 | 
			
		||||
   */
 | 
			
		||||
  private function verifyCron($row_limit) {
 | 
			
		||||
    // Generate additional log entries.
 | 
			
		||||
    $this->generateLogEntries($row_limit + 10);
 | 
			
		||||
    // Verify dblog row count exceeds row limit.
 | 
			
		||||
    // Verify that the database log row count exceeds the row limit.
 | 
			
		||||
    $count = db_query('SELECT COUNT(wid) FROM {watchdog}')->fetchField();
 | 
			
		||||
    $this->assertTrue($count > $row_limit, t('Dblog row count of @count exceeds row limit of @limit', array('@count' => $count, '@limit' => $row_limit)));
 | 
			
		||||
 | 
			
		||||
    // Run cron job.
 | 
			
		||||
    // Run a cron job.
 | 
			
		||||
    $this->cronRun();
 | 
			
		||||
    // Verify dblog row count equals row limit plus one because cron adds a record after it runs.
 | 
			
		||||
    // Verify that the database log row count equals the row limit plus one
 | 
			
		||||
    // because cron adds a record after it runs.
 | 
			
		||||
    $count = db_query('SELECT COUNT(wid) FROM {watchdog}')->fetchField();
 | 
			
		||||
    $this->assertTrue($count == $row_limit + 1, t('Dblog row count of @count equals row limit of @limit plus one', array('@count' => $count, '@limit' => $row_limit)));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Generate dblog entries.
 | 
			
		||||
   * Generates a number of random database log events.
 | 
			
		||||
   *
 | 
			
		||||
   * @param integer $count
 | 
			
		||||
   *   Number of log entries to generate.
 | 
			
		||||
   * @param $type
 | 
			
		||||
   *   The type of watchdog entry.
 | 
			
		||||
   * @param $severity
 | 
			
		||||
   *   The severity of the watchdog entry.
 | 
			
		||||
   * @param int $count
 | 
			
		||||
   *   Number of watchdog entries to generate.
 | 
			
		||||
   * @param string $type
 | 
			
		||||
   *   (optional) The type of watchdog entry. Defaults to 'custom'.
 | 
			
		||||
   * @param int $severity
 | 
			
		||||
   *   (optional) The severity of the watchdog entry. Defaults to WATCHDOG_NOTICE.
 | 
			
		||||
   */
 | 
			
		||||
  private function generateLogEntries($count, $type = 'custom', $severity = WATCHDOG_NOTICE) {
 | 
			
		||||
    global $base_root;
 | 
			
		||||
@@ -119,42 +141,43 @@ class DBLogTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Verify the logged in user has the desired access to the various dblog nodes.
 | 
			
		||||
   * Confirms that database log reports are displayed at the correct paths.
 | 
			
		||||
   *
 | 
			
		||||
   * @param integer $response HTTP response code.
 | 
			
		||||
   * @param int $response
 | 
			
		||||
   *   (optional) HTTP response code. Defaults to 200.
 | 
			
		||||
   */
 | 
			
		||||
  private function verifyReports($response = 200) {
 | 
			
		||||
    $quote = ''';
 | 
			
		||||
 | 
			
		||||
    // View dblog help node.
 | 
			
		||||
    // View the database log help page.
 | 
			
		||||
    $this->drupalGet('admin/help/dblog');
 | 
			
		||||
    $this->assertResponse($response);
 | 
			
		||||
    if ($response == 200) {
 | 
			
		||||
      $this->assertText(t('Database logging'), t('DBLog help was displayed'));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // View dblog report node.
 | 
			
		||||
    // View the database log report page.
 | 
			
		||||
    $this->drupalGet('admin/reports/dblog');
 | 
			
		||||
    $this->assertResponse($response);
 | 
			
		||||
    if ($response == 200) {
 | 
			
		||||
      $this->assertText(t('Recent log messages'), t('DBLog report was displayed'));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // View dblog page-not-found report node.
 | 
			
		||||
    // View the database log page-not-found report page.
 | 
			
		||||
    $this->drupalGet('admin/reports/page-not-found');
 | 
			
		||||
    $this->assertResponse($response);
 | 
			
		||||
    if ($response == 200) {
 | 
			
		||||
      $this->assertText(t('Top ' . $quote . 'page not found' . $quote . ' errors'), t('DBLog page-not-found report was displayed'));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // View dblog access-denied report node.
 | 
			
		||||
    // View the database log access-denied report page.
 | 
			
		||||
    $this->drupalGet('admin/reports/access-denied');
 | 
			
		||||
    $this->assertResponse($response);
 | 
			
		||||
    if ($response == 200) {
 | 
			
		||||
      $this->assertText(t('Top ' . $quote . 'access denied' . $quote . ' errors'), t('DBLog access-denied report was displayed'));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // View dblog event node.
 | 
			
		||||
    // View the database log event page.
 | 
			
		||||
    $this->drupalGet('admin/reports/event/1');
 | 
			
		||||
    $this->assertResponse($response);
 | 
			
		||||
    if ($response == 200) {
 | 
			
		||||
@@ -163,7 +186,7 @@ class DBLogTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Verify events.
 | 
			
		||||
   * Generates and then verifies various types of events.
 | 
			
		||||
   */
 | 
			
		||||
  private function verifyEvents() {
 | 
			
		||||
    // Invoke events.
 | 
			
		||||
@@ -179,14 +202,14 @@ class DBLogTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Generate and verify user events.
 | 
			
		||||
   *
 | 
			
		||||
   * Generates and then verifies some user events.
 | 
			
		||||
   */
 | 
			
		||||
  private function doUser() {
 | 
			
		||||
    // Set user variables.
 | 
			
		||||
    $name = $this->randomName();
 | 
			
		||||
    $pass = user_password();
 | 
			
		||||
    // Add user using form to generate add user event (which is not triggered by drupalCreateUser).
 | 
			
		||||
    // Add a user using the form to generate an add user event (which is not
 | 
			
		||||
    // triggered by drupalCreateUser).
 | 
			
		||||
    $edit = array();
 | 
			
		||||
    $edit['name'] = $name;
 | 
			
		||||
    $edit['mail'] = $name . '@example.com';
 | 
			
		||||
@@ -195,15 +218,16 @@ class DBLogTestCase extends DrupalWebTestCase {
 | 
			
		||||
    $edit['status'] = 1;
 | 
			
		||||
    $this->drupalPost('admin/people/create', $edit, t('Create new account'));
 | 
			
		||||
    $this->assertResponse(200);
 | 
			
		||||
    // Retrieve user object.
 | 
			
		||||
    // Retrieve the user object.
 | 
			
		||||
    $user = user_load_by_name($name);
 | 
			
		||||
    $this->assertTrue($user != NULL, t('User @name was loaded', array('@name' => $name)));
 | 
			
		||||
    $user->pass_raw = $pass; // Needed by drupalLogin.
 | 
			
		||||
    // pass_raw property is needed by drupalLogin.
 | 
			
		||||
    $user->pass_raw = $pass;
 | 
			
		||||
    // Login user.
 | 
			
		||||
    $this->drupalLogin($user);
 | 
			
		||||
    // Logout user.
 | 
			
		||||
    $this->drupalLogout();
 | 
			
		||||
    // Fetch row ids in watchdog that relate to the user.
 | 
			
		||||
    // Fetch the row IDs in watchdog that relate to the user.
 | 
			
		||||
    $result = db_query('SELECT wid FROM {watchdog} WHERE uid = :uid', array(':uid' => $user->uid));
 | 
			
		||||
    foreach ($result as $row) {
 | 
			
		||||
      $ids[] = $row->wid;
 | 
			
		||||
@@ -213,17 +237,18 @@ class DBLogTestCase extends DrupalWebTestCase {
 | 
			
		||||
 | 
			
		||||
    // Login the admin user.
 | 
			
		||||
    $this->drupalLogin($this->big_user);
 | 
			
		||||
    // Delete user.
 | 
			
		||||
    // Delete the user created at the start of this test.
 | 
			
		||||
    // We need to POST here to invoke batch_process() in the internal browser.
 | 
			
		||||
    $this->drupalPost('user/' . $user->uid . '/cancel', array('user_cancel_method' => 'user_cancel_reassign'), t('Cancel account'));
 | 
			
		||||
 | 
			
		||||
    // View the dblog report.
 | 
			
		||||
    // View the database log report.
 | 
			
		||||
    $this->drupalGet('admin/reports/dblog');
 | 
			
		||||
    $this->assertResponse(200);
 | 
			
		||||
 | 
			
		||||
    // Verify events were recorded.
 | 
			
		||||
    // Verify that the expected events were recorded.
 | 
			
		||||
    // Add user.
 | 
			
		||||
    // Default display includes name and email address; if too long then email is replaced by three periods.
 | 
			
		||||
    // Default display includes name and email address; if too long, the email
 | 
			
		||||
    // address is replaced by three periods.
 | 
			
		||||
    $this->assertLogMessage(t('New user: %name (%email).', array('%name' => $name, '%email' => $user->mail)), t('DBLog event was recorded: [add user]'));
 | 
			
		||||
    // Login user.
 | 
			
		||||
    $this->assertLogMessage(t('Session opened for %name.', array('%name' => $name)), t('DBLog event was recorded: [login user]'));
 | 
			
		||||
@@ -232,7 +257,7 @@ class DBLogTestCase extends DrupalWebTestCase {
 | 
			
		||||
    // Delete user.
 | 
			
		||||
    $message = t('Deleted user: %name %email.', array('%name' => $name, '%email' => '<' . $user->mail . '>'));
 | 
			
		||||
    $message_text = truncate_utf8(filter_xss($message, array()), 56, TRUE, TRUE);
 | 
			
		||||
    // Verify full message on details page.
 | 
			
		||||
    // Verify that the full message displays on the details page.
 | 
			
		||||
    $link = FALSE;
 | 
			
		||||
    if ($links = $this->xpath('//a[text()="' . html_entity_decode($message_text) . '"]')) {
 | 
			
		||||
      // Found link with the message text.
 | 
			
		||||
@@ -253,7 +278,7 @@ class DBLogTestCase extends DrupalWebTestCase {
 | 
			
		||||
    $not_found_url = $this->randomName(60);
 | 
			
		||||
    $this->drupalGet($not_found_url);
 | 
			
		||||
    $this->assertResponse(404);
 | 
			
		||||
    // View dblog page-not-found report page.
 | 
			
		||||
    // View the database log page-not-found report page.
 | 
			
		||||
    $this->drupalGet('admin/reports/page-not-found');
 | 
			
		||||
    $this->assertResponse(200);
 | 
			
		||||
    // Check that full-length URL displayed.
 | 
			
		||||
@@ -261,9 +286,10 @@ class DBLogTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Generate and verify node events.
 | 
			
		||||
   * Generates and then verifies some node events.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $type Content type.
 | 
			
		||||
   * @param string $type
 | 
			
		||||
   *   A node type (e.g., 'article', 'page' or 'poll').
 | 
			
		||||
   */
 | 
			
		||||
  private function doNode($type) {
 | 
			
		||||
    // Create user.
 | 
			
		||||
@@ -272,61 +298,65 @@ class DBLogTestCase extends DrupalWebTestCase {
 | 
			
		||||
    // Login user.
 | 
			
		||||
    $this->drupalLogin($user);
 | 
			
		||||
 | 
			
		||||
    // Create node using form to generate add content event (which is not triggered by drupalCreateNode).
 | 
			
		||||
    // Create a node using the form in order to generate an add content event
 | 
			
		||||
    // (which is not triggered by drupalCreateNode).
 | 
			
		||||
    $edit = $this->getContent($type);
 | 
			
		||||
    $langcode = LANGUAGE_NONE;
 | 
			
		||||
    $title = $edit["title"];
 | 
			
		||||
    $this->drupalPost('node/add/' . $type, $edit, t('Save'));
 | 
			
		||||
    $this->assertResponse(200);
 | 
			
		||||
    // Retrieve node object.
 | 
			
		||||
    // Retrieve the node object.
 | 
			
		||||
    $node = $this->drupalGetNodeByTitle($title);
 | 
			
		||||
    $this->assertTrue($node != NULL, t('Node @title was loaded', array('@title' => $title)));
 | 
			
		||||
    // Edit node.
 | 
			
		||||
    // Edit the node.
 | 
			
		||||
    $edit = $this->getContentUpdate($type);
 | 
			
		||||
    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
 | 
			
		||||
    $this->assertResponse(200);
 | 
			
		||||
    // Delete node.
 | 
			
		||||
    // Delete the node.
 | 
			
		||||
    $this->drupalPost('node/' . $node->nid . '/delete', array(), t('Delete'));
 | 
			
		||||
    $this->assertResponse(200);
 | 
			
		||||
    // View node (to generate page not found event).
 | 
			
		||||
    // View the node (to generate page not found event).
 | 
			
		||||
    $this->drupalGet('node/' . $node->nid);
 | 
			
		||||
    $this->assertResponse(404);
 | 
			
		||||
    // View the dblog report (to generate access denied event).
 | 
			
		||||
    // View the database log report (to generate access denied event).
 | 
			
		||||
    $this->drupalGet('admin/reports/dblog');
 | 
			
		||||
    $this->assertResponse(403);
 | 
			
		||||
 | 
			
		||||
    // Login the admin user.
 | 
			
		||||
    $this->drupalLogin($this->big_user);
 | 
			
		||||
    // View the dblog report.
 | 
			
		||||
    // View the database log report.
 | 
			
		||||
    $this->drupalGet('admin/reports/dblog');
 | 
			
		||||
    $this->assertResponse(200);
 | 
			
		||||
 | 
			
		||||
    // Verify events were recorded.
 | 
			
		||||
    // Content added.
 | 
			
		||||
    // Verify that node events were recorded.
 | 
			
		||||
    // Was node content added?
 | 
			
		||||
    $this->assertLogMessage(t('@type: added %title.', array('@type' => $type, '%title' => $title)), t('DBLog event was recorded: [content added]'));
 | 
			
		||||
    // Content updated.
 | 
			
		||||
    // Was node content updated?
 | 
			
		||||
    $this->assertLogMessage(t('@type: updated %title.', array('@type' => $type, '%title' => $title)), t('DBLog event was recorded: [content updated]'));
 | 
			
		||||
    // Content deleted.
 | 
			
		||||
    // Was node content deleted?
 | 
			
		||||
    $this->assertLogMessage(t('@type: deleted %title.', array('@type' => $type, '%title' => $title)), t('DBLog event was recorded: [content deleted]'));
 | 
			
		||||
 | 
			
		||||
    // View dblog access-denied report node.
 | 
			
		||||
    // View the database log access-denied report page.
 | 
			
		||||
    $this->drupalGet('admin/reports/access-denied');
 | 
			
		||||
    $this->assertResponse(200);
 | 
			
		||||
    // Access denied.
 | 
			
		||||
    // Verify that the 'access denied' event was recorded.
 | 
			
		||||
    $this->assertText(t('admin/reports/dblog'), t('DBLog event was recorded: [access denied]'));
 | 
			
		||||
 | 
			
		||||
    // View dblog page-not-found report node.
 | 
			
		||||
    // View the database log page-not-found report page.
 | 
			
		||||
    $this->drupalGet('admin/reports/page-not-found');
 | 
			
		||||
    $this->assertResponse(200);
 | 
			
		||||
    // Page not found.
 | 
			
		||||
    // Verify that the 'page not found' event was recorded.
 | 
			
		||||
    $this->assertText(t('node/@nid', array('@nid' => $node->nid)), t('DBLog event was recorded: [page not found]'));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create content based on content type.
 | 
			
		||||
   * Creates random content based on node content type.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $type Content type.
 | 
			
		||||
   * @return array Content.
 | 
			
		||||
   * @param string $type
 | 
			
		||||
   *   Node content type (e.g., 'article').
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   Random content needed by various node types.
 | 
			
		||||
   */
 | 
			
		||||
  private function getContent($type) {
 | 
			
		||||
    $langcode = LANGUAGE_NONE;
 | 
			
		||||
@@ -350,10 +380,13 @@ class DBLogTestCase extends DrupalWebTestCase {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create content update based on content type.
 | 
			
		||||
   * Creates random content as an update based on node content type.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $type 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 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);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -1735,11 +1735,14 @@ function hook_field_storage_details_alter(&$details, $field) {
 | 
			
		||||
 *     loaded.
 | 
			
		||||
 */
 | 
			
		||||
function hook_field_storage_load($entity_type, $entities, $age, $fields, $options) {
 | 
			
		||||
  $field_info = field_info_field_by_ids();
 | 
			
		||||
  $load_current = $age == FIELD_LOAD_CURRENT;
 | 
			
		||||
 | 
			
		||||
  foreach ($fields as $field_id => $ids) {
 | 
			
		||||
    $field = $field_info[$field_id];
 | 
			
		||||
    // By the time this hook runs, the relevant field definitions have been
 | 
			
		||||
    // populated and cached in FieldInfo, so calling field_info_field_by_id()
 | 
			
		||||
    // on each field individually is more efficient than loading all fields in
 | 
			
		||||
    // memory upfront with field_info_field_by_ids().
 | 
			
		||||
    $field = field_info_field_by_id($field_id);
 | 
			
		||||
    $field_name = $field['field_name'];
 | 
			
		||||
    $table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -283,7 +283,6 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
 | 
			
		||||
    'language' => NULL,
 | 
			
		||||
  );
 | 
			
		||||
  $options += $default_options;
 | 
			
		||||
  $field_info = field_info_field_by_ids();
 | 
			
		||||
 | 
			
		||||
  $fields = array();
 | 
			
		||||
  $grouped_instances = array();
 | 
			
		||||
@@ -307,7 +306,7 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
 | 
			
		||||
    foreach ($instances as $instance) {
 | 
			
		||||
      $field_id = $instance['field_id'];
 | 
			
		||||
      $field_name = $instance['field_name'];
 | 
			
		||||
      $field = $field_info[$field_id];
 | 
			
		||||
      $field = field_info_field_by_id($field_id);
 | 
			
		||||
      $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
 | 
			
		||||
      if (function_exists($function)) {
 | 
			
		||||
        // Add the field to the list of fields to invoke the hook on.
 | 
			
		||||
@@ -555,16 +554,23 @@ function _field_invoke_get_instances($entity_type, $bundle, $options) {
 | 
			
		||||
 * @param $langcode
 | 
			
		||||
 *   The language the field values are going to be entered, if no language
 | 
			
		||||
 *   is provided the default site language will be used.
 | 
			
		||||
 * @param array $options
 | 
			
		||||
 *   An associative array of additional options. See _field_invoke() for
 | 
			
		||||
 *   details.
 | 
			
		||||
 *
 | 
			
		||||
 * @see field_form_get_state()
 | 
			
		||||
 * @see field_form_set_state()
 | 
			
		||||
 */
 | 
			
		||||
function field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode = NULL) {
 | 
			
		||||
function field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode = NULL, $options = array()) {
 | 
			
		||||
  // Validate $options since this is a new parameter added after Drupal 7 was
 | 
			
		||||
  // released.
 | 
			
		||||
  $options = is_array($options) ? $options : array();
 | 
			
		||||
 | 
			
		||||
  // Set #parents to 'top-level' by default.
 | 
			
		||||
  $form += array('#parents' => array());
 | 
			
		||||
 | 
			
		||||
  // If no language is provided use the default site language.
 | 
			
		||||
  $options = array('language' => field_valid_language($langcode));
 | 
			
		||||
  $options['language'] = field_valid_language($langcode);
 | 
			
		||||
  $form += (array) _field_invoke_default('form', $entity_type, $entity, $form, $form_state, $options);
 | 
			
		||||
 | 
			
		||||
  // Add custom weight handling.
 | 
			
		||||
@@ -614,7 +620,6 @@ function field_attach_form($entity_type, $entity, &$form, &$form_state, $langcod
 | 
			
		||||
 *     non-deleted fields are operated on.
 | 
			
		||||
 */
 | 
			
		||||
function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $options = array()) {
 | 
			
		||||
  $field_info = field_info_field_by_ids();
 | 
			
		||||
  $load_current = $age == FIELD_LOAD_CURRENT;
 | 
			
		||||
 | 
			
		||||
  // Merge default options.
 | 
			
		||||
@@ -692,7 +697,7 @@ function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $
 | 
			
		||||
        }
 | 
			
		||||
        // Collect the storage backend if the field has not been loaded yet.
 | 
			
		||||
        if (!isset($skip_fields[$field_id])) {
 | 
			
		||||
          $field = $field_info[$field_id];
 | 
			
		||||
          $field = field_info_field_by_id($field_id);
 | 
			
		||||
          $storages[$field['storage']['type']][$field_id][] = $load_current ? $id : $vid;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
@@ -709,7 +714,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.
 | 
			
		||||
@@ -769,13 +774,21 @@ function field_attach_load_revision($entity_type, $entities, $options = array())
 | 
			
		||||
 *   If validation errors are found, a FieldValidationException is thrown. The
 | 
			
		||||
 *   'errors' property contains the array of errors, keyed by field name,
 | 
			
		||||
 *   language and delta.
 | 
			
		||||
 * @param array $options
 | 
			
		||||
 *   An associative array of additional options. See _field_invoke() for
 | 
			
		||||
 *   details.
 | 
			
		||||
 */
 | 
			
		||||
function field_attach_validate($entity_type, $entity) {
 | 
			
		||||
function field_attach_validate($entity_type, $entity, $options = array()) {
 | 
			
		||||
  // Validate $options since this is a new parameter added after Drupal 7 was
 | 
			
		||||
  // released.
 | 
			
		||||
  $options = is_array($options) ? $options : array();
 | 
			
		||||
 | 
			
		||||
  $errors = array();
 | 
			
		||||
  // Check generic, field-type-agnostic errors first.
 | 
			
		||||
  _field_invoke_default('validate', $entity_type, $entity, $errors);
 | 
			
		||||
  $null = NULL;
 | 
			
		||||
  _field_invoke_default('validate', $entity_type, $entity, $errors, $null, $options);
 | 
			
		||||
  // Check field-type specific errors.
 | 
			
		||||
  _field_invoke('validate', $entity_type, $entity, $errors);
 | 
			
		||||
  _field_invoke('validate', $entity_type, $entity, $errors, $null, $options);
 | 
			
		||||
 | 
			
		||||
  // Let other modules validate the entity.
 | 
			
		||||
  // Avoid module_invoke_all() to let $errors be taken by reference.
 | 
			
		||||
@@ -817,14 +830,21 @@ function field_attach_validate($entity_type, $entity) {
 | 
			
		||||
 *   full form structure, or a sub-element of a larger form.
 | 
			
		||||
 * @param $form_state
 | 
			
		||||
 *   An associative array containing the current state of the form.
 | 
			
		||||
 * @param array $options
 | 
			
		||||
 *   An associative array of additional options. See _field_invoke() for
 | 
			
		||||
 *   details.
 | 
			
		||||
 */
 | 
			
		||||
function field_attach_form_validate($entity_type, $entity, $form, &$form_state) {
 | 
			
		||||
function field_attach_form_validate($entity_type, $entity, $form, &$form_state, $options = array()) {
 | 
			
		||||
  // Validate $options since this is a new parameter added after Drupal 7 was
 | 
			
		||||
  // released.
 | 
			
		||||
  $options = is_array($options) ? $options : array();
 | 
			
		||||
 | 
			
		||||
  // Extract field values from submitted values.
 | 
			
		||||
  _field_invoke_default('extract_form_values', $entity_type, $entity, $form, $form_state);
 | 
			
		||||
 | 
			
		||||
  // Perform field_level validation.
 | 
			
		||||
  try {
 | 
			
		||||
    field_attach_validate($entity_type, $entity);
 | 
			
		||||
    field_attach_validate($entity_type, $entity, $options);
 | 
			
		||||
  }
 | 
			
		||||
  catch (FieldValidationException $e) {
 | 
			
		||||
    // Pass field-level validation errors back to widgets for accurate error
 | 
			
		||||
@@ -836,7 +856,7 @@ function field_attach_form_validate($entity_type, $entity, $form, &$form_state)
 | 
			
		||||
        field_form_set_state($form['#parents'], $field_name, $langcode, $form_state, $field_state);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    _field_invoke_default('form_errors', $entity_type, $entity, $form, $form_state);
 | 
			
		||||
    _field_invoke_default('form_errors', $entity_type, $entity, $form, $form_state, $options);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -857,12 +877,19 @@ function field_attach_form_validate($entity_type, $entity, $form, &$form_state)
 | 
			
		||||
 *   full form structure, or a sub-element of a larger form.
 | 
			
		||||
 * @param $form_state
 | 
			
		||||
 *   An associative array containing the current state of the form.
 | 
			
		||||
 * @param array $options
 | 
			
		||||
 *   An associative array of additional options. See _field_invoke() for
 | 
			
		||||
 *   details.
 | 
			
		||||
 */
 | 
			
		||||
function field_attach_submit($entity_type, $entity, $form, &$form_state) {
 | 
			
		||||
  // Extract field values from submitted values.
 | 
			
		||||
  _field_invoke_default('extract_form_values', $entity_type, $entity, $form, $form_state);
 | 
			
		||||
function field_attach_submit($entity_type, $entity, $form, &$form_state, $options = array()) {
 | 
			
		||||
  // Validate $options since this is a new parameter added after Drupal 7 was
 | 
			
		||||
  // released.
 | 
			
		||||
  $options = is_array($options) ? $options : array();
 | 
			
		||||
 | 
			
		||||
  _field_invoke_default('submit', $entity_type, $entity, $form, $form_state);
 | 
			
		||||
  // Extract field values from submitted values.
 | 
			
		||||
  _field_invoke_default('extract_form_values', $entity_type, $entity, $form, $form_state, $options);
 | 
			
		||||
 | 
			
		||||
  _field_invoke_default('submit', $entity_type, $entity, $form, $form_state, $options);
 | 
			
		||||
 | 
			
		||||
  // Let other modules act on submitting the entity.
 | 
			
		||||
  // Avoid module_invoke_all() to let $form_state be taken by reference.
 | 
			
		||||
@@ -1093,9 +1120,16 @@ function field_attach_delete_revision($entity_type, $entity) {
 | 
			
		||||
 * @param $langcode
 | 
			
		||||
 *   (Optional) The language the field values are to be shown in. If no language
 | 
			
		||||
 *   is provided the current language is used.
 | 
			
		||||
 * @param array $options
 | 
			
		||||
 *   An associative array of additional options. See _field_invoke() for
 | 
			
		||||
 *   details.
 | 
			
		||||
 */
 | 
			
		||||
function field_attach_prepare_view($entity_type, $entities, $view_mode, $langcode = NULL) {
 | 
			
		||||
  $options = array('language' => array());
 | 
			
		||||
function field_attach_prepare_view($entity_type, $entities, $view_mode, $langcode = NULL, $options = array()) {
 | 
			
		||||
  // Validate $options since this is a new parameter added after Drupal 7 was
 | 
			
		||||
  // released.
 | 
			
		||||
  $options = is_array($options) ? $options : array();
 | 
			
		||||
 | 
			
		||||
  $options['language'] = array();
 | 
			
		||||
 | 
			
		||||
  // To ensure hooks are only run once per entity, only process items without
 | 
			
		||||
  // the _field_view_prepared flag.
 | 
			
		||||
@@ -1167,14 +1201,21 @@ function field_attach_prepare_view($entity_type, $entities, $view_mode, $langcod
 | 
			
		||||
 * @param $langcode
 | 
			
		||||
 *   The language the field values are to be shown in. If no language is
 | 
			
		||||
 *   provided the current language is used.
 | 
			
		||||
 * @param array $options
 | 
			
		||||
 *   An associative array of additional options. See _field_invoke() for
 | 
			
		||||
 *   details.
 | 
			
		||||
 * @return
 | 
			
		||||
 *   A renderable array for the field values.
 | 
			
		||||
 */
 | 
			
		||||
function field_attach_view($entity_type, $entity, $view_mode, $langcode = NULL) {
 | 
			
		||||
function field_attach_view($entity_type, $entity, $view_mode, $langcode = NULL, $options = array()) {
 | 
			
		||||
  // Validate $options since this is a new parameter added after Drupal 7 was
 | 
			
		||||
  // released.
 | 
			
		||||
  $options = is_array($options) ? $options : array();
 | 
			
		||||
 | 
			
		||||
  // Determine the actual language to display for each field, given the
 | 
			
		||||
  // languages available in the field data.
 | 
			
		||||
  $display_language = field_language($entity_type, $entity, NULL, $langcode);
 | 
			
		||||
  $options = array('language' => $display_language);
 | 
			
		||||
  $options['language'] = $display_language;
 | 
			
		||||
 | 
			
		||||
  // Invoke field_default_view().
 | 
			
		||||
  $null = NULL;
 | 
			
		||||
 
 | 
			
		||||
@@ -319,7 +319,11 @@ function field_read_field($field_name, $include_additional = array()) {
 | 
			
		||||
 * Reads in fields that match an array of conditions.
 | 
			
		||||
 *
 | 
			
		||||
 * @param array $params
 | 
			
		||||
 *   An array of conditions to match against.
 | 
			
		||||
 *   An array of conditions to match against. Keys are columns from the
 | 
			
		||||
 *   'field_config' table, values are conditions to match. Additionally,
 | 
			
		||||
 *   conditions on the 'entity_type' and 'bundle' columns from the
 | 
			
		||||
 *   'field_config_instance' table are supported (select fields having an
 | 
			
		||||
 *   instance on a given bundle).
 | 
			
		||||
 * @param array $include_additional
 | 
			
		||||
 *   The default behavior of this function is to not return fields that
 | 
			
		||||
 *   are inactive or have been deleted. Setting
 | 
			
		||||
@@ -337,8 +341,21 @@ function field_read_fields($params = array(), $include_additional = array()) {
 | 
			
		||||
 | 
			
		||||
  // Turn the conditions into a query.
 | 
			
		||||
  foreach ($params as $key => $value) {
 | 
			
		||||
    // Allow filtering on the 'entity_type' and 'bundle' columns of the
 | 
			
		||||
    // field_config_instance table.
 | 
			
		||||
    if ($key == 'entity_type' || $key == 'bundle') {
 | 
			
		||||
      if (empty($fci_join)) {
 | 
			
		||||
        $fci_join = $query->join('field_config_instance', 'fci', 'fc.id = fci.field_id');
 | 
			
		||||
      }
 | 
			
		||||
      $key = 'fci.' . $key;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      $key = 'fc.' . $key;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $query->condition($key, $value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!isset($include_additional['include_inactive']) || !$include_additional['include_inactive']) {
 | 
			
		||||
    $query
 | 
			
		||||
      ->condition('fc.active', 1)
 | 
			
		||||
 
 | 
			
		||||
@@ -5,13 +5,14 @@ version = VERSION
 | 
			
		||||
core = 7.x
 | 
			
		||||
files[] = field.module
 | 
			
		||||
files[] = field.attach.inc
 | 
			
		||||
files[] = field.info.class.inc
 | 
			
		||||
files[] = tests/field.test
 | 
			
		||||
dependencies[] = field_sql_storage
 | 
			
		||||
required = TRUE
 | 
			
		||||
stylesheets[all][] = theme/field.css
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										668
									
								
								modules/field/field.info.class.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										668
									
								
								modules/field/field.info.class.inc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,668 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * @file
 | 
			
		||||
 * Definition of the FieldInfo class.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides field and instance definitions for the current runtime environment.
 | 
			
		||||
 *
 | 
			
		||||
 * A FieldInfo object is created and statically persisted through the request
 | 
			
		||||
 * by the _field_info_field_cache() function. The object properties act as a
 | 
			
		||||
 * "static cache" of fields and instances definitions.
 | 
			
		||||
 *
 | 
			
		||||
 * The preferred way to access definitions is through the getBundleInstances()
 | 
			
		||||
 * method, which keeps cache entries per bundle, storing both fields and
 | 
			
		||||
 * instances for a given bundle. Fields used in multiple bundles are duplicated
 | 
			
		||||
 * in several cache entries, and are merged into a single list in the memory
 | 
			
		||||
 * cache. Cache entries are loaded for bundles as a whole, optimizing memory
 | 
			
		||||
 * and CPU usage for the most common pattern of iterating over all instances of
 | 
			
		||||
 * a bundle rather than accessing a single instance.
 | 
			
		||||
 *
 | 
			
		||||
 * The getFields() and getInstances() methods, which return all existing field
 | 
			
		||||
 * and instance definitions, are kept mainly for backwards compatibility, and
 | 
			
		||||
 * should be avoided when possible, since they load and persist in memory a
 | 
			
		||||
 * potentially large array of information. In many cases, the lightweight
 | 
			
		||||
 * getFieldMap() method should be preferred.
 | 
			
		||||
 */
 | 
			
		||||
class FieldInfo {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Lightweight map of fields across entity types and bundles.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $fieldMap;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * List of $field structures keyed by ID. Includes deleted fields.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $fieldsById = array();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Mapping of field names to the ID of the corresponding non-deleted field.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $fieldIdsByName = array();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Whether $fieldsById contains all field definitions or a subset.
 | 
			
		||||
   *
 | 
			
		||||
   * @var bool
 | 
			
		||||
   */
 | 
			
		||||
  protected $loadedAllFields = FALSE;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Separately tracks requested field names or IDs that do not exist.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $unknownFields = array();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Instance definitions by bundle.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $bundleInstances = array();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Whether $bundleInstances contains all instances definitions or a subset.
 | 
			
		||||
   *
 | 
			
		||||
   * @var bool
 | 
			
		||||
   */
 | 
			
		||||
  protected $loadedAllInstances = FALSE;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Separately tracks requested bundles that are empty (or do not exist).
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $emptyBundles = array();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Extra fields by bundle.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $bundleExtraFields = array();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Clears the "static" and persistent caches.
 | 
			
		||||
   */
 | 
			
		||||
  public function flush() {
 | 
			
		||||
    $this->fieldMap = NULL;
 | 
			
		||||
 | 
			
		||||
    $this->fieldsById = array();
 | 
			
		||||
    $this->fieldIdsByName = array();
 | 
			
		||||
    $this->loadedAllFields = FALSE;
 | 
			
		||||
    $this->unknownFields = array();
 | 
			
		||||
 | 
			
		||||
    $this->bundleInstances = array();
 | 
			
		||||
    $this->loadedAllInstances = FALSE;
 | 
			
		||||
    $this->emptyBundles = array();
 | 
			
		||||
 | 
			
		||||
    $this->bundleExtraFields = array();
 | 
			
		||||
 | 
			
		||||
    cache_clear_all('field_info:', 'cache_field', TRUE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Collects a lightweight map of fields across bundles.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   An array keyed by field name. Each value is an array with two entries:
 | 
			
		||||
   *   - type: The field type.
 | 
			
		||||
   *   - bundles: The bundles in which the field appears, as an array with
 | 
			
		||||
   *     entity types as keys and the array of bundle names as values.
 | 
			
		||||
   */
 | 
			
		||||
  public function getFieldMap() {
 | 
			
		||||
    // Read from the "static" cache.
 | 
			
		||||
    if ($this->fieldMap !== NULL) {
 | 
			
		||||
      return $this->fieldMap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Read from persistent cache.
 | 
			
		||||
    if ($cached = cache_get('field_info:field_map', 'cache_field')) {
 | 
			
		||||
      $map = $cached->data;
 | 
			
		||||
 | 
			
		||||
      // Save in "static" cache.
 | 
			
		||||
      $this->fieldMap = $map;
 | 
			
		||||
 | 
			
		||||
      return $map;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $map = array();
 | 
			
		||||
 | 
			
		||||
    $query = db_query('SELECT fc.type, fci.field_name, fci.entity_type, fci.bundle FROM {field_config_instance} fci INNER JOIN {field_config} fc ON fc.id = fci.field_id WHERE fc.active = 1 AND fc.storage_active = 1 AND fc.deleted = 0 AND fci.deleted = 0');
 | 
			
		||||
    foreach ($query as $row) {
 | 
			
		||||
      $map[$row->field_name]['bundles'][$row->entity_type][] = $row->bundle;
 | 
			
		||||
      $map[$row->field_name]['type'] = $row->type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Save in "static" and persistent caches.
 | 
			
		||||
    $this->fieldMap = $map;
 | 
			
		||||
    cache_set('field_info:field_map', $map, 'cache_field');
 | 
			
		||||
 | 
			
		||||
    return $map;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns all active fields, including deleted ones.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   An array of field definitions, keyed by field ID.
 | 
			
		||||
   */
 | 
			
		||||
  public function getFields() {
 | 
			
		||||
    // Read from the "static" cache.
 | 
			
		||||
    if ($this->loadedAllFields) {
 | 
			
		||||
      return $this->fieldsById;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Read from persistent cache.
 | 
			
		||||
    if ($cached = cache_get('field_info:fields', 'cache_field')) {
 | 
			
		||||
      $this->fieldsById = $cached->data;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      // Collect and prepare fields.
 | 
			
		||||
      foreach (field_read_fields(array(), array('include_deleted' => TRUE)) as $field) {
 | 
			
		||||
        $this->fieldsById[$field['id']] = $this->prepareField($field);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Store in persistent cache.
 | 
			
		||||
      cache_set('field_info:fields', $this->fieldsById, 'cache_field');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Fill the name/ID map.
 | 
			
		||||
    foreach ($this->fieldsById as $field) {
 | 
			
		||||
      if (!$field['deleted']) {
 | 
			
		||||
        $this->fieldIdsByName[$field['field_name']] = $field['id'];
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $this->loadedAllFields = TRUE;
 | 
			
		||||
 | 
			
		||||
    return $this->fieldsById;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Retrieves all active, non-deleted instances definitions.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $entity_type
 | 
			
		||||
   *   (optional) The entity type.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   If $entity_type is not set, all instances keyed by entity type and bundle
 | 
			
		||||
   *   name. If $entity_type is set, all instances for that entity type, keyed
 | 
			
		||||
   *   by bundle name.
 | 
			
		||||
   */
 | 
			
		||||
  public function getInstances($entity_type = NULL) {
 | 
			
		||||
    // If the full list is not present in "static" cache yet.
 | 
			
		||||
    if (!$this->loadedAllInstances) {
 | 
			
		||||
 | 
			
		||||
      // Read from persistent cache.
 | 
			
		||||
      if ($cached = cache_get('field_info:instances', 'cache_field')) {
 | 
			
		||||
        $this->bundleInstances = $cached->data;
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        // Collect and prepare instances.
 | 
			
		||||
 | 
			
		||||
        // We also need to populate the static field cache, since it will not
 | 
			
		||||
        // be set by subsequent getBundleInstances() calls.
 | 
			
		||||
        $this->getFields();
 | 
			
		||||
 | 
			
		||||
        // Initialize empty arrays for all existing entity types and bundles.
 | 
			
		||||
        // This is not strictly needed, but is done to preserve the behavior of
 | 
			
		||||
        // field_info_instances() before http://drupal.org/node/1915646.
 | 
			
		||||
        foreach (field_info_bundles() as $existing_entity_type => $bundles) {
 | 
			
		||||
          foreach ($bundles as $bundle => $bundle_info) {
 | 
			
		||||
            $this->bundleInstances[$existing_entity_type][$bundle] = array();
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach (field_read_instances() as $instance) {
 | 
			
		||||
          $field = $this->getField($instance['field_name']);
 | 
			
		||||
          $instance = $this->prepareInstance($instance, $field['type']);
 | 
			
		||||
          $this->bundleInstances[$instance['entity_type']][$instance['bundle']][$instance['field_name']] = $instance;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Store in persistent cache.
 | 
			
		||||
        cache_set('field_info:instances', $this->bundleInstances, 'cache_field');
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      $this->loadedAllInstances = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (isset($entity_type)) {
 | 
			
		||||
      return isset($this->bundleInstances[$entity_type]) ? $this->bundleInstances[$entity_type] : array();
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      return $this->bundleInstances;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns a field definition from a field name.
 | 
			
		||||
   *
 | 
			
		||||
   * This method only retrieves active, non-deleted fields.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $field_name
 | 
			
		||||
   *   The field name.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   The field definition, or NULL if no field was found.
 | 
			
		||||
   */
 | 
			
		||||
  public function getField($field_name) {
 | 
			
		||||
    // Read from the "static" cache.
 | 
			
		||||
    if (isset($this->fieldIdsByName[$field_name])) {
 | 
			
		||||
      $field_id = $this->fieldIdsByName[$field_name];
 | 
			
		||||
      return $this->fieldsById[$field_id];
 | 
			
		||||
    }
 | 
			
		||||
    if (isset($this->unknownFields[$field_name])) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Do not check the (large) persistent cache, but read the definition.
 | 
			
		||||
 | 
			
		||||
    // Cache miss: read from definition.
 | 
			
		||||
    if ($field = field_read_field($field_name)) {
 | 
			
		||||
      $field = $this->prepareField($field);
 | 
			
		||||
 | 
			
		||||
      // Save in the "static" cache.
 | 
			
		||||
      $this->fieldsById[$field['id']] = $field;
 | 
			
		||||
      $this->fieldIdsByName[$field['field_name']] = $field['id'];
 | 
			
		||||
 | 
			
		||||
      return $field;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      $this->unknownFields[$field_name] = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns a field definition from a field ID.
 | 
			
		||||
   *
 | 
			
		||||
   * This method only retrieves active fields, deleted or not.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $field_id
 | 
			
		||||
   *   The field ID.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   The field definition, or NULL if no field was found.
 | 
			
		||||
   */
 | 
			
		||||
  public function getFieldById($field_id) {
 | 
			
		||||
    // Read from the "static" cache.
 | 
			
		||||
    if (isset($this->fieldsById[$field_id])) {
 | 
			
		||||
      return $this->fieldsById[$field_id];
 | 
			
		||||
    }
 | 
			
		||||
    if (isset($this->unknownFields[$field_id])) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // No persistent cache, fields are only persistently cached as part of a
 | 
			
		||||
    // bundle.
 | 
			
		||||
 | 
			
		||||
    // Cache miss: read from definition.
 | 
			
		||||
    if ($fields = field_read_fields(array('id' => $field_id), array('include_deleted' => TRUE))) {
 | 
			
		||||
      $field = current($fields);
 | 
			
		||||
      $field = $this->prepareField($field);
 | 
			
		||||
 | 
			
		||||
      // Store in the static cache.
 | 
			
		||||
      $this->fieldsById[$field['id']] = $field;
 | 
			
		||||
      if (!$field['deleted']) {
 | 
			
		||||
        $this->fieldIdsByName[$field['field_name']] = $field['id'];
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return $field;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      $this->unknownFields[$field_id] = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Retrieves the instances for a bundle.
 | 
			
		||||
   *
 | 
			
		||||
   * The function also populates the corresponding field definitions in the
 | 
			
		||||
   * "static" cache.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $entity_type
 | 
			
		||||
   *   The entity type.
 | 
			
		||||
   * @param $bundle
 | 
			
		||||
   *   The bundle name.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   The array of instance definitions, keyed by field name.
 | 
			
		||||
   */
 | 
			
		||||
  public function getBundleInstances($entity_type, $bundle) {
 | 
			
		||||
    // Read from the "static" cache.
 | 
			
		||||
    if (isset($this->bundleInstances[$entity_type][$bundle])) {
 | 
			
		||||
      return $this->bundleInstances[$entity_type][$bundle];
 | 
			
		||||
    }
 | 
			
		||||
    if (isset($this->emptyBundles[$entity_type][$bundle])) {
 | 
			
		||||
      return array();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Read from the persistent cache.
 | 
			
		||||
    if ($cached = cache_get("field_info:bundle:$entity_type:$bundle", 'cache_field')) {
 | 
			
		||||
      $info = $cached->data;
 | 
			
		||||
 | 
			
		||||
      // Extract the field definitions and save them in the "static" cache.
 | 
			
		||||
      foreach ($info['fields'] as $field) {
 | 
			
		||||
        if (!isset($this->fieldsById[$field['id']])) {
 | 
			
		||||
          $this->fieldsById[$field['id']] = $field;
 | 
			
		||||
          if (!$field['deleted']) {
 | 
			
		||||
            $this->fieldIdsByName[$field['field_name']] = $field['id'];
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      unset($info['fields']);
 | 
			
		||||
 | 
			
		||||
      // Store the instance definitions in the "static" cache'. Empty (or
 | 
			
		||||
      // non-existent) bundles are stored separately, so that they do not
 | 
			
		||||
      // pollute the global list returned by getInstances().
 | 
			
		||||
      if ($info['instances']) {
 | 
			
		||||
        $this->bundleInstances[$entity_type][$bundle] = $info['instances'];
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        $this->emptyBundles[$entity_type][$bundle] = TRUE;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return $info['instances'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Cache miss: collect from the definitions.
 | 
			
		||||
 | 
			
		||||
    $instances = array();
 | 
			
		||||
 | 
			
		||||
    // Collect the fields in the bundle.
 | 
			
		||||
    $params = array('entity_type' => $entity_type, 'bundle' => $bundle);
 | 
			
		||||
    $fields = field_read_fields($params);
 | 
			
		||||
 | 
			
		||||
    // This iterates on non-deleted instances, so deleted fields are kept out of
 | 
			
		||||
    // the persistent caches.
 | 
			
		||||
    foreach (field_read_instances($params) as $instance) {
 | 
			
		||||
      $field = $fields[$instance['field_name']];
 | 
			
		||||
 | 
			
		||||
      $instance = $this->prepareInstance($instance, $field['type']);
 | 
			
		||||
      $instances[$field['field_name']] = $instance;
 | 
			
		||||
 | 
			
		||||
      // If the field is not in our global "static" list yet, add it.
 | 
			
		||||
      if (!isset($this->fieldsById[$field['id']])) {
 | 
			
		||||
        $field = $this->prepareField($field);
 | 
			
		||||
 | 
			
		||||
        $this->fieldsById[$field['id']] = $field;
 | 
			
		||||
        $this->fieldIdsByName[$field['field_name']] = $field['id'];
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Store in the 'static' cache'. Empty (or non-existent) bundles are stored
 | 
			
		||||
    // separately, so that they do not pollute the global list returned by
 | 
			
		||||
    // getInstances().
 | 
			
		||||
    if ($instances) {
 | 
			
		||||
      $this->bundleInstances[$entity_type][$bundle] = $instances;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      $this->emptyBundles[$entity_type][$bundle] = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // The persistent cache additionally contains the definitions of the fields
 | 
			
		||||
    // involved in the bundle.
 | 
			
		||||
    $cache = array(
 | 
			
		||||
      'instances' => $instances,
 | 
			
		||||
      'fields' => array()
 | 
			
		||||
    );
 | 
			
		||||
    foreach ($instances as $instance) {
 | 
			
		||||
      $cache['fields'][] = $this->fieldsById[$instance['field_id']];
 | 
			
		||||
    }
 | 
			
		||||
    cache_set("field_info:bundle:$entity_type:$bundle", $cache, 'cache_field');
 | 
			
		||||
 | 
			
		||||
    return $instances;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Retrieves the "extra fields" for a bundle.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $entity_type
 | 
			
		||||
   *   The entity type.
 | 
			
		||||
   * @param $bundle
 | 
			
		||||
   *   The bundle name.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   The array of extra fields.
 | 
			
		||||
   */
 | 
			
		||||
  public function getBundleExtraFields($entity_type, $bundle) {
 | 
			
		||||
    // Read from the "static" cache.
 | 
			
		||||
    if (isset($this->bundleExtraFields[$entity_type][$bundle])) {
 | 
			
		||||
      return $this->bundleExtraFields[$entity_type][$bundle];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Read from the persistent cache.
 | 
			
		||||
    if ($cached = cache_get("field_info:bundle_extra:$entity_type:$bundle", 'cache_field')) {
 | 
			
		||||
      $this->bundleExtraFields[$entity_type][$bundle] = $cached->data;
 | 
			
		||||
      return $this->bundleExtraFields[$entity_type][$bundle];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Cache miss: read from hook_field_extra_fields(). Note: given the current
 | 
			
		||||
    // shape of the hook, we have no other way than collecting extra fields on
 | 
			
		||||
    // all bundles.
 | 
			
		||||
    $info = array();
 | 
			
		||||
    $extra = module_invoke_all('field_extra_fields');
 | 
			
		||||
    drupal_alter('field_extra_fields', $extra);
 | 
			
		||||
    // Merge in saved settings.
 | 
			
		||||
    if (isset($extra[$entity_type][$bundle])) {
 | 
			
		||||
      $info = $this->prepareExtraFields($extra[$entity_type][$bundle], $entity_type, $bundle);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Store in the 'static' and persistent caches.
 | 
			
		||||
    $this->bundleExtraFields[$entity_type][$bundle] = $info;
 | 
			
		||||
    cache_set("field_info:bundle_extra:$entity_type:$bundle", $info, 'cache_field');
 | 
			
		||||
 | 
			
		||||
    return $this->bundleExtraFields[$entity_type][$bundle];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Prepares a field definition for the current run-time context.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $field
 | 
			
		||||
   *   The raw field structure as read from the database.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   The field definition completed for the current runtime context.
 | 
			
		||||
   */
 | 
			
		||||
  public function prepareField($field) {
 | 
			
		||||
    // Make sure all expected field settings are present.
 | 
			
		||||
    $field['settings'] += field_info_field_settings($field['type']);
 | 
			
		||||
    $field['storage']['settings'] += field_info_storage_settings($field['storage']['type']);
 | 
			
		||||
 | 
			
		||||
    // Add storage details.
 | 
			
		||||
    $details = (array) module_invoke($field['storage']['module'], 'field_storage_details', $field);
 | 
			
		||||
    drupal_alter('field_storage_details', $details, $field);
 | 
			
		||||
    $field['storage']['details'] = $details;
 | 
			
		||||
 | 
			
		||||
    // Populate the list of bundles using the field.
 | 
			
		||||
    $field['bundles'] = array();
 | 
			
		||||
    if (!$field['deleted']) {
 | 
			
		||||
      $map = $this->getFieldMap();
 | 
			
		||||
      if (isset($map[$field['field_name']])) {
 | 
			
		||||
        $field['bundles'] = $map[$field['field_name']]['bundles'];
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return $field;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Prepares an instance definition for the current run-time context.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $instance
 | 
			
		||||
   *   The raw instance structure as read from the database.
 | 
			
		||||
   * @param $field_type
 | 
			
		||||
   *   The field type.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   The field instance array completed for the current runtime context.
 | 
			
		||||
   */
 | 
			
		||||
  public function prepareInstance($instance, $field_type) {
 | 
			
		||||
    // Make sure all expected instance settings are present.
 | 
			
		||||
    $instance['settings'] += field_info_instance_settings($field_type);
 | 
			
		||||
 | 
			
		||||
    // Set a default value for the instance.
 | 
			
		||||
    if (field_behaviors_widget('default value', $instance) == FIELD_BEHAVIOR_DEFAULT && !isset($instance['default_value'])) {
 | 
			
		||||
      $instance['default_value'] = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Prepare widget settings.
 | 
			
		||||
    $instance['widget'] = $this->prepareInstanceWidget($instance['widget'], $field_type);
 | 
			
		||||
 | 
			
		||||
    // Prepare display settings.
 | 
			
		||||
    foreach ($instance['display'] as $view_mode => $display) {
 | 
			
		||||
      $instance['display'][$view_mode] = $this->prepareInstanceDisplay($display, $field_type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Fall back to 'hidden' for view modes configured to use custom display
 | 
			
		||||
    // settings, and for which the instance has no explicit settings.
 | 
			
		||||
    $entity_info = entity_get_info($instance['entity_type']);
 | 
			
		||||
    $view_modes = array_merge(array('default'), array_keys($entity_info['view modes']));
 | 
			
		||||
    $view_mode_settings = field_view_mode_settings($instance['entity_type'], $instance['bundle']);
 | 
			
		||||
    foreach ($view_modes as $view_mode) {
 | 
			
		||||
      if ($view_mode == 'default' || !empty($view_mode_settings[$view_mode]['custom_settings'])) {
 | 
			
		||||
        if (!isset($instance['display'][$view_mode])) {
 | 
			
		||||
          $instance['display'][$view_mode] = array(
 | 
			
		||||
            'type' => 'hidden',
 | 
			
		||||
            'label' => 'above',
 | 
			
		||||
            'settings' => array(),
 | 
			
		||||
            'weight' => 0,
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return $instance;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Prepares widget properties for the current run-time context.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $widget
 | 
			
		||||
   *   Widget specifications as found in $instance['widget'].
 | 
			
		||||
   * @param $field_type
 | 
			
		||||
   *   The field type.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   The widget properties completed for the current runtime context.
 | 
			
		||||
   */
 | 
			
		||||
  public function prepareInstanceWidget($widget, $field_type) {
 | 
			
		||||
    $field_type_info = field_info_field_types($field_type);
 | 
			
		||||
 | 
			
		||||
    // Fill in default values.
 | 
			
		||||
    $widget += array(
 | 
			
		||||
      'type' => $field_type_info['default_widget'],
 | 
			
		||||
      'settings' => array(),
 | 
			
		||||
      'weight' => 0,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    $widget_type_info = field_info_widget_types($widget['type']);
 | 
			
		||||
    // Fall back to default formatter if formatter type is not available.
 | 
			
		||||
    if (!$widget_type_info) {
 | 
			
		||||
      $widget['type'] = $field_type_info['default_widget'];
 | 
			
		||||
      $widget_type_info = field_info_widget_types($widget['type']);
 | 
			
		||||
    }
 | 
			
		||||
    $widget['module'] = $widget_type_info['module'];
 | 
			
		||||
    // Fill in default settings for the widget.
 | 
			
		||||
    $widget['settings'] += field_info_widget_settings($widget['type']);
 | 
			
		||||
 | 
			
		||||
    return $widget;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Adapts display specifications to the current run-time context.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $display
 | 
			
		||||
   *   Display specifications as found in $instance['display']['a_view_mode'].
 | 
			
		||||
   * @param $field_type
 | 
			
		||||
   *   The field type.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   The display properties completed for the current runtime context.
 | 
			
		||||
   */
 | 
			
		||||
  public function prepareInstanceDisplay($display, $field_type) {
 | 
			
		||||
    $field_type_info = field_info_field_types($field_type);
 | 
			
		||||
 | 
			
		||||
    // Fill in default values.
 | 
			
		||||
    $display += array(
 | 
			
		||||
      'label' => 'above',
 | 
			
		||||
      'type' => $field_type_info['default_formatter'],
 | 
			
		||||
      'settings' => array(),
 | 
			
		||||
      'weight' => 0,
 | 
			
		||||
    );
 | 
			
		||||
    if ($display['type'] != 'hidden') {
 | 
			
		||||
      $formatter_type_info = field_info_formatter_types($display['type']);
 | 
			
		||||
      // Fall back to default formatter if formatter type is not available.
 | 
			
		||||
      if (!$formatter_type_info) {
 | 
			
		||||
        $display['type'] = $field_type_info['default_formatter'];
 | 
			
		||||
        $formatter_type_info = field_info_formatter_types($display['type']);
 | 
			
		||||
      }
 | 
			
		||||
      $display['module'] = $formatter_type_info['module'];
 | 
			
		||||
      // Fill in default settings for the formatter.
 | 
			
		||||
      $display['settings'] += field_info_formatter_settings($display['type']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return $display;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Prepares 'extra fields' for the current run-time context.
 | 
			
		||||
   *
 | 
			
		||||
   * @param $extra_fields
 | 
			
		||||
   *   The array of extra fields, as collected in hook_field_extra_fields().
 | 
			
		||||
   * @param $entity_type
 | 
			
		||||
   *   The entity type.
 | 
			
		||||
   * @param $bundle
 | 
			
		||||
   *   The bundle name.
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *   The list of extra fields completed for the current runtime context.
 | 
			
		||||
   */
 | 
			
		||||
  public function prepareExtraFields($extra_fields, $entity_type, $bundle) {
 | 
			
		||||
    $entity_type_info = entity_get_info($entity_type);
 | 
			
		||||
    $bundle_settings = field_bundle_settings($entity_type, $bundle);
 | 
			
		||||
    $extra_fields += array('form' => array(), 'display' => array());
 | 
			
		||||
 | 
			
		||||
    $result = array();
 | 
			
		||||
    // Extra fields in forms.
 | 
			
		||||
    foreach ($extra_fields['form'] as $name => $field_data) {
 | 
			
		||||
      $settings = isset($bundle_settings['extra_fields']['form'][$name]) ? $bundle_settings['extra_fields']['form'][$name] : array();
 | 
			
		||||
      if (isset($settings['weight'])) {
 | 
			
		||||
        $field_data['weight'] = $settings['weight'];
 | 
			
		||||
      }
 | 
			
		||||
      $result['form'][$name] = $field_data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Extra fields in displayed entities.
 | 
			
		||||
    $data = $extra_fields['display'];
 | 
			
		||||
    foreach ($extra_fields['display'] as $name => $field_data) {
 | 
			
		||||
      $settings = isset($bundle_settings['extra_fields']['display'][$name]) ? $bundle_settings['extra_fields']['display'][$name] : array();
 | 
			
		||||
      $view_modes = array_merge(array('default'), array_keys($entity_type_info['view modes']));
 | 
			
		||||
      foreach ($view_modes as $view_mode) {
 | 
			
		||||
        if (isset($settings[$view_mode])) {
 | 
			
		||||
          $field_data['display'][$view_mode] = $settings[$view_mode];
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
          $field_data['display'][$view_mode] = array(
 | 
			
		||||
            'weight' => $field_data['weight'],
 | 
			
		||||
            'visible' => TRUE,
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      unset($field_data['weight']);
 | 
			
		||||
      $result['display'][$name] = $field_data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return $result;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -5,6 +5,32 @@
 | 
			
		||||
 * Field Info API, providing information about available fields and field types.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Retrieves the FieldInfo object for the current request.
 | 
			
		||||
 *
 | 
			
		||||
 * @return FieldInfo
 | 
			
		||||
 *   An instance of the FieldInfo class.
 | 
			
		||||
 */
 | 
			
		||||
function _field_info_field_cache() {
 | 
			
		||||
  // Use the advanced drupal_static() pattern, since this is called very often.
 | 
			
		||||
  static $drupal_static_fast;
 | 
			
		||||
 | 
			
		||||
  if (!isset($drupal_static_fast)) {
 | 
			
		||||
    $drupal_static_fast['field_info_field_cache'] = &drupal_static(__FUNCTION__);
 | 
			
		||||
  }
 | 
			
		||||
  $field_info = &$drupal_static_fast['field_info_field_cache'];
 | 
			
		||||
 | 
			
		||||
  if (!isset($field_info)) {
 | 
			
		||||
    // @todo The registry should save the need for an explicit include, but not
 | 
			
		||||
    // a couple upgrade tests (DisabledNodeTypeTestCase,
 | 
			
		||||
    // FilterFormatUpgradePathTestCase...) break in a strange way without it.
 | 
			
		||||
    include_once dirname(__FILE__) . '/field.info.class.inc';
 | 
			
		||||
    $field_info = new FieldInfo();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return $field_info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @defgroup field_info Field Info API
 | 
			
		||||
 * @{
 | 
			
		||||
@@ -34,7 +60,50 @@ function field_info_cache_clear() {
 | 
			
		||||
  entity_info_cache_clear();
 | 
			
		||||
 | 
			
		||||
  _field_info_collate_types(TRUE);
 | 
			
		||||
  _field_info_collate_fields(TRUE);
 | 
			
		||||
  _field_info_field_cache()->flush();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Collates all information on existing fields and instances.
 | 
			
		||||
 *
 | 
			
		||||
 * Deprecated. This function is kept to ensure backwards compatibility, but has
 | 
			
		||||
 * a serious performance impact, and should be absolutely avoided.
 | 
			
		||||
 * See http://drupal.org/node/1915646.
 | 
			
		||||
 *
 | 
			
		||||
 * Use the regular field_info_*() API functions to access the information, or
 | 
			
		||||
 * field_info_cache_clear() to clear the cached data.
 | 
			
		||||
 */
 | 
			
		||||
function _field_info_collate_fields($reset = FALSE) {
 | 
			
		||||
  if ($reset) {
 | 
			
		||||
    _field_info_field_cache()->flush();
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  $cache = _field_info_field_cache();
 | 
			
		||||
 | 
			
		||||
  // Collect fields, and build the array of IDs keyed by field_name.
 | 
			
		||||
  $fields = $cache->getFields();
 | 
			
		||||
  $field_ids = array();
 | 
			
		||||
  foreach ($fields as $id => $field) {
 | 
			
		||||
    if (!$field['deleted']) {
 | 
			
		||||
      $field_ids[$field['field_name']] = $id;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Collect extra fields for all entity types.
 | 
			
		||||
  $extra_fields = array();
 | 
			
		||||
  foreach (field_info_bundles() as $entity_type => $bundles) {
 | 
			
		||||
    foreach ($bundles as $bundle => $info) {
 | 
			
		||||
      $extra_fields[$entity_type][$bundle] = $cache->getBundleExtraFields($entity_type, $bundle);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return array(
 | 
			
		||||
    'fields' => $fields,
 | 
			
		||||
    'field_ids' => $field_ids,
 | 
			
		||||
    'instances' => $cache->getInstances(),
 | 
			
		||||
    'extra_fields' => $extra_fields,
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -161,282 +230,69 @@ function _field_info_collate_types($reset = FALSE) {
 | 
			
		||||
  return $info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Collates all information on existing fields and instances.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $reset
 | 
			
		||||
 *   If TRUE, clear the cache. The information will be rebuilt from the
 | 
			
		||||
 *   database next time it is needed. Defaults to FALSE.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   If $reset is TRUE, nothing.
 | 
			
		||||
 *   If $reset is FALSE, an array containing the following elements:
 | 
			
		||||
 *   - fields: Array of existing fields, keyed by field ID. This element
 | 
			
		||||
 *     lists deleted and non-deleted fields, but not inactive ones.
 | 
			
		||||
 *     Each field has an additional element, 'bundles', which is an array
 | 
			
		||||
 *     of all non-deleted instances of that field.
 | 
			
		||||
 *   - field_ids: Array of field IDs, keyed by field name. This element
 | 
			
		||||
 *     only lists non-deleted, active fields.
 | 
			
		||||
 *   - instances: Array of existing instances, keyed by entity type, bundle
 | 
			
		||||
 *     name and field name. This element only lists non-deleted instances
 | 
			
		||||
 *     whose field is active.
 | 
			
		||||
 */
 | 
			
		||||
function _field_info_collate_fields($reset = FALSE) {
 | 
			
		||||
  static $info;
 | 
			
		||||
 | 
			
		||||
  if ($reset) {
 | 
			
		||||
    $info = NULL;
 | 
			
		||||
    cache_clear_all('field_info_fields', 'cache_field');
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!isset($info)) {
 | 
			
		||||
    if ($cached = cache_get('field_info_fields', 'cache_field')) {
 | 
			
		||||
      $info = $cached->data;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      $definitions = array(
 | 
			
		||||
        'field_ids' => field_read_fields(array(), array('include_deleted' => 1)),
 | 
			
		||||
        'instances' => field_read_instances(),
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      // Populate 'fields' with all fields, keyed by ID.
 | 
			
		||||
      $info['fields'] = array();
 | 
			
		||||
      foreach ($definitions['field_ids'] as $key => $field) {
 | 
			
		||||
        $info['fields'][$key] = $definitions['field_ids'][$key] = _field_info_prepare_field($field);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Build an array of field IDs for non-deleted fields, keyed by name.
 | 
			
		||||
      $info['field_ids'] = array();
 | 
			
		||||
      foreach ($info['fields'] as $key => $field) {
 | 
			
		||||
        if (!$field['deleted']) {
 | 
			
		||||
          $info['field_ids'][$field['field_name']] = $key;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Populate 'instances'. Only non-deleted instances are considered.
 | 
			
		||||
      $info['instances'] = array();
 | 
			
		||||
      foreach (field_info_bundles() as $entity_type => $bundles) {
 | 
			
		||||
        foreach ($bundles as $bundle => $bundle_info) {
 | 
			
		||||
          $info['instances'][$entity_type][$bundle] = array();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      foreach ($definitions['instances'] as $instance) {
 | 
			
		||||
        $field = $info['fields'][$instance['field_id']];
 | 
			
		||||
        $instance = _field_info_prepare_instance($instance, $field);
 | 
			
		||||
        $info['instances'][$instance['entity_type']][$instance['bundle']][$instance['field_name']] = $instance;
 | 
			
		||||
        // Enrich field definitions with the list of bundles where they have
 | 
			
		||||
        // instances. NOTE: Deleted fields in $info['field_ids'] are not
 | 
			
		||||
        // enriched because all of their instances are deleted, too, and
 | 
			
		||||
        // are thus not in $definitions['instances'].
 | 
			
		||||
        $info['fields'][$instance['field_id']]['bundles'][$instance['entity_type']][] = $instance['bundle'];
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Populate 'extra_fields'.
 | 
			
		||||
      $extra = module_invoke_all('field_extra_fields');
 | 
			
		||||
      drupal_alter('field_extra_fields', $extra);
 | 
			
		||||
      // Merge in saved settings.
 | 
			
		||||
      foreach ($extra as $entity_type => $bundles) {
 | 
			
		||||
        foreach ($bundles as $bundle => $extra_fields) {
 | 
			
		||||
          $extra_fields = _field_info_prepare_extra_fields($extra_fields, $entity_type, $bundle);
 | 
			
		||||
          $info['extra_fields'][$entity_type][$bundle] = $extra_fields;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      cache_set('field_info_fields', $info, 'cache_field');
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return $info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Prepares a field definition for the current run-time context.
 | 
			
		||||
 *
 | 
			
		||||
 * Since the field was last saved or updated, new field settings can be
 | 
			
		||||
 * expected.
 | 
			
		||||
 * The functionality has moved to the FieldInfo class. This function is kept as
 | 
			
		||||
 * a backwards-compatibility layer. See http://drupal.org/node/1915646.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $field
 | 
			
		||||
 *   The raw field structure as read from the database.
 | 
			
		||||
 * @see FieldInfo::prepareField()
 | 
			
		||||
 */
 | 
			
		||||
function _field_info_prepare_field($field) {
 | 
			
		||||
  // Make sure all expected field settings are present.
 | 
			
		||||
  $field['settings'] += field_info_field_settings($field['type']);
 | 
			
		||||
  $field['storage']['settings'] += field_info_storage_settings($field['storage']['type']);
 | 
			
		||||
 | 
			
		||||
  // Add storage details.
 | 
			
		||||
  $details = (array) module_invoke($field['storage']['module'], 'field_storage_details', $field);
 | 
			
		||||
  drupal_alter('field_storage_details', $details, $field, $instance);
 | 
			
		||||
  $field['storage']['details'] = $details;
 | 
			
		||||
 | 
			
		||||
  // Initialize the 'bundles' list.
 | 
			
		||||
  $field['bundles'] = array();
 | 
			
		||||
 | 
			
		||||
  return $field;
 | 
			
		||||
  $cache = _field_info_field_cache();
 | 
			
		||||
  return $cache->prepareField($field);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Prepares an instance definition for the current run-time context.
 | 
			
		||||
 *
 | 
			
		||||
 * Since the instance was last saved or updated, a number of things might have
 | 
			
		||||
 * changed: widgets or formatters disabled, new settings expected, new view
 | 
			
		||||
 * modes added...
 | 
			
		||||
 * The functionality has moved to the FieldInfo class. This function is kept as
 | 
			
		||||
 * a backwards-compatibility layer. See http://drupal.org/node/1915646.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $instance
 | 
			
		||||
 *   The raw instance structure as read from the database.
 | 
			
		||||
 * @param $field
 | 
			
		||||
 *   The field structure for the instance.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   Field instance array.
 | 
			
		||||
 * @see FieldInfo::prepareInstance()
 | 
			
		||||
 */
 | 
			
		||||
function _field_info_prepare_instance($instance, $field) {
 | 
			
		||||
  // Make sure all expected instance settings are present.
 | 
			
		||||
  $instance['settings'] += field_info_instance_settings($field['type']);
 | 
			
		||||
 | 
			
		||||
  // Set a default value for the instance.
 | 
			
		||||
  if (field_behaviors_widget('default value', $instance) == FIELD_BEHAVIOR_DEFAULT && !isset($instance['default_value'])) {
 | 
			
		||||
    $instance['default_value'] = NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  $instance['widget'] = _field_info_prepare_instance_widget($field, $instance['widget']);
 | 
			
		||||
 | 
			
		||||
  foreach ($instance['display'] as $view_mode => $display) {
 | 
			
		||||
    $instance['display'][$view_mode] = _field_info_prepare_instance_display($field, $display);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Fallback to 'hidden' for view modes configured to use custom display
 | 
			
		||||
  // settings, and for which the instance has no explicit settings.
 | 
			
		||||
  $entity_info = entity_get_info($instance['entity_type']);
 | 
			
		||||
  $view_modes = array_merge(array('default'), array_keys($entity_info['view modes']));
 | 
			
		||||
  $view_mode_settings = field_view_mode_settings($instance['entity_type'], $instance['bundle']);
 | 
			
		||||
  foreach ($view_modes as $view_mode) {
 | 
			
		||||
    if ($view_mode == 'default' || !empty($view_mode_settings[$view_mode]['custom_settings'])) {
 | 
			
		||||
      if (!isset($instance['display'][$view_mode])) {
 | 
			
		||||
        $instance['display'][$view_mode] = array(
 | 
			
		||||
          'type' => 'hidden',
 | 
			
		||||
          'label' => 'above',
 | 
			
		||||
          'settings' => array(),
 | 
			
		||||
          'weight' => 0,
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return $instance;
 | 
			
		||||
  $cache = _field_info_field_cache();
 | 
			
		||||
  return $cache->prepareInstance($instance, $field['type']);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Adapts display specifications to the current run-time context.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $field
 | 
			
		||||
 *   The field structure for the instance.
 | 
			
		||||
 * @param $display
 | 
			
		||||
 *   Display specifications as found in
 | 
			
		||||
 *   $instance['display']['some_view_mode'].
 | 
			
		||||
 * The functionality has moved to the FieldInfo class. This function is kept as
 | 
			
		||||
 * a backwards-compatibility layer. See http://drupal.org/node/1915646.
 | 
			
		||||
 *
 | 
			
		||||
 * @see FieldInfo::prepareInstanceDisplay()
 | 
			
		||||
 */
 | 
			
		||||
function _field_info_prepare_instance_display($field, $display) {
 | 
			
		||||
  $field_type = field_info_field_types($field['type']);
 | 
			
		||||
 | 
			
		||||
  // Fill in default values.
 | 
			
		||||
  $display += array(
 | 
			
		||||
    'label' => 'above',
 | 
			
		||||
    'type' => $field_type['default_formatter'],
 | 
			
		||||
    'settings' => array(),
 | 
			
		||||
    'weight' => 0,
 | 
			
		||||
  );
 | 
			
		||||
  if ($display['type'] != 'hidden') {
 | 
			
		||||
    $formatter_type = field_info_formatter_types($display['type']);
 | 
			
		||||
    // Fallback to default formatter if formatter type is not available.
 | 
			
		||||
    if (!$formatter_type) {
 | 
			
		||||
      $display['type'] = $field_type['default_formatter'];
 | 
			
		||||
      $formatter_type = field_info_formatter_types($display['type']);
 | 
			
		||||
    }
 | 
			
		||||
    $display['module'] = $formatter_type['module'];
 | 
			
		||||
    // Fill in default settings for the formatter.
 | 
			
		||||
    $display['settings'] += field_info_formatter_settings($display['type']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return $display;
 | 
			
		||||
  $cache = _field_info_field_cache();
 | 
			
		||||
  return $cache->prepareInstanceDisplay($display, $field['type']);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Prepares widget specifications for the current run-time context.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $field
 | 
			
		||||
 *   The field structure for the instance.
 | 
			
		||||
 * @param $widget
 | 
			
		||||
 *   Widget specifications as found in $instance['widget'].
 | 
			
		||||
 * The functionality has moved to the FieldInfo class. This function is kept as
 | 
			
		||||
 * a backwards-compatibility layer. See http://drupal.org/node/1915646.
 | 
			
		||||
 *
 | 
			
		||||
 * @see FieldInfo::prepareInstanceWidget()
 | 
			
		||||
 */
 | 
			
		||||
function _field_info_prepare_instance_widget($field, $widget) {
 | 
			
		||||
  $field_type = field_info_field_types($field['type']);
 | 
			
		||||
 | 
			
		||||
  // Fill in default values.
 | 
			
		||||
  $widget += array(
 | 
			
		||||
    'type' => $field_type['default_widget'],
 | 
			
		||||
    'settings' => array(),
 | 
			
		||||
    'weight' => 0,
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  $widget_type = field_info_widget_types($widget['type']);
 | 
			
		||||
  // Fallback to default formatter if formatter type is not available.
 | 
			
		||||
  if (!$widget_type) {
 | 
			
		||||
    $widget['type'] = $field_type['default_widget'];
 | 
			
		||||
    $widget_type = field_info_widget_types($widget['type']);
 | 
			
		||||
  }
 | 
			
		||||
  $widget['module'] = $widget_type['module'];
 | 
			
		||||
  // Fill in default settings for the widget.
 | 
			
		||||
  $widget['settings'] += field_info_widget_settings($widget['type']);
 | 
			
		||||
 | 
			
		||||
  return $widget;
 | 
			
		||||
  $cache = _field_info_field_cache();
 | 
			
		||||
  return $cache->prepareInstanceWidget($widget, $field['type']);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Prepares 'extra fields' for the current run-time context.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $extra_fields
 | 
			
		||||
 *   The array of extra fields, as collected in hook_field_extra_fields().
 | 
			
		||||
 * @param $entity_type
 | 
			
		||||
 *   The entity type.
 | 
			
		||||
 * @param $bundle
 | 
			
		||||
 *   The bundle name.
 | 
			
		||||
 * The functionality has moved to the FieldInfo class. This function is kept as
 | 
			
		||||
 * a backwards-compatibility layer. See http://drupal.org/node/1915646.
 | 
			
		||||
 *
 | 
			
		||||
 * @see FieldInfo::prepareExtraFields()
 | 
			
		||||
 */
 | 
			
		||||
function _field_info_prepare_extra_fields($extra_fields, $entity_type, $bundle) {
 | 
			
		||||
  $entity_type_info = entity_get_info($entity_type);
 | 
			
		||||
  $bundle_settings = field_bundle_settings($entity_type, $bundle);
 | 
			
		||||
  $extra_fields += array('form' => array(), 'display' => array());
 | 
			
		||||
 | 
			
		||||
  $result = array();
 | 
			
		||||
  // Extra fields in forms.
 | 
			
		||||
  foreach ($extra_fields['form'] as $name => $field_data) {
 | 
			
		||||
    $settings = isset($bundle_settings['extra_fields']['form'][$name]) ? $bundle_settings['extra_fields']['form'][$name] : array();
 | 
			
		||||
    if (isset($settings['weight'])) {
 | 
			
		||||
      $field_data['weight'] = $settings['weight'];
 | 
			
		||||
    }
 | 
			
		||||
    $result['form'][$name] = $field_data;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Extra fields in displayed entities.
 | 
			
		||||
  $data = $extra_fields['display'];
 | 
			
		||||
  foreach ($extra_fields['display'] as $name => $field_data) {
 | 
			
		||||
    $settings = isset($bundle_settings['extra_fields']['display'][$name]) ? $bundle_settings['extra_fields']['display'][$name] : array();
 | 
			
		||||
    $view_modes = array_merge(array('default'), array_keys($entity_type_info['view modes']));
 | 
			
		||||
    foreach ($view_modes as $view_mode) {
 | 
			
		||||
      if (isset($settings[$view_mode])) {
 | 
			
		||||
        $field_data['display'][$view_mode] = $settings[$view_mode];
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        $field_data['display'][$view_mode] = array(
 | 
			
		||||
          'weight' => $field_data['weight'],
 | 
			
		||||
          'visible' => TRUE,
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    unset($field_data['weight']);
 | 
			
		||||
    $result['display'][$name] = $field_data;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return $result;
 | 
			
		||||
  $cache = _field_info_field_cache();
 | 
			
		||||
  return $cache->prepareExtraFields($extra_fields, $entity_type, $bundle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -583,22 +439,51 @@ function field_info_bundles($entity_type = NULL) {
 | 
			
		||||
  return $bundles;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns a lightweight map of fields across bundles.
 | 
			
		||||
 *
 | 
			
		||||
 * The function only returns active, non deleted fields.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   An array keyed by field name. Each value is an array with two entries:
 | 
			
		||||
 *   - type: The field type.
 | 
			
		||||
 *   - bundles: The bundles in which the field appears, as an array with entity
 | 
			
		||||
 *     types as keys and the array of bundle names as values.
 | 
			
		||||
 */
 | 
			
		||||
function field_info_field_map() {
 | 
			
		||||
  $cache = _field_info_field_cache();
 | 
			
		||||
  return $cache->getFieldMap();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns all field definitions.
 | 
			
		||||
 *
 | 
			
		||||
 * Use of this function should be avoided when possible, since it loads and
 | 
			
		||||
 * statically caches a potentially large array of information. Use
 | 
			
		||||
 * field_info_field_map() instead.
 | 
			
		||||
 *
 | 
			
		||||
 * When iterating over the fields present in a given bundle after a call to
 | 
			
		||||
 * field_info_instances($entity_type, $bundle), it is recommended to use
 | 
			
		||||
 * field_info_field() on each individual field instead.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   An array of field definitions, keyed by field name. Each field has an
 | 
			
		||||
 *   additional property, 'bundles', which is an array of all the bundles to
 | 
			
		||||
 *   which this field belongs keyed by entity type.
 | 
			
		||||
 *
 | 
			
		||||
 * @see field_info_field_map()
 | 
			
		||||
 */
 | 
			
		||||
function field_info_fields() {
 | 
			
		||||
  $cache = _field_info_field_cache();
 | 
			
		||||
  $info = $cache->getFields();
 | 
			
		||||
 | 
			
		||||
  $fields = array();
 | 
			
		||||
  $info = _field_info_collate_fields();
 | 
			
		||||
  foreach ($info['fields'] as $key => $field) {
 | 
			
		||||
  foreach ($info as $key => $field) {
 | 
			
		||||
    if (!$field['deleted']) {
 | 
			
		||||
      $fields[$field['field_name']] = $field;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return $fields;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -620,10 +505,8 @@ function field_info_fields() {
 | 
			
		||||
 * @see field_info_field_by_id()
 | 
			
		||||
 */
 | 
			
		||||
function field_info_field($field_name) {
 | 
			
		||||
  $info = _field_info_collate_fields();
 | 
			
		||||
  if (isset($info['field_ids'][$field_name])) {
 | 
			
		||||
    return $info['fields'][$info['field_ids'][$field_name]];
 | 
			
		||||
  }
 | 
			
		||||
  $cache = _field_info_field_cache();
 | 
			
		||||
  return $cache->getField($field_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -641,17 +524,19 @@ function field_info_field($field_name) {
 | 
			
		||||
 * @see field_info_field()
 | 
			
		||||
 */
 | 
			
		||||
function field_info_field_by_id($field_id) {
 | 
			
		||||
  $info = _field_info_collate_fields();
 | 
			
		||||
  if (isset($info['fields'][$field_id])) {
 | 
			
		||||
    return $info['fields'][$field_id];
 | 
			
		||||
  }
 | 
			
		||||
  $cache = _field_info_field_cache();
 | 
			
		||||
  return $cache->getFieldById($field_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns the same data as field_info_field_by_id() for every field.
 | 
			
		||||
 *
 | 
			
		||||
 * This function is typically used when handling all fields of some entities
 | 
			
		||||
 * to avoid thousands of calls to field_info_field_by_id().
 | 
			
		||||
 * Use of this function should be avoided when possible, since it loads and
 | 
			
		||||
 * statically caches a potentially large array of information.
 | 
			
		||||
 *
 | 
			
		||||
 * When iterating over the fields present in a given bundle after a call to
 | 
			
		||||
 * field_info_instances($entity_type, $bundle), it is recommended to use
 | 
			
		||||
 * field_info_field() on each individual field instead.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   An array, each key is a field ID and the values are field arrays as
 | 
			
		||||
@@ -662,41 +547,57 @@ function field_info_field_by_id($field_id) {
 | 
			
		||||
 * @see field_info_field_by_id()
 | 
			
		||||
 */
 | 
			
		||||
function field_info_field_by_ids() {
 | 
			
		||||
  $info = _field_info_collate_fields();
 | 
			
		||||
  return $info['fields'];
 | 
			
		||||
  $cache = _field_info_field_cache();
 | 
			
		||||
  return $cache->getFields();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Retrieves information about field instances.
 | 
			
		||||
 *
 | 
			
		||||
 * Use of this function to retrieve instances across separate bundles (i.e.
 | 
			
		||||
 * when the $bundle parameter is NULL) should be avoided when possible, since
 | 
			
		||||
 * it loads and statically caches a potentially large array of information. Use
 | 
			
		||||
 * field_info_field_map() instead.
 | 
			
		||||
 *
 | 
			
		||||
 * When retrieving the instances of a specific bundle (i.e. when both
 | 
			
		||||
 * $entity_type and $bundle_name are provided), the function also populates a
 | 
			
		||||
 * static cache with the corresponding field definitions, allowing fast
 | 
			
		||||
 * retrieval of field_info_field() later in the request.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $entity_type
 | 
			
		||||
 *   The entity type for which to return instances.
 | 
			
		||||
 *   (optional) The entity type for which to return instances.
 | 
			
		||||
 * @param $bundle_name
 | 
			
		||||
 *   The bundle name for which to return instances.
 | 
			
		||||
 *   (optional) The bundle name for which to return instances. If $entity_type
 | 
			
		||||
 *   is NULL, the $bundle_name parameter is ignored.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   If $entity_type is not set, return all instances keyed by entity type and
 | 
			
		||||
 *   bundle name. If $entity_type is set, return all instances for that entity
 | 
			
		||||
 *   type, keyed by bundle name. If $entity_type and $bundle_name are set, return
 | 
			
		||||
 *   all instances for that bundle.
 | 
			
		||||
 *
 | 
			
		||||
 * @see field_info_field_map()
 | 
			
		||||
 */
 | 
			
		||||
function field_info_instances($entity_type = NULL, $bundle_name = NULL) {
 | 
			
		||||
  $info = _field_info_collate_fields();
 | 
			
		||||
  $cache = _field_info_field_cache();
 | 
			
		||||
 | 
			
		||||
  if (isset($entity_type) && isset($bundle_name)) {
 | 
			
		||||
    return isset($info['instances'][$entity_type][$bundle_name]) ? $info['instances'][$entity_type][$bundle_name] : array();
 | 
			
		||||
  if (!isset($entity_type)) {
 | 
			
		||||
    return $cache->getInstances();
 | 
			
		||||
  }
 | 
			
		||||
  elseif (isset($entity_type)) {
 | 
			
		||||
    return isset($info['instances'][$entity_type]) ? $info['instances'][$entity_type] : array();
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    return $info['instances'];
 | 
			
		||||
  if (!isset($bundle_name)) {
 | 
			
		||||
    return $cache->getInstances($entity_type);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return $cache->getBundleInstances($entity_type, $bundle_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns an array of instance data for a specific field and bundle.
 | 
			
		||||
 *
 | 
			
		||||
 * The function populates a static cache with all fields and instances used in
 | 
			
		||||
 * the bundle, allowing fast retrieval of field_info_field() or
 | 
			
		||||
 * field_info_instance() later in the request.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $entity_type
 | 
			
		||||
 *   The entity type for the instance.
 | 
			
		||||
 * @param $field_name
 | 
			
		||||
@@ -709,9 +610,10 @@ function field_info_instances($entity_type = NULL, $bundle_name = NULL) {
 | 
			
		||||
 *   NULL if the instance does not exist.
 | 
			
		||||
 */
 | 
			
		||||
function field_info_instance($entity_type, $field_name, $bundle_name) {
 | 
			
		||||
  $info = _field_info_collate_fields();
 | 
			
		||||
  if (isset($info['instances'][$entity_type][$bundle_name][$field_name])) {
 | 
			
		||||
    return $info['instances'][$entity_type][$bundle_name][$field_name];
 | 
			
		||||
  $cache = _field_info_field_cache();
 | 
			
		||||
  $info = $cache->getBundleInstances($entity_type, $bundle_name);
 | 
			
		||||
  if (isset($info[$field_name])) {
 | 
			
		||||
    return $info[$field_name];
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -769,11 +671,10 @@ function field_info_instance($entity_type, $field_name, $bundle_name) {
 | 
			
		||||
 *   The array of pseudo-field elements in the bundle.
 | 
			
		||||
 */
 | 
			
		||||
function field_info_extra_fields($entity_type, $bundle, $context) {
 | 
			
		||||
  $info = _field_info_collate_fields();
 | 
			
		||||
  if (isset($info['extra_fields'][$entity_type][$bundle][$context])) {
 | 
			
		||||
    return $info['extra_fields'][$entity_type][$bundle][$context];
 | 
			
		||||
  }
 | 
			
		||||
  return array();
 | 
			
		||||
  $cache = _field_info_field_cache();
 | 
			
		||||
  $info = $cache->getBundleExtraFields($entity_type, $bundle);
 | 
			
		||||
 | 
			
		||||
  return isset($info[$context]) ? $info[$context] : array();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -459,6 +459,13 @@ function field_update_7002() {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add the FieldInfo class to the class registry.
 | 
			
		||||
 */
 | 
			
		||||
function field_update_7003() {
 | 
			
		||||
  // Empty update to force a rebuild of the registry.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @} End of "addtogroup updates-7.x-extra".
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -873,7 +873,8 @@ function field_view_field($entity_type, $entity, $field_name, $display = array()
 | 
			
		||||
  if ($field = field_info_field($field_name)) {
 | 
			
		||||
    if (is_array($display)) {
 | 
			
		||||
      // When using custom display settings, fill in default values.
 | 
			
		||||
      $display = _field_info_prepare_instance_display($field, $display);
 | 
			
		||||
      $cache = _field_info_field_cache();
 | 
			
		||||
      $display = $cache->prepareInstanceDisplay($display, $field["type"]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Hook invocations are done through the _field_invoke() functions in
 | 
			
		||||
@@ -1197,7 +1198,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);
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,8 @@ dependencies[] = field
 | 
			
		||||
files[] = field_sql_storage.test
 | 
			
		||||
required = TRUE
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -324,11 +324,14 @@ function field_sql_storage_field_storage_delete_field($field) {
 | 
			
		||||
 * Implements hook_field_storage_load().
 | 
			
		||||
 */
 | 
			
		||||
function field_sql_storage_field_storage_load($entity_type, $entities, $age, $fields, $options) {
 | 
			
		||||
  $field_info = field_info_field_by_ids();
 | 
			
		||||
  $load_current = $age == FIELD_LOAD_CURRENT;
 | 
			
		||||
 | 
			
		||||
  foreach ($fields as $field_id => $ids) {
 | 
			
		||||
    $field = $field_info[$field_id];
 | 
			
		||||
    // By the time this hook runs, the relevant field definitions have been
 | 
			
		||||
    // populated and cached in FieldInfo, so calling field_info_field_by_id()
 | 
			
		||||
    // on each field individually is more efficient than loading all fields in
 | 
			
		||||
    // memory upfront with field_info_field_by_ids().
 | 
			
		||||
    $field = field_info_field_by_id($field_id);
 | 
			
		||||
    $field_name = $field['field_name'];
 | 
			
		||||
    $table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,8 @@ dependencies[] = field
 | 
			
		||||
dependencies[] = options
 | 
			
		||||
files[] = tests/list.test
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,8 @@ package = Testing
 | 
			
		||||
version = VERSION
 | 
			
		||||
hidden = TRUE
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,8 @@ core = 7.x
 | 
			
		||||
dependencies[] = field
 | 
			
		||||
files[] = number.test
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,8 @@ core = 7.x
 | 
			
		||||
dependencies[] = field
 | 
			
		||||
files[] = options.test
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,8 @@ dependencies[] = field
 | 
			
		||||
files[] = text.test
 | 
			
		||||
required = TRUE
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -85,12 +85,28 @@ class FieldAttachTestCase extends FieldTestCase {
 | 
			
		||||
    }
 | 
			
		||||
    parent::setUp($modules);
 | 
			
		||||
 | 
			
		||||
    $this->field_name = drupal_strtolower($this->randomName() . '_field_name');
 | 
			
		||||
    $this->field = array('field_name' => $this->field_name, 'type' => 'test_field', 'cardinality' => 4);
 | 
			
		||||
    $this->field = field_create_field($this->field);
 | 
			
		||||
    $this->field_id = $this->field['id'];
 | 
			
		||||
    $this->instance = array(
 | 
			
		||||
      'field_name' => $this->field_name,
 | 
			
		||||
    $this->createFieldWithInstance();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a field and an instance of it.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $suffix
 | 
			
		||||
   *   (optional) A string that should only contain characters that are valid in
 | 
			
		||||
   *   PHP variable names as well.
 | 
			
		||||
   */
 | 
			
		||||
  function createFieldWithInstance($suffix = '') {
 | 
			
		||||
    $field_name = 'field_name' . $suffix;
 | 
			
		||||
    $field = 'field' . $suffix;
 | 
			
		||||
    $field_id = 'field_id' . $suffix;
 | 
			
		||||
    $instance = 'instance' . $suffix;
 | 
			
		||||
 | 
			
		||||
    $this->$field_name = drupal_strtolower($this->randomName() . '_field_name' . $suffix);
 | 
			
		||||
    $this->$field = array('field_name' => $this->$field_name, 'type' => 'test_field', 'cardinality' => 4);
 | 
			
		||||
    $this->$field = field_create_field($this->$field);
 | 
			
		||||
    $this->$field_id = $this->{$field}['id'];
 | 
			
		||||
    $this->$instance = array(
 | 
			
		||||
      'field_name' => $this->$field_name,
 | 
			
		||||
      'entity_type' => 'test_entity',
 | 
			
		||||
      'bundle' => 'test_bundle',
 | 
			
		||||
      'label' => $this->randomName() . '_label',
 | 
			
		||||
@@ -107,7 +123,7 @@ class FieldAttachTestCase extends FieldTestCase {
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
    );
 | 
			
		||||
    field_create_instance($this->instance);
 | 
			
		||||
    field_create_instance($this->$instance);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -641,13 +657,18 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
 | 
			
		||||
   * Test field_attach_view() and field_attach_prepare_view().
 | 
			
		||||
   */
 | 
			
		||||
  function testFieldAttachView() {
 | 
			
		||||
    $this->createFieldWithInstance('_2');
 | 
			
		||||
 | 
			
		||||
    $entity_type = 'test_entity';
 | 
			
		||||
    $entity_init = field_test_create_stub_entity();
 | 
			
		||||
    $langcode = LANGUAGE_NONE;
 | 
			
		||||
    $options = array('field_name' => $this->field_name_2);
 | 
			
		||||
 | 
			
		||||
    // Populate values to be displayed.
 | 
			
		||||
    $values = $this->_generateTestFieldValues($this->field['cardinality']);
 | 
			
		||||
    $entity_init->{$this->field_name}[$langcode] = $values;
 | 
			
		||||
    $values_2 = $this->_generateTestFieldValues($this->field_2['cardinality']);
 | 
			
		||||
    $entity_init->{$this->field_name_2}[$langcode] = $values_2;
 | 
			
		||||
 | 
			
		||||
    // Simple formatter, label displayed.
 | 
			
		||||
    $entity = clone($entity_init);
 | 
			
		||||
@@ -662,15 +683,47 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
    field_update_instance($this->instance);
 | 
			
		||||
    $formatter_setting_2 = $this->randomName();
 | 
			
		||||
    $this->instance_2['display'] = array(
 | 
			
		||||
      'full' => array(
 | 
			
		||||
        'label' => 'above',
 | 
			
		||||
        'type' => 'field_test_default',
 | 
			
		||||
        'settings' => array(
 | 
			
		||||
          'test_formatter_setting' => $formatter_setting_2,
 | 
			
		||||
        )
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
    field_update_instance($this->instance_2);
 | 
			
		||||
    // View all fields.
 | 
			
		||||
    field_attach_prepare_view($entity_type, array($entity->ftid => $entity), 'full');
 | 
			
		||||
    $entity->content = field_attach_view($entity_type, $entity, 'full');
 | 
			
		||||
    $output = drupal_render($entity->content);
 | 
			
		||||
    $this->content = $output;
 | 
			
		||||
    $this->assertRaw($this->instance['label'], "Label is displayed.");
 | 
			
		||||
    $this->assertRaw($this->instance['label'], "First field's label is displayed.");
 | 
			
		||||
    foreach ($values as $delta => $value) {
 | 
			
		||||
      $this->content = $output;
 | 
			
		||||
      $this->assertRaw("$formatter_setting|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
 | 
			
		||||
    }
 | 
			
		||||
    $this->assertRaw($this->instance_2['label'], "Second field's label is displayed.");
 | 
			
		||||
    foreach ($values_2 as $delta => $value) {
 | 
			
		||||
      $this->content = $output;
 | 
			
		||||
      $this->assertRaw("$formatter_setting_2|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
 | 
			
		||||
    }
 | 
			
		||||
    // View single field (the second field).
 | 
			
		||||
    field_attach_prepare_view($entity_type, array($entity->ftid => $entity), 'full', $langcode, $options);
 | 
			
		||||
    $entity->content = field_attach_view($entity_type, $entity, 'full', $langcode, $options);
 | 
			
		||||
    $output = drupal_render($entity->content);
 | 
			
		||||
    $this->content = $output;
 | 
			
		||||
    $this->assertNoRaw($this->instance['label'], "First field's label is not displayed.");
 | 
			
		||||
    foreach ($values as $delta => $value) {
 | 
			
		||||
      $this->content = $output;
 | 
			
		||||
      $this->assertNoRaw("$formatter_setting|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
 | 
			
		||||
    }
 | 
			
		||||
    $this->assertRaw($this->instance_2['label'], "Second field's label is displayed.");
 | 
			
		||||
    foreach ($values_2 as $delta => $value) {
 | 
			
		||||
      $this->content = $output;
 | 
			
		||||
      $this->assertRaw("$formatter_setting_2|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Label hidden.
 | 
			
		||||
    $entity = clone($entity_init);
 | 
			
		||||
@@ -697,7 +750,7 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
 | 
			
		||||
    $this->content = $output;
 | 
			
		||||
    $this->assertNoRaw($this->instance['label'], "Hidden field: label is not displayed.");
 | 
			
		||||
    foreach ($values as $delta => $value) {
 | 
			
		||||
      $this->assertNoRaw($value['value'], "Hidden field: value $delta is not displayed.");
 | 
			
		||||
      $this->assertNoRaw("$formatter_setting|{$value['value']}", "Hidden field: value $delta is not displayed.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Multiple formatter.
 | 
			
		||||
@@ -907,11 +960,13 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
 | 
			
		||||
   * hook_field_validate.
 | 
			
		||||
   */
 | 
			
		||||
  function testFieldAttachValidate() {
 | 
			
		||||
    $this->createFieldWithInstance('_2');
 | 
			
		||||
 | 
			
		||||
    $entity_type = 'test_entity';
 | 
			
		||||
    $entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
 | 
			
		||||
    $langcode = LANGUAGE_NONE;
 | 
			
		||||
 | 
			
		||||
    // Set up values to generate errors
 | 
			
		||||
    // Set up all but one values of the first field to generate errors.
 | 
			
		||||
    $values = array();
 | 
			
		||||
    for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
 | 
			
		||||
      $values[$delta]['value'] = -1;
 | 
			
		||||
@@ -920,6 +975,14 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
 | 
			
		||||
    $values[1]['value'] = 1;
 | 
			
		||||
    $entity->{$this->field_name}[$langcode] = $values;
 | 
			
		||||
 | 
			
		||||
    // Set up all values of the second field to generate errors.
 | 
			
		||||
    $values_2 = array();
 | 
			
		||||
    for ($delta = 0; $delta < $this->field_2['cardinality']; $delta++) {
 | 
			
		||||
      $values_2[$delta]['value'] = -1;
 | 
			
		||||
    }
 | 
			
		||||
    $entity->{$this->field_name_2}[$langcode] = $values_2;
 | 
			
		||||
 | 
			
		||||
    // Validate all fields.
 | 
			
		||||
    try {
 | 
			
		||||
      field_attach_validate($entity_type, $entity);
 | 
			
		||||
    }
 | 
			
		||||
@@ -929,26 +992,57 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
 | 
			
		||||
 | 
			
		||||
    foreach ($values as $delta => $value) {
 | 
			
		||||
      if ($value['value'] != 1) {
 | 
			
		||||
        $this->assertIdentical($errors[$this->field_name][$langcode][$delta][0]['error'], 'field_test_invalid', "Error set on value $delta");
 | 
			
		||||
        $this->assertEqual(count($errors[$this->field_name][$langcode][$delta]), 1, "Only one error set on value $delta");
 | 
			
		||||
        $this->assertIdentical($errors[$this->field_name][$langcode][$delta][0]['error'], 'field_test_invalid', "Error set on first field's value $delta");
 | 
			
		||||
        $this->assertEqual(count($errors[$this->field_name][$langcode][$delta]), 1, "Only one error set on first field's value $delta");
 | 
			
		||||
        unset($errors[$this->field_name][$langcode][$delta]);
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        $this->assertFalse(isset($errors[$this->field_name][$langcode][$delta]), "No error set on value $delta");
 | 
			
		||||
        $this->assertFalse(isset($errors[$this->field_name][$langcode][$delta]), "No error set on first field's value $delta");
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    $this->assertEqual(count($errors[$this->field_name][$langcode]), 0, 'No extraneous errors set');
 | 
			
		||||
    foreach ($values_2 as $delta => $value) {
 | 
			
		||||
      $this->assertIdentical($errors[$this->field_name_2][$langcode][$delta][0]['error'], 'field_test_invalid', "Error set on second field's value $delta");
 | 
			
		||||
      $this->assertEqual(count($errors[$this->field_name_2][$langcode][$delta]), 1, "Only one error set on second field's value $delta");
 | 
			
		||||
      unset($errors[$this->field_name_2][$langcode][$delta]);
 | 
			
		||||
    }
 | 
			
		||||
    $this->assertEqual(count($errors[$this->field_name][$langcode]), 0, 'No extraneous errors set for first field');
 | 
			
		||||
    $this->assertEqual(count($errors[$this->field_name_2][$langcode]), 0, 'No extraneous errors set for second field');
 | 
			
		||||
 | 
			
		||||
    // Validate a single field.
 | 
			
		||||
    $options = array('field_name' => $this->field_name_2);
 | 
			
		||||
    try {
 | 
			
		||||
      field_attach_validate($entity_type, $entity, $options);
 | 
			
		||||
    }
 | 
			
		||||
    catch (FieldValidationException $e) {
 | 
			
		||||
      $errors = $e->errors;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    foreach ($values_2 as $delta => $value) {
 | 
			
		||||
      $this->assertIdentical($errors[$this->field_name_2][$langcode][$delta][0]['error'], 'field_test_invalid', "Error set on second field's value $delta");
 | 
			
		||||
      $this->assertEqual(count($errors[$this->field_name_2][$langcode][$delta]), 1, "Only one error set on second field's value $delta");
 | 
			
		||||
      unset($errors[$this->field_name_2][$langcode][$delta]);
 | 
			
		||||
    }
 | 
			
		||||
    $this->assertFalse(isset($errors[$this->field_name]), 'No validation errors are set for the first field, despite it having errors');
 | 
			
		||||
    $this->assertEqual(count($errors[$this->field_name_2][$langcode]), 0, 'No extraneous errors set for second field');
 | 
			
		||||
 | 
			
		||||
    // Check that cardinality is validated.
 | 
			
		||||
    $entity->{$this->field_name}[$langcode] = $this->_generateTestFieldValues($this->field['cardinality'] + 1);
 | 
			
		||||
    $entity->{$this->field_name_2}[$langcode] = $this->_generateTestFieldValues($this->field_2['cardinality'] + 1);
 | 
			
		||||
    // When validating all fields.
 | 
			
		||||
    try {
 | 
			
		||||
      field_attach_validate($entity_type, $entity);
 | 
			
		||||
    }
 | 
			
		||||
    catch (FieldValidationException $e) {
 | 
			
		||||
      $errors = $e->errors;
 | 
			
		||||
    }
 | 
			
		||||
    $this->assertEqual($errors[$this->field_name][$langcode][0][0]['error'], 'field_cardinality', t('Cardinality validation failed.'));
 | 
			
		||||
 | 
			
		||||
    $this->assertEqual($errors[$this->field_name_2][$langcode][0][0]['error'], 'field_cardinality', 'Cardinality validation failed.');
 | 
			
		||||
    // When validating a single field (the second field).
 | 
			
		||||
    try {
 | 
			
		||||
      field_attach_validate($entity_type, $entity, $options);
 | 
			
		||||
    }
 | 
			
		||||
    catch (FieldValidationException $e) {
 | 
			
		||||
      $errors = $e->errors;
 | 
			
		||||
    }
 | 
			
		||||
    $this->assertEqual($errors[$this->field_name_2][$langcode][0][0]['error'], 'field_cardinality', 'Cardinality validation failed.');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
@@ -958,34 +1052,59 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
 | 
			
		||||
   * widgets show up.
 | 
			
		||||
   */
 | 
			
		||||
  function testFieldAttachForm() {
 | 
			
		||||
    $this->createFieldWithInstance('_2');
 | 
			
		||||
 | 
			
		||||
    $entity_type = 'test_entity';
 | 
			
		||||
    $entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
 | 
			
		||||
    $langcode = LANGUAGE_NONE;
 | 
			
		||||
 | 
			
		||||
    // When generating form for all fields.
 | 
			
		||||
    $form = array();
 | 
			
		||||
    $form_state = form_state_defaults();
 | 
			
		||||
    field_attach_form($entity_type, $entity, $form, $form_state);
 | 
			
		||||
 | 
			
		||||
    $langcode = LANGUAGE_NONE;
 | 
			
		||||
    $this->assertEqual($form[$this->field_name][$langcode]['#title'], $this->instance['label'], "Form title is {$this->instance['label']}");
 | 
			
		||||
    $this->assertEqual($form[$this->field_name][$langcode]['#title'], $this->instance['label'], "First field's form title is {$this->instance['label']}");
 | 
			
		||||
    $this->assertEqual($form[$this->field_name_2][$langcode]['#title'], $this->instance_2['label'], "Second field's form title is {$this->instance_2['label']}");
 | 
			
		||||
    for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
 | 
			
		||||
      // field_test_widget uses 'textfield'
 | 
			
		||||
      $this->assertEqual($form[$this->field_name][$langcode][$delta]['value']['#type'], 'textfield', "Form delta $delta widget is textfield");
 | 
			
		||||
    }
 | 
			
		||||
        $this->assertEqual($form[$this->field_name][$langcode][$delta]['value']['#type'], 'textfield', "First field's form delta $delta widget is textfield");
 | 
			
		||||
      }
 | 
			
		||||
      for ($delta = 0; $delta < $this->field_2['cardinality']; $delta++) {
 | 
			
		||||
        // field_test_widget uses 'textfield'
 | 
			
		||||
        $this->assertEqual($form[$this->field_name_2][$langcode][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield");
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // When generating form for a single field (the second field).
 | 
			
		||||
      $options = array('field_name' => $this->field_name_2);
 | 
			
		||||
      $form = array();
 | 
			
		||||
      $form_state = form_state_defaults();
 | 
			
		||||
      field_attach_form($entity_type, $entity, $form, $form_state, NULL, $options);
 | 
			
		||||
 | 
			
		||||
      $this->assertFalse(isset($form[$this->field_name]), 'The first field does not exist in the form');
 | 
			
		||||
      $this->assertEqual($form[$this->field_name_2][$langcode]['#title'], $this->instance_2['label'], "Second field's form title is {$this->instance_2['label']}");
 | 
			
		||||
      for ($delta = 0; $delta < $this->field_2['cardinality']; $delta++) {
 | 
			
		||||
        // field_test_widget uses 'textfield'
 | 
			
		||||
        $this->assertEqual($form[$this->field_name_2][$langcode][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield");
 | 
			
		||||
      }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test field_attach_submit().
 | 
			
		||||
   */
 | 
			
		||||
  function testFieldAttachSubmit() {
 | 
			
		||||
    $entity_type = 'test_entity';
 | 
			
		||||
    $entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
 | 
			
		||||
    $this->createFieldWithInstance('_2');
 | 
			
		||||
 | 
			
		||||
    // Build the form.
 | 
			
		||||
    $entity_type = 'test_entity';
 | 
			
		||||
    $entity_init = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
 | 
			
		||||
    $langcode = LANGUAGE_NONE;
 | 
			
		||||
 | 
			
		||||
    // Build the form for all fields.
 | 
			
		||||
    $form = array();
 | 
			
		||||
    $form_state = form_state_defaults();
 | 
			
		||||
    field_attach_form($entity_type, $entity, $form, $form_state);
 | 
			
		||||
    field_attach_form($entity_type, $entity_init, $form, $form_state);
 | 
			
		||||
 | 
			
		||||
    // Simulate incoming values.
 | 
			
		||||
    // First field.
 | 
			
		||||
    $values = array();
 | 
			
		||||
    $weights = array();
 | 
			
		||||
    for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
 | 
			
		||||
@@ -999,22 +1118,59 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
 | 
			
		||||
    }
 | 
			
		||||
    // Leave an empty value. 'field_test' fields are empty if empty().
 | 
			
		||||
    $values[1]['value'] = 0;
 | 
			
		||||
 | 
			
		||||
    $langcode = LANGUAGE_NONE;
 | 
			
		||||
    // Second field.
 | 
			
		||||
    $values_2 = array();
 | 
			
		||||
    $weights_2 = array();
 | 
			
		||||
    for ($delta = 0; $delta < $this->field_2['cardinality']; $delta++) {
 | 
			
		||||
      $values_2[$delta]['value'] = mt_rand(1, 127);
 | 
			
		||||
      // Assign random weight.
 | 
			
		||||
      do {
 | 
			
		||||
        $weight = mt_rand(0, $this->field_2['cardinality']);
 | 
			
		||||
      } while (in_array($weight, $weights_2));
 | 
			
		||||
      $weights_2[$delta] = $weight;
 | 
			
		||||
      $values_2[$delta]['_weight'] = $weight;
 | 
			
		||||
    }
 | 
			
		||||
    // Leave an empty value. 'field_test' fields are empty if empty().
 | 
			
		||||
    $values_2[1]['value'] = 0;
 | 
			
		||||
    // Pretend the form has been built.
 | 
			
		||||
    drupal_prepare_form('field_test_entity_form', $form, $form_state);
 | 
			
		||||
    drupal_process_form('field_test_entity_form', $form, $form_state);
 | 
			
		||||
    $form_state['values'][$this->field_name][$langcode] = $values;
 | 
			
		||||
    $form_state['values'][$this->field_name_2][$langcode] = $values_2;
 | 
			
		||||
 | 
			
		||||
    // Call field_attach_submit() for all fields.
 | 
			
		||||
    $entity = clone($entity_init);
 | 
			
		||||
    field_attach_submit($entity_type, $entity, $form, $form_state);
 | 
			
		||||
 | 
			
		||||
    asort($weights);
 | 
			
		||||
    asort($weights_2);
 | 
			
		||||
    $expected_values = array();
 | 
			
		||||
    $expected_values_2 = array();
 | 
			
		||||
    foreach ($weights as $key => $value) {
 | 
			
		||||
      if ($key != 1) {
 | 
			
		||||
        $expected_values[] = array('value' => $values[$key]['value']);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    $this->assertIdentical($entity->{$this->field_name}[$langcode], $expected_values, 'Submit filters empty values');
 | 
			
		||||
    foreach ($weights_2 as $key => $value) {
 | 
			
		||||
      if ($key != 1) {
 | 
			
		||||
        $expected_values_2[] = array('value' => $values_2[$key]['value']);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    $this->assertIdentical($entity->{$this->field_name_2}[$langcode], $expected_values_2, 'Submit filters empty values');
 | 
			
		||||
 | 
			
		||||
    // Call field_attach_submit() for a single field (the second field).
 | 
			
		||||
    $options = array('field_name' => $this->field_name_2);
 | 
			
		||||
    $entity = clone($entity_init);
 | 
			
		||||
    field_attach_submit($entity_type, $entity, $form, $form_state, $options);
 | 
			
		||||
    $expected_values_2 = array();
 | 
			
		||||
    foreach ($weights_2 as $key => $value) {
 | 
			
		||||
      if ($key != 1) {
 | 
			
		||||
        $expected_values_2[] = array('value' => $values_2[$key]['value']);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    $this->assertFalse(isset($entity->{$this->field_name}), 'The first field does not exist in the entity object');
 | 
			
		||||
    $this->assertIdentical($entity->{$this->field_name_2}[$langcode], $expected_values_2, 'Submit filters empty values');
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1144,6 +1300,16 @@ class FieldInfoTestCase extends FieldTestCase {
 | 
			
		||||
    $this->assertIdentical($instances, $expected, "field_info_instances('user') returns " . var_export($expected, TRUE) . '.');
 | 
			
		||||
    $instances = field_info_instances('user', 'user');
 | 
			
		||||
    $this->assertIdentical($instances, array(), "field_info_instances('user', 'user') returns an empty array.");
 | 
			
		||||
 | 
			
		||||
    // Test that querying for invalid entity types does not add entries in the
 | 
			
		||||
    // list returned by field_info_instances().
 | 
			
		||||
    field_info_cache_clear();
 | 
			
		||||
    field_info_instances('invalid_entity', 'invalid_bundle');
 | 
			
		||||
    // Simulate new request by clearing static caches.
 | 
			
		||||
    drupal_static_reset();
 | 
			
		||||
    field_info_instances('invalid_entity', 'invalid_bundle');
 | 
			
		||||
    $instances = field_info_instances();
 | 
			
		||||
    $this->assertFalse(isset($instances['invalid_entity']), 'field_info_instances() does not contain entries for the invalid entity type that was queried before');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
@@ -1253,6 +1419,80 @@ class FieldInfoTestCase extends FieldTestCase {
 | 
			
		||||
    $this->assertNull(field_info_instance('comment', 'field', 'comment_node_article'), t('No instances are returned on disabled entity types.'));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test field_info_field_map().
 | 
			
		||||
   */
 | 
			
		||||
  function testFieldMap() {
 | 
			
		||||
    // We will overlook fields created by the 'standard' install profile.
 | 
			
		||||
    $exclude = field_info_field_map();
 | 
			
		||||
 | 
			
		||||
    // Create a new bundle for 'test_entity' entity type.
 | 
			
		||||
    field_test_create_bundle('test_bundle_2');
 | 
			
		||||
 | 
			
		||||
    // Create a couple fields.
 | 
			
		||||
    $fields  = array(
 | 
			
		||||
      array(
 | 
			
		||||
        'field_name' => 'field_1',
 | 
			
		||||
        'type' => 'test_field',
 | 
			
		||||
      ),
 | 
			
		||||
      array(
 | 
			
		||||
        'field_name' => 'field_2',
 | 
			
		||||
        'type' => 'hidden_test_field',
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
    foreach ($fields as $field) {
 | 
			
		||||
      field_create_field($field);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Create a couple instances.
 | 
			
		||||
    $instances = array(
 | 
			
		||||
      array(
 | 
			
		||||
        'field_name' => 'field_1',
 | 
			
		||||
        'entity_type' => 'test_entity',
 | 
			
		||||
        'bundle' => 'test_bundle',
 | 
			
		||||
      ),
 | 
			
		||||
      array(
 | 
			
		||||
        'field_name' => 'field_1',
 | 
			
		||||
        'entity_type' => 'test_entity',
 | 
			
		||||
        'bundle' => 'test_bundle_2',
 | 
			
		||||
      ),
 | 
			
		||||
      array(
 | 
			
		||||
        'field_name' => 'field_2',
 | 
			
		||||
        'entity_type' => 'test_entity',
 | 
			
		||||
        'bundle' => 'test_bundle',
 | 
			
		||||
      ),
 | 
			
		||||
      array(
 | 
			
		||||
        'field_name' => 'field_2',
 | 
			
		||||
        'entity_type' => 'test_cacheable_entity',
 | 
			
		||||
        'bundle' => 'test_bundle',
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
    foreach ($instances as $instance) {
 | 
			
		||||
      field_create_instance($instance);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $expected = array(
 | 
			
		||||
      'field_1' => array(
 | 
			
		||||
        'type' => 'test_field',
 | 
			
		||||
        'bundles' => array(
 | 
			
		||||
          'test_entity' => array('test_bundle', 'test_bundle_2'),
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
      'field_2' => array(
 | 
			
		||||
        'type' => 'hidden_test_field',
 | 
			
		||||
        'bundles' => array(
 | 
			
		||||
          'test_entity' => array('test_bundle'),
 | 
			
		||||
          'test_cacheable_entity' => array('test_bundle'),
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Check that the field map is correct.
 | 
			
		||||
    $map = field_info_field_map();
 | 
			
		||||
    $map = array_diff_key($map, $exclude);
 | 
			
		||||
    $this->assertEqual($map, $expected);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test that the field_info settings convenience functions work.
 | 
			
		||||
   */
 | 
			
		||||
@@ -1277,6 +1517,31 @@ class FieldInfoTestCase extends FieldTestCase {
 | 
			
		||||
      $this->assertIdentical(field_info_formatter_settings($type), $data['settings'], "field_info_formatter_settings returns {$type}'s formatter settings");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests that the field info cache can be built correctly.
 | 
			
		||||
   */
 | 
			
		||||
  function testFieldInfoCache() {
 | 
			
		||||
    // Create a test field and ensure it's in the array returned by
 | 
			
		||||
    // field_info_fields().
 | 
			
		||||
    $field_name = drupal_strtolower($this->randomName());
 | 
			
		||||
    $field = array(
 | 
			
		||||
      'field_name' => $field_name,
 | 
			
		||||
      'type' => 'test_field',
 | 
			
		||||
    );
 | 
			
		||||
    field_create_field($field);
 | 
			
		||||
    $fields = field_info_fields();
 | 
			
		||||
    $this->assertTrue(isset($fields[$field_name]), 'The test field is initially found in the array returned by field_info_fields().');
 | 
			
		||||
 | 
			
		||||
    // Now rebuild the field info cache, and set a variable which will cause
 | 
			
		||||
    // the cache to be cleared while it's being rebuilt; see
 | 
			
		||||
    // field_test_entity_info(). Ensure the test field is still in the returned
 | 
			
		||||
    // array.
 | 
			
		||||
    field_info_cache_clear();
 | 
			
		||||
    variable_set('field_test_clear_info_cache_in_hook_entity_info', TRUE);
 | 
			
		||||
    $fields = field_info_fields();
 | 
			
		||||
    $this->assertTrue(isset($fields[$field_name]), 'The test field is found in the array returned by field_info_fields() even if its cache is cleared while being rebuilt.');
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class FieldFormTestCase extends FieldTestCase {
 | 
			
		||||
@@ -2178,6 +2443,41 @@ class FieldCrudTestCase extends FieldTestCase {
 | 
			
		||||
    $this->assertTrue($field_definition < $field, t('The field was properly read.'));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests reading field definitions.
 | 
			
		||||
   */
 | 
			
		||||
  function testReadFields() {
 | 
			
		||||
    $field_definition = array(
 | 
			
		||||
      'field_name' => 'field_1',
 | 
			
		||||
      'type' => 'test_field',
 | 
			
		||||
    );
 | 
			
		||||
    field_create_field($field_definition);
 | 
			
		||||
 | 
			
		||||
    // Check that 'single column' criteria works.
 | 
			
		||||
    $fields = field_read_fields(array('field_name' => $field_definition['field_name']));
 | 
			
		||||
    $this->assertTrue(count($fields) == 1 && isset($fields[$field_definition['field_name']]), 'The field was properly read.');
 | 
			
		||||
 | 
			
		||||
    // Check that 'multi column' criteria works.
 | 
			
		||||
    $fields = field_read_fields(array('field_name' => $field_definition['field_name'], 'type' => $field_definition['type']));
 | 
			
		||||
    $this->assertTrue(count($fields) == 1 && isset($fields[$field_definition['field_name']]), 'The field was properly read.');
 | 
			
		||||
    $fields = field_read_fields(array('field_name' => $field_definition['field_name'], 'type' => 'foo'));
 | 
			
		||||
    $this->assertTrue(empty($fields), 'No field was found.');
 | 
			
		||||
 | 
			
		||||
    // Create an instance of the field.
 | 
			
		||||
    $instance_definition = array(
 | 
			
		||||
      'field_name' => $field_definition['field_name'],
 | 
			
		||||
      'entity_type' => 'test_entity',
 | 
			
		||||
      'bundle' => 'test_bundle',
 | 
			
		||||
    );
 | 
			
		||||
    field_create_instance($instance_definition);
 | 
			
		||||
 | 
			
		||||
    // Check that criteria spanning over the field_config_instance table work.
 | 
			
		||||
    $fields = field_read_fields(array('entity_type' => $instance_definition['entity_type'], 'bundle' => $instance_definition['bundle']));
 | 
			
		||||
    $this->assertTrue(count($fields) == 1 && isset($fields[$field_definition['field_name']]), 'The field was properly read.');
 | 
			
		||||
    $fields = field_read_fields(array('entity_type' => $instance_definition['entity_type'], 'field_name' => $instance_definition['field_name']));
 | 
			
		||||
    $this->assertTrue(count($fields) == 1 && isset($fields[$field_definition['field_name']]), 'The field was properly read.');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test creation of indexes on data column.
 | 
			
		||||
   */
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,12 @@
 | 
			
		||||
 * Implements hook_entity_info().
 | 
			
		||||
 */
 | 
			
		||||
function field_test_entity_info() {
 | 
			
		||||
  // If requested, clear the field cache while this hook is being called. See
 | 
			
		||||
  // testFieldInfoCache().
 | 
			
		||||
  if (variable_get('field_test_clear_info_cache_in_hook_entity_info', FALSE)) {
 | 
			
		||||
    field_info_cache_clear();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  $bundles = variable_get('field_test_bundles', array('test_bundle' => array('label' => 'Test Bundle')));
 | 
			
		||||
  $test_entity_modes = array(
 | 
			
		||||
    'full' => array(
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,8 @@ files[] = field_test.entity.inc
 | 
			
		||||
version = VERSION
 | 
			
		||||
hidden = TRUE
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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'],
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,8 @@ core = 7.x
 | 
			
		||||
dependencies[] = field
 | 
			
		||||
files[] = field_ui.test
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -332,23 +332,30 @@ function _field_ui_bundle_admin_path($entity_type, $bundle_name) {
 | 
			
		||||
 * Identifies inactive fields within a bundle.
 | 
			
		||||
 */
 | 
			
		||||
function field_ui_inactive_instances($entity_type, $bundle_name = NULL) {
 | 
			
		||||
  if (!empty($bundle_name)) {
 | 
			
		||||
    $inactive = array($bundle_name => array());
 | 
			
		||||
    $params = array('bundle' => $bundle_name);
 | 
			
		||||
  $params = array('entity_type' => $entity_type);
 | 
			
		||||
 | 
			
		||||
  if (empty($bundle_name)) {
 | 
			
		||||
    $active = field_info_instances($entity_type);
 | 
			
		||||
    $inactive = array();
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    $inactive = array();
 | 
			
		||||
    $params = array();
 | 
			
		||||
    // Restrict to the specified bundle. For consistency with the case where
 | 
			
		||||
    // $bundle_name is NULL, the $active and  $inactive arrays are keyed by
 | 
			
		||||
    // bundle name first.
 | 
			
		||||
    $params['bundle'] = $bundle_name;
 | 
			
		||||
    $active = array($bundle_name => field_info_instances($entity_type, $bundle_name));
 | 
			
		||||
    $inactive = array($bundle_name => array());
 | 
			
		||||
  }
 | 
			
		||||
  $params['entity_type'] = $entity_type;
 | 
			
		||||
 | 
			
		||||
  $active_instances = field_info_instances($entity_type);
 | 
			
		||||
  // Iterate on existing definitions, and spot those that do not appear in the
 | 
			
		||||
  // $active list collected earlier.
 | 
			
		||||
  $all_instances = field_read_instances($params, array('include_inactive' => TRUE));
 | 
			
		||||
  foreach ($all_instances as $instance) {
 | 
			
		||||
    if (!isset($active_instances[$instance['bundle']][$instance['field_name']])) {
 | 
			
		||||
    if (!isset($active[$instance['bundle']][$instance['field_name']])) {
 | 
			
		||||
      $inactive[$instance['bundle']][$instance['field_name']] = $instance;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!empty($bundle_name)) {
 | 
			
		||||
    return $inactive[$bundle_name];
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -269,7 +269,7 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
 | 
			
		||||
   */
 | 
			
		||||
  function assertFieldSettings($bundle, $field_name, $string = 'dummy test string', $entity_type = 'node') {
 | 
			
		||||
    // Reset the fields info.
 | 
			
		||||
    _field_info_collate_fields(TRUE);
 | 
			
		||||
    field_info_cache_clear();
 | 
			
		||||
    // Assert field settings.
 | 
			
		||||
    $field = field_info_field($field_name);
 | 
			
		||||
    $this->assertTrue($field['settings']['test_field_setting'] == $string, t('Field settings were found.'));
 | 
			
		||||
@@ -360,7 +360,7 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
 | 
			
		||||
    $this->fieldUIDeleteField($bundle_path1, $this->field_name, $this->field_label, $this->type);
 | 
			
		||||
 | 
			
		||||
    // Reset the fields info.
 | 
			
		||||
    _field_info_collate_fields(TRUE);
 | 
			
		||||
    field_info_cache_clear();
 | 
			
		||||
    // Check that the field instance was deleted.
 | 
			
		||||
    $this->assertNull(field_info_instance('node', $this->field_name, $this->type), t('Field instance was deleted.'));
 | 
			
		||||
    // Check that the field was not deleted
 | 
			
		||||
@@ -370,7 +370,7 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
 | 
			
		||||
    $this->fieldUIDeleteField($bundle_path2, $this->field_name, $this->field_label, $type_name2);
 | 
			
		||||
 | 
			
		||||
    // Reset the fields info.
 | 
			
		||||
    _field_info_collate_fields(TRUE);
 | 
			
		||||
    field_info_cache_clear();
 | 
			
		||||
    // Check that the field instance was deleted.
 | 
			
		||||
    $this->assertNull(field_info_instance('node', $this->field_name, $type_name2), t('Field instance was deleted.'));
 | 
			
		||||
    // Check that the field was deleted too.
 | 
			
		||||
 
 | 
			
		||||
@@ -261,8 +261,16 @@ function file_field_update($entity_type, $entity, $field, $instance, $langcode,
 | 
			
		||||
    $current_fids[] = $item['fid'];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Compare the original field values with the ones that are being saved.
 | 
			
		||||
  $original = $entity->original;
 | 
			
		||||
  // Compare the original field values with the ones that are being saved. Use
 | 
			
		||||
  // $entity->original to check this when possible, but if it isn't available,
 | 
			
		||||
  // create a bare-bones entity and load its previous values instead.
 | 
			
		||||
  if (isset($entity->original)) {
 | 
			
		||||
    $original = $entity->original;
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    $original = entity_create_stub_entity($entity_type, array($id, $vid, $bundle));
 | 
			
		||||
    field_attach_load($entity_type, array($id => $original), FIELD_LOAD_CURRENT, array('field_id' => $field['id']));
 | 
			
		||||
  }
 | 
			
		||||
  $original_fids = array();
 | 
			
		||||
  if (!empty($original->{$field['field_name']}[$langcode])) {
 | 
			
		||||
    foreach ($original->{$field['field_name']}[$langcode] as $original_item) {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,8 @@ core = 7.x
 | 
			
		||||
dependencies[] = field
 | 
			
		||||
files[] = tests/file.test
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,8 @@ version = VERSION
 | 
			
		||||
core = 7.x
 | 
			
		||||
hidden = TRUE
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,13 +2,14 @@
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * Admin page callbacks for the filter module.
 | 
			
		||||
 * Administrative page callbacks for the Filter module.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Menu callback; Displays a list of all text formats and allows them to be rearranged.
 | 
			
		||||
 * Page callback: Form constructor for a form to list and reorder text formats.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup forms
 | 
			
		||||
 * @see filter_menu()
 | 
			
		||||
 * @see filter_admin_overview_submit()
 | 
			
		||||
 */
 | 
			
		||||
function filter_admin_overview($form) {
 | 
			
		||||
@@ -45,6 +46,9 @@ function filter_admin_overview($form) {
 | 
			
		||||
  return $form;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Form submission handler for filter_admin_overview().
 | 
			
		||||
 */
 | 
			
		||||
function filter_admin_overview_submit($form, &$form_state) {
 | 
			
		||||
  foreach ($form_state['values']['formats'] as $id => $data) {
 | 
			
		||||
    if (is_array($data) && isset($data['weight'])) {
 | 
			
		||||
@@ -95,7 +99,26 @@ function theme_filter_admin_overview($variables) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Menu callback; Display a text format form.
 | 
			
		||||
 * Page callback: Displays the text format add/edit form.
 | 
			
		||||
 *
 | 
			
		||||
 * @param object|null $format
 | 
			
		||||
 *   (optional) An object representing a format, with the following properties:
 | 
			
		||||
 *   - format: A machine-readable name representing the ID of the text format
 | 
			
		||||
 *     to save. If this corresponds to an existing text format, that format
 | 
			
		||||
 *     will be updated; otherwise, a new format will be created.
 | 
			
		||||
 *   - name: The title of the text format.
 | 
			
		||||
 *   - cache: (optional) An integer indicating whether the text format is
 | 
			
		||||
 *     cacheable (1) or not (0). Defaults to 1.
 | 
			
		||||
 *   - status: (optional) An integer indicating whether the text format is
 | 
			
		||||
 *     enabled (1) or not (0). Defaults to 1.
 | 
			
		||||
 *   - weight: (optional) The weight of the text format, which controls its
 | 
			
		||||
 *     placement in text format lists. If omitted, the weight is set to 0.
 | 
			
		||||
 *     Defaults to NULL.
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   A form array.
 | 
			
		||||
 *
 | 
			
		||||
 * @see filter_menu()
 | 
			
		||||
 */
 | 
			
		||||
function filter_admin_format_page($format = NULL) {
 | 
			
		||||
  if (!isset($format->name)) {
 | 
			
		||||
@@ -109,11 +132,24 @@ function filter_admin_format_page($format = NULL) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Generate a text format form.
 | 
			
		||||
 * Form constructor for the text format add/edit form.
 | 
			
		||||
 *
 | 
			
		||||
 * @param $format
 | 
			
		||||
 *   A format object having the properties:
 | 
			
		||||
 *   - format: A machine-readable name representing the ID of the text format to
 | 
			
		||||
 *     save. If this corresponds to an existing text format, that format will be
 | 
			
		||||
 *     updated; otherwise, a new format will be created.
 | 
			
		||||
 *   - name: The title of the text format.
 | 
			
		||||
 *   - cache: An integer indicating whether the text format is cacheable (1) or
 | 
			
		||||
 *     not (0). Defaults to 1.
 | 
			
		||||
 *   - status: (optional) An integer indicating whether the text format is
 | 
			
		||||
 *     enabled (1) or not (0). Defaults to 1.
 | 
			
		||||
 *   - weight: (optional) The weight of the text format, which controls its
 | 
			
		||||
 *     placement in text format lists. If omitted, the weight is set to 0.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup forms
 | 
			
		||||
 * @see filter_admin_format_form_validate()
 | 
			
		||||
 * @see filter_admin_format_form_submit()
 | 
			
		||||
 * @ingroup forms
 | 
			
		||||
 */
 | 
			
		||||
function filter_admin_format_form($form, &$form_state, $format) {
 | 
			
		||||
  $is_fallback = ($format->format == filter_fallback_format());
 | 
			
		||||
@@ -287,7 +323,9 @@ function theme_filter_admin_format_filter_order($variables) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Validate text format form submissions.
 | 
			
		||||
 * Form validation handler for filter_admin_format_form().
 | 
			
		||||
 *
 | 
			
		||||
 * @see filter_admin_format_form_submit()
 | 
			
		||||
 */
 | 
			
		||||
function filter_admin_format_form_validate($form, &$form_state) {
 | 
			
		||||
  $format_format = trim($form_state['values']['format']);
 | 
			
		||||
@@ -304,7 +342,9 @@ function filter_admin_format_form_validate($form, &$form_state) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Process text format form submissions.
 | 
			
		||||
 * Form submission handler for filter_admin_format_form().
 | 
			
		||||
 *
 | 
			
		||||
 * @see filter_admin_format_form_validate()
 | 
			
		||||
 */
 | 
			
		||||
function filter_admin_format_form_submit($form, &$form_state) {
 | 
			
		||||
  // Remove unnecessary values.
 | 
			
		||||
@@ -336,10 +376,14 @@ function filter_admin_format_form_submit($form, &$form_state) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Menu callback; confirm deletion of a format.
 | 
			
		||||
 * Form constructor for the text format deletion confirmation form.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup forms
 | 
			
		||||
 * @param $format
 | 
			
		||||
 *   An object representing a text format.
 | 
			
		||||
 *
 | 
			
		||||
 * @see filter_menu()
 | 
			
		||||
 * @see filter_admin_disable_submit()
 | 
			
		||||
 * @ingroup forms
 | 
			
		||||
 */
 | 
			
		||||
function filter_admin_disable($form, &$form_state, $format) {
 | 
			
		||||
  $form['#format'] = $format;
 | 
			
		||||
@@ -353,7 +397,7 @@ function filter_admin_disable($form, &$form_state, $format) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Process filter disable form submission.
 | 
			
		||||
 * Form submission handler for filter_admin_disable().
 | 
			
		||||
 */
 | 
			
		||||
function filter_admin_disable_submit($form, &$form_state) {
 | 
			
		||||
  $format = $form['#format'];
 | 
			
		||||
@@ -362,4 +406,3 @@ function filter_admin_disable_submit($form, &$form_state) {
 | 
			
		||||
 | 
			
		||||
  $form_state['redirect'] = 'admin/config/content/formats';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,8 @@ files[] = filter.test
 | 
			
		||||
required = TRUE
 | 
			
		||||
configure = admin/config/content/formats
 | 
			
		||||
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-03-07
 | 
			
		||||
version = "7.21"
 | 
			
		||||
; Information added by drupal.org packaging script on 2013-04-03
 | 
			
		||||
version = "7.22"
 | 
			
		||||
project = "drupal"
 | 
			
		||||
datestamp = "1362616996"
 | 
			
		||||
datestamp = "1365027012"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * Install, update and uninstall functions for the filter module.
 | 
			
		||||
 * Install, update, and uninstall functions for the Filter module.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user