From 174d1ce37b414301b367f7286f000ccdb6f03e66 Mon Sep 17 00:00:00 2001
From: Tim Steiner <tsteiner2@unl.edu>
Date: Fri, 3 Aug 2012 09:59:36 -0500
Subject: [PATCH] [gh-441] Update drupal core to 7.15

---
 CHANGELOG.txt                                 |  52 ++-
 COPYRIGHT.txt                                 |  25 +-
 MAINTAINERS.txt                               |   6 +-
 UPGRADE.txt                                   |   2 +-
 authorize.php                                 |   1 -
 includes/bootstrap.inc                        |  49 ++-
 includes/common.inc                           | 107 ++++--
 includes/database/database.inc                |   9 +-
 includes/database/mysql/database.inc          |   4 +-
 includes/database/mysql/query.inc             |   4 +-
 includes/database/mysql/schema.inc            |   4 +-
 includes/database/pgsql/database.inc          |   4 +-
 includes/database/pgsql/select.inc            |   4 +-
 includes/database/prefetch.inc                |   4 +-
 includes/database/query.inc                   |   4 +-
 includes/database/select.inc                  |   4 +-
 includes/database/sqlite/database.inc         |   4 +-
 includes/database/sqlite/query.inc            |   4 +-
 includes/database/sqlite/select.inc           |   4 +-
 includes/entity.inc                           |  23 +-
 includes/errors.inc                           |   6 +-
 includes/form.inc                             |  66 ++--
 includes/graph.inc                            |   8 +-
 includes/locale.inc                           |  25 +-
 includes/module.inc                           |  27 ++
 includes/theme.inc                            | 185 +++++++---
 includes/update.inc                           |   2 +-
 misc/autocomplete.js                          |   6 +-
 misc/states.js                                |   3 +-
 misc/tableselect.js                           |   3 +-
 modules/aggregator/aggregator.info            |   6 +-
 modules/aggregator/tests/aggregator_test.info |   6 +-
 modules/block/block.info                      |   6 +-
 modules/block/block.install                   |  11 +-
 modules/block/block.test                      |   4 +-
 modules/block/tests/block_test.info           |   6 +-
 .../block_test_theme/block_test_theme.info    |   6 +-
 modules/blog/blog.info                        |   6 +-
 modules/book/book.info                        |   6 +-
 modules/book/book.module                      |  15 +-
 modules/book/book.pages.inc                   |   5 +-
 modules/book/book.test                        |  35 +-
 modules/color/color.info                      |   6 +-
 modules/color/color.install                   |   9 +
 modules/comment/comment.info                  |   6 +-
 modules/comment/comment.install               |  20 +-
 modules/comment/comment.module                |   1 +
 modules/comment/comment.pages.inc             |   8 +-
 modules/comment/comment.test                  |  25 ++
 modules/contact/contact.info                  |   6 +-
 modules/contact/contact.install               |   2 +-
 modules/contextual/contextual.info            |   6 +-
 modules/dashboard/dashboard.info              |   6 +-
 modules/dblog/dblog.info                      |   6 +-
 modules/dblog/dblog.install                   |   2 +-
 modules/dblog/dblog.test                      |   4 +-
 modules/field/field.api.php                   |  84 ++---
 modules/field/field.attach.inc                |   4 +-
 modules/field/field.form.inc                  | 193 +++++-----
 modules/field/field.info                      |   6 +-
 modules/field/field.info.inc                  |   5 +-
 modules/field/field.install                   |   4 +-
 modules/field/field.module                    |  82 ++---
 .../field_sql_storage/field_sql_storage.info  |   6 +-
 .../field_sql_storage.install                 |   2 +-
 .../field_sql_storage.module                  |   7 +-
 modules/field/modules/list/list.info          |   6 +-
 modules/field/modules/list/list.install       |  11 +-
 .../field/modules/list/tests/list_test.info   |   6 +-
 modules/field/modules/number/number.info      |   6 +-
 modules/field/modules/options/options.info    |   6 +-
 modules/field/modules/text/text.info          |   6 +-
 modules/field/tests/field.test                |  14 +-
 modules/field/tests/field_test.info           |   6 +-
 modules/field/tests/field_test.module         |  11 +
 modules/field_ui/field_ui.admin.inc           |   5 +-
 modules/field_ui/field_ui.api.php             |   2 +-
 modules/field_ui/field_ui.info                |   6 +-
 modules/field_ui/field_ui.js                  |   2 +-
 modules/field_ui/field_ui.test                |   2 +-
 modules/file/file.field.inc                   |   8 +-
 modules/file/file.info                        |   6 +-
 modules/file/file.js                          |   2 +-
 modules/file/tests/file.test                  |   2 +-
 modules/file/tests/file_module_test.info      |   6 +-
 modules/filter/filter.info                    |   6 +-
 modules/filter/filter.install                 |   2 +-
 modules/filter/filter.test                    |  25 +-
 modules/forum/forum-icon.tpl.php              |   4 +-
 modules/forum/forum-list.tpl.php              |  45 +--
 modules/forum/forum-rtl.css                   |   4 +
 modules/forum/forum-submitted.tpl.php         |  12 +-
 modules/forum/forum-topic-list.tpl.php        |  44 +--
 modules/forum/forum.admin.inc                 |  77 +++-
 modules/forum/forum.css                       |   4 +
 modules/forum/forum.info                      |   6 +-
 modules/forum/forum.install                   |  32 +-
 modules/forum/forum.module                    | 183 +++++++---
 modules/forum/forum.pages.inc                 |  13 +-
 modules/forum/forum.test                      |  98 +++--
 modules/forum/forums.tpl.php                  |  14 +-
 modules/help/help.info                        |   6 +-
 modules/image/image.admin.inc                 |   2 +-
 modules/image/image.field.inc                 |   4 +-
 modules/image/image.info                      |   6 +-
 modules/image/image.install                   |   9 +
 modules/image/tests/image_module_test.info    |   6 +-
 modules/locale/locale.datepicker.js           | 138 +++----
 modules/locale/locale.info                    |   6 +-
 modules/locale/locale.install                 |  18 +-
 modules/locale/locale.module                  |  32 +-
 modules/locale/locale.test                    |  53 ++-
 modules/locale/tests/locale_test.info         |   6 +-
 modules/menu/menu.info                        |   6 +-
 modules/menu/menu.install                     |   4 +-
 modules/node/content_types.inc                |   2 +-
 modules/node/node.admin.inc                   |   9 +-
 modules/node/node.info                        |   6 +-
 modules/node/node.install                     |  13 +-
 modules/node/node.module                      |  26 +-
 modules/node/node.pages.inc                   |   9 +-
 modules/node/node.test                        | 108 +++++-
 modules/node/node.tokens.inc                  |   3 +-
 modules/node/tests/node_access_test.info      |   6 +-
 modules/node/tests/node_test.info             |   6 +-
 modules/node/tests/node_test_exception.info   |   6 +-
 modules/openid/openid.info                    |   6 +-
 modules/openid/openid.install                 |   2 +-
 modules/openid/tests/openid_test.info         |   6 +-
 modules/overlay/overlay.info                  |   6 +-
 modules/path/path.info                        |   6 +-
 modules/path/path.module                      |  35 +-
 modules/php/php.info                          |   6 +-
 modules/php/php.test                          |   4 +-
 modules/poll/poll.info                        |   6 +-
 modules/poll/poll.install                     |   9 +
 modules/profile/profile.info                  |   6 +-
 modules/rdf/rdf.info                          |   6 +-
 modules/rdf/tests/rdf_test.info               |   6 +-
 modules/search/search.info                    |   6 +-
 .../search/tests/search_embedded_form.info    |   6 +-
 modules/search/tests/search_extra_type.info   |   6 +-
 modules/shortcut/shortcut.info                |   6 +-
 modules/simpletest/drupal_web_test_case.php   | 204 ++++++++---
 modules/simpletest/files/README.txt           |   8 +-
 modules/simpletest/simpletest.info            |   6 +-
 modules/simpletest/simpletest.js              |  71 ++--
 modules/simpletest/tests/actions.test         |   2 +-
 .../simpletest/tests/actions_loop_test.info   |   6 +-
 modules/simpletest/tests/ajax_forms_test.info |   6 +-
 modules/simpletest/tests/ajax_test.info       |   6 +-
 modules/simpletest/tests/batch.test           |   2 -
 modules/simpletest/tests/batch_test.info      |   6 +-
 modules/simpletest/tests/common_test.info     |   6 +-
 .../tests/common_test_cron_helper.info        |   6 +-
 modules/simpletest/tests/database_test.info   |   6 +-
 ...drupal_system_listing_compatible_test.info |   6 +-
 ...upal_system_listing_incompatible_test.info |   6 +-
 .../simpletest/tests/entity_cache_test.info   |   6 +-
 .../tests/entity_cache_test_dependency.info   |   6 +-
 .../tests/entity_crud_hook_test.info          |   6 +-
 modules/simpletest/tests/entity_query.test    |  41 ++-
 .../tests/entity_query_access_test.info       |  12 +
 .../tests/entity_query_access_test.module     |  54 +++
 modules/simpletest/tests/error_test.info      |   6 +-
 modules/simpletest/tests/file_test.info       |   6 +-
 modules/simpletest/tests/filter_test.info     |   6 +-
 modules/simpletest/tests/form.test            |  51 ++-
 modules/simpletest/tests/form_test.info       |   6 +-
 modules/simpletest/tests/form_test.module     |  41 +++
 modules/simpletest/tests/image_test.info      |   6 +-
 modules/simpletest/tests/menu.test            |   4 +-
 modules/simpletest/tests/menu_test.info       |   6 +-
 modules/simpletest/tests/module_test.info     |   6 +-
 modules/simpletest/tests/path_test.info       |   6 +-
 .../simpletest/tests/requirements1_test.info  |   6 +-
 .../simpletest/tests/requirements2_test.info  |   6 +-
 modules/simpletest/tests/session_test.info    |   6 +-
 .../tests/system_dependencies_test.info       |   6 +-
 ...atible_core_version_dependencies_test.info |   6 +-
 ...system_incompatible_core_version_test.info |   6 +-
 ...ible_module_version_dependencies_test.info |   6 +-
 ...stem_incompatible_module_version_test.info |   6 +-
 modules/simpletest/tests/system_test.info     |   6 +-
 modules/simpletest/tests/taxonomy_test.info   |   6 +-
 modules/simpletest/tests/theme.test           |  31 ++
 modules/simpletest/tests/theme_test.info      |   6 +-
 modules/simpletest/tests/theme_test.module    |   2 +
 .../themes/test_basetheme/test_basetheme.info |  13 +
 .../themes/test_subtheme/test_subtheme.info   |  13 +
 .../tests/themes/test_theme/test_theme.info   |   8 +-
 .../simpletest/tests/update_script_test.info  |   6 +-
 modules/simpletest/tests/update_test_1.info   |   6 +-
 modules/simpletest/tests/update_test_2.info   |   6 +-
 modules/simpletest/tests/update_test_3.info   |   6 +-
 modules/simpletest/tests/upgrade/upgrade.test | 134 ++-----
 modules/simpletest/tests/url_alter_test.info  |   6 +-
 modules/simpletest/tests/xmlrpc_test.info     |   6 +-
 modules/statistics/statistics.admin.inc       |  52 ++-
 modules/statistics/statistics.info            |   6 +-
 modules/statistics/statistics.install         |   4 +-
 modules/statistics/statistics.module          |  59 +--
 modules/statistics/statistics.pages.inc       |  16 +-
 modules/statistics/statistics.test            |  28 +-
 modules/syslog/syslog.info                    |   6 +-
 modules/system/image.gd.inc                   |   4 +-
 modules/system/system.admin.inc               |   2 +-
 modules/system/system.api.php                 |  94 +++--
 modules/system/system.base.css                |   1 +
 modules/system/system.info                    |   6 +-
 modules/system/system.install                 |  31 +-
 modules/system/system.module                  |  45 +--
 modules/system/theme.api.php                  |  24 +-
 modules/taxonomy/taxonomy.admin.inc           |   3 +-
 modules/taxonomy/taxonomy.info                |   6 +-
 modules/taxonomy/taxonomy.install             | 120 +++++--
 modules/taxonomy/taxonomy.module              |  39 +-
 modules/taxonomy/taxonomy.test                | 336 +++++++++++-------
 modules/toolbar/toolbar.info                  |   6 +-
 modules/tracker/tracker.info                  |   6 +-
 modules/tracker/tracker.install               |   2 +-
 .../translation/tests/translation_test.info   |   6 +-
 modules/translation/translation.info          |   6 +-
 modules/translation/translation.module        |  20 +-
 modules/translation/translation.pages.inc     |   2 +-
 modules/translation/translation.test          |   2 +-
 modules/trigger/tests/trigger_test.info       |   6 +-
 modules/trigger/trigger.admin.inc             |   2 +-
 modules/trigger/trigger.info                  |   6 +-
 modules/trigger/trigger.install               |   9 +
 modules/trigger/trigger.module                |  24 +-
 modules/trigger/trigger.test                  |  29 ++
 modules/update/tests/aaa_update_test.info     |   6 +-
 modules/update/tests/bbb_update_test.info     |   6 +-
 modules/update/tests/ccc_update_test.info     |   6 +-
 .../update_test_basetheme.info                |   6 +-
 .../update_test_subtheme.info                 |   6 +-
 modules/update/tests/update_test.info         |   6 +-
 modules/update/tests/update_test.module       |  64 ++--
 modules/update/update-rtl.css                 |   4 +
 modules/update/update.api.php                 |  30 +-
 modules/update/update.authorize.inc           |  83 +++--
 modules/update/update.compare.inc             | 185 ++++++----
 modules/update/update.css                     |   4 +
 modules/update/update.fetch.inc               |  61 ++--
 modules/update/update.info                    |   6 +-
 modules/update/update.install                 |  40 +--
 modules/update/update.manager.inc             | 184 +++++-----
 modules/update/update.module                  | 214 ++++++-----
 modules/update/update.report.inc              |   5 +-
 modules/update/update.settings.inc            |  26 +-
 modules/update/update.test                    | 122 ++++---
 modules/user/tests/user_form_test.info        |   6 +-
 modules/user/user.info                        |   6 +-
 modules/user/user.install                     |  20 +-
 modules/user/user.module                      |  14 +-
 modules/user/user.pages.inc                   |   8 +-
 modules/user/user.test                        |  62 +++-
 profiles/minimal/minimal.info                 |   6 +-
 profiles/minimal/minimal.install              |   2 +-
 profiles/standard/standard.info               |   6 +-
 ...drupal_system_listing_compatible_test.info |   6 +-
 ...upal_system_listing_incompatible_test.info |   6 +-
 profiles/testing/testing.info                 |   6 +-
 sites/default/default.settings.php            |   2 +-
 themes/bartik/bartik.info                     |   6 +-
 themes/bartik/css/style.css                   |   2 +-
 themes/bartik/template.php                    |   2 +-
 themes/garland/garland.info                   |   6 +-
 themes/seven/seven.info                       |   6 +-
 themes/stark/stark.info                       |   6 +-
 271 files changed, 3712 insertions(+), 2018 deletions(-)
 create mode 100644 modules/simpletest/tests/entity_query_access_test.info
 create mode 100644 modules/simpletest/tests/entity_query_access_test.module
 create mode 100644 modules/simpletest/tests/themes/test_basetheme/test_basetheme.info
 create mode 100644 modules/simpletest/tests/themes/test_subtheme/test_subtheme.info

diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 231618d0c..09662cf88 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,4 +1,55 @@
 
+Drupal 7.15, 2012-08-01
+-----------------------
+- Introduced a 'user_password_reset_timeout' variable to allow the 24-hour
+  expiration for user password reset links to be adjusted (API addition).
+- Fixed database errors due to ambiguous column names that occurred when
+  EntityFieldQuery was used in certain situations.
+- Changed the drupal_array_get_nested_value() function to return a reference
+  (API addition).
+- Changed the System module's hook_block_info() implementation to assign the
+  "Main page content" and "System help" blocks to appropriate regions by
+  default and prevent error messages on the block administration page (data
+  structure change).
+- Fixed regression: Non-node entities couldn't be accessed with
+  EntityFieldQuery.
+- Fixed regression: Optional radio buttons with an empty, non-NULL default
+  value led to an illegal choice error when none were selected.
+- Reorganized the testing framework to split setUp() into specific sub-methods
+  and fix several regressions in the process.
+- Fixed bug which made it impossible to search for strings that have not been
+  translated into a particular language.
+- Renamed the "Field" column on the Manage Fields screen to "Field type", since
+  the former was confusing and inaccurate (UI change).
+- Performance improvement: Removed needless call to system_rebuild_module_data()
+  in field_sync_field_status(), greatly speeding up bulk module enable/disable.
+- Fixed bug which prevented notifications from being sent when core, module, and
+  theme updates are available.
+- Fixed bug which prevented sub-themes from inheriting the default values of
+  theme settings defined by the base theme.
+- Fixed bug which prevented the jQuery UI Datepicker from being localized.
+- Made Ajax alert dialogs respect error reporting settings.
+- Fixed bug which prevented image styles from being deleted on PHP 5.4.
+- Fixed bug: Language detection by domain only worked on port 80.
+- Fixed regression: The first plural index on a page was not calculated
+  correctly.
+- Introduced generic entity language support. Entities may now declare their
+  language property in hook_entity_info(), and modules working with entities
+  may access the language using entity_language() (API change:
+  http://drupal.org/node/1626346).
+- Added EntityFieldQuery support for taxonomy bundles.
+- Fixed issue where field form structure was incomplete if field_access()
+  returned FALSE. Instead of being incomplete, the form structure now has
+  #access set to FALSE and field form validation is skipped (data structure
+  change: http://drupal.org/node/1663020).
+- Fixed data loss issue due to field_has_data() returning inconsistent results.
+  The fix adds an optional DANGEROUS_ACCESS_CHECK_OPT_OUT tag to entity field
+  queries which field storage engines can respond to (API addition:
+  http://drupal.org/node/1597378).
+- Fixed notice: Undefined index: default_image in image_field_prepare_view()
+- Numerous API documentation improvements.
+- Additional automated test coverage.
+
 Drupal 7.14 2012-05-02
 ----------------------
 - Fixed "integrity constraint" fatal errors when rebuilding registry.
@@ -48,7 +99,6 @@ Drupal 7.14 2012-05-02
   - system_update_7061() converts filepaths too aggressively.
   - Trigger upgrade path: Node triggers removed when upgrading to 7-x from 6.25.
 
-
 Drupal 7.13 2012-05-02
 ----------------------
 - Fixed security issues (Multiple vulnerabilities), see SA-CORE-2012-002.
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index e98347441..a2a6511cf 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -1,5 +1,4 @@
-
-All Drupal code is Copyright 2001 - 2010 by the original authors.
+All Drupal code is Copyright 2001 - 2012 by the original authors.
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -21,5 +20,25 @@ Drupal includes works under other copyright notices and distributed
 according to the terms of the GNU General Public License or a compatible
 license, including:
 
-  jQuery - Copyright (c) 2008 - 2009 John Resig
+Javascript
+
+  Farbtastic - Copyright (c) 2010 Matt Farina
+
+  jQuery - Copyright (c) 2010 John Resig
+
+  jQuery BBQ - Copyright (c) 2010 "Cowboy" Ben Alman
+
+  jQuery Cookie - Copyright (c) 2006 Klaus Hartl
+
+  jQuery Form - Copyright (c) 2010 Mike Alsup
+
+  jQuery Once - Copyright (c) 2009 Konstantin K�fer
+
+  jQuery UI - Copyright (c) 2010 by the original authors
+    (http://jqueryui.com/about)
+
+  Sizzle.js - Copyright (c) 2010 The Dojo Foundation (http://sizzlejs.com/)
+
+PHP
 
+  ArchiveTar - Copyright (c) 1997 - 2008 Vincent Blavet
diff --git a/MAINTAINERS.txt b/MAINTAINERS.txt
index aff25901f..aa1421533 100644
--- a/MAINTAINERS.txt
+++ b/MAINTAINERS.txt
@@ -11,6 +11,7 @@ The branch maintainers for Drupal 7 are:
 
 - Dries Buytaert 'dries' <http://drupal.org/user/1>
 - Angela Byron 'webchick' <http://drupal.org/user/24967>
+- David Rothstein 'David_Rothstein' <http://drupal.org/user/124982>
 
 
 Component maintainers
@@ -23,7 +24,6 @@ maintainer. Current component maintainers for Drupal 7:
 
 Ajax system
 - Alex Bronstein 'effulgentsia' <http://drupal.org/user/78040>
-- Randy Fay 'rfay' <http://drupal.org/user/30906>
 - Earl Miles 'merlinofchaos' <http://drupal.org/user/26979>
 
 Base system
@@ -147,6 +147,10 @@ User experience and usability
 - Roy Scholten 'yoroy' <http://drupal.org/user/41502>
 - Bojhan Somers 'Bojhan' <http://drupal.org/user/87969>
 
+Node Access
+- Moshe Weitzman 'moshe weitzman' <http://drupal.org/user/23>
+- Ken Rickard 'agentrickard' <http://drupal.org/user/20975>
+- Jess Myrbo 'xjm' <http://drupal.org/user/65776>
 
 Module maintainers
 ------------------
diff --git a/UPGRADE.txt b/UPGRADE.txt
index c993df7e1..e870ff0f0 100644
--- a/UPGRADE.txt
+++ b/UPGRADE.txt
@@ -141,7 +141,7 @@ following the instructions in the INTRODUCTION section at the top of this file:
    download Drupal 6.x and follow the instructions in its UPGRADE.txt. This
    document only applies for upgrades from 6.x to 7.x.
 
-3. In addition to updating to the latest available version of Drupal 7.x core,
+3. In addition to updating to the latest available version of Drupal 6.x core,
    you must also upgrade all of your contributed modules for Drupal to their
    latest Drupal 6.x versions.
 
diff --git a/authorize.php b/authorize.php
index 3c0bd7b36..d14fa6e59 100644
--- a/authorize.php
+++ b/authorize.php
@@ -60,7 +60,6 @@ function authorize_access_allowed() {
 // *** Real work of the script begins here. ***
 
 require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
-require_once DRUPAL_ROOT . '/includes/session.inc';
 require_once DRUPAL_ROOT . '/includes/common.inc';
 require_once DRUPAL_ROOT . '/includes/file.inc';
 require_once DRUPAL_ROOT . '/includes/module.inc';
diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc
index 61edce216..b99e4b93f 100644
--- a/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -8,7 +8,7 @@
 /**
  * The current system version.
  */
-define('VERSION', '7.14');
+define('VERSION', '7.15');
 
 /**
  * Core API compatibility.
@@ -1773,22 +1773,37 @@ function watchdog($type, $message, $variables = array(), $severity = WATCHDOG_NO
 }
 
 /**
- * Sets a message which reflects the status of the performed operation.
+ * Sets a message to display to the user.
  *
- * If the function is called with no arguments, this function returns all set
- * messages without clearing them.
+ * Messages are stored in a session variable and displayed in page.tpl.php via
+ * the $messages theme variable.
  *
- * @param $message
- *   The message to be displayed to the user. For consistency with other
- *   messages, it should begin with a capital letter and end with a period.
- * @param $type
- *   The type of the message. One of the following values are possible:
+ * Example usage:
+ * @code
+ * drupal_set_message(t('An error occurred and processing did not complete.'), 'error');
+ * @endcode
+ *
+ * @param string $message
+ *   (optional) The translated message to be displayed to the user. For
+ *   consistency with other messages, it should begin with a capital letter and
+ *   end with a period.
+ * @param string $type
+ *   (optional) The message's type. Defaults to 'status'. These values are
+ *   supported:
  *   - 'status'
  *   - 'warning'
  *   - 'error'
- * @param $repeat
- *   If this is FALSE and the message is already set, then the message won't
- *   be repeated.
+ * @param bool $repeat
+ *   (optional) If this is FALSE and the message is already set, then the
+ *   message won't be repeated. Defaults to TRUE.
+ *
+ * @return array|null
+ *   A multidimensional array with keys corresponding to the set message types.
+ *   The indexed array values of each contain the set messages for that type.
+ *   Or, if there are no messages set, the function returns NULL.
+ *
+ * @see drupal_get_messages()
+ * @see theme_status_messages()
  */
 function drupal_set_message($message = NULL, $type = 'status', $repeat = TRUE) {
   if ($message) {
@@ -2725,7 +2740,7 @@ function request_path() {
     return $path;
   }
 
-  if (isset($_GET['q'])) {
+  if (isset($_GET['q']) && is_string($_GET['q'])) {
     // This is a request with a ?q=foo/bar query string. $_GET['q'] is
     // overwritten in drupal_path_initialize(), but request_path() is called
     // very early in the bootstrap process, so the original value is saved in
@@ -2856,7 +2871,7 @@ function ip_address() {
 }
 
 /**
- * @ingroup schemaapi
+ * @addtogroup schemaapi
  * @{
  */
 
@@ -2978,12 +2993,12 @@ function drupal_get_complete_schema($rebuild = FALSE) {
 }
 
 /**
- * @} End of "ingroup schemaapi".
+ * @} End of "addtogroup schemaapi".
  */
 
 
 /**
- * @ingroup registry
+ * @addtogroup registry
  * @{
  */
 
@@ -3145,7 +3160,7 @@ function registry_update() {
 }
 
 /**
- * @} End of "ingroup registry".
+ * @} End of "addtogroup registry".
  */
 
 /**
diff --git a/includes/common.inc b/includes/common.inc
index 1ba7b8207..dfa9153a2 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -647,20 +647,23 @@ function drupal_encode_path($path) {
  * callback.
  *
  * @param $path
- *   A Drupal path or a full URL.
+ *   (optional) A Drupal path or a full URL, which will be passed to url() to
+ *   compute the redirect for the URL.
  * @param $options
- *   An associative array of additional URL options to pass to url().
+ *   (optional) An associative array of additional URL options to pass to url().
  * @param $http_response_code
- *   Valid values for an actual "goto" as per RFC 2616 section 10.3 are:
- *   - 301 Moved Permanently (the recommended value for most redirects)
- *   - 302 Found (default in Drupal and PHP, sometimes used for spamming search
- *         engines)
- *   - 303 See Other
- *   - 304 Not Modified
- *   - 305 Use Proxy
- *   - 307 Temporary Redirect (alternative to "503 Site Down for Maintenance")
- *   Note: Other values are defined by RFC 2616, but are rarely used and poorly
- *   supported.
+ *   (optional) The HTTP status code to use for the redirection, defaults to
+ *   302. The valid values for 3xx redirection status codes are defined in
+ *   @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3 RFC 2616 @endlink
+ *   and the
+ *   @link http://tools.ietf.org/html/draft-reschke-http-status-308-07 draft for the new HTTP status codes: @endlink
+ *   - 301: Moved Permanently (the recommended value for most redirects).
+ *   - 302: Found (default in Drupal and PHP, sometimes used for spamming search
+ *     engines).
+ *   - 303: See Other.
+ *   - 304: Not Modified.
+ *   - 305: Use Proxy.
+ *   - 307: Temporary Redirect.
  *
  * @see drupal_get_destination()
  * @see url()
@@ -1099,7 +1102,7 @@ function fix_gpc_magic() {
 /**
  * Verifies the syntax of the given e-mail address.
  *
- * Empty e-mail addresses are allowed. See RFC 2822 for details.
+ * See @link http://tools.ietf.org/html/rfc5321 RFC 5321 @endlink for details.
  *
  * @param $mail
  *   A string containing an e-mail address.
@@ -2041,8 +2044,9 @@ function format_username($account) {
  * alternative than url().
  *
  * @param $path
- *   The internal path or external URL being linked to, such as "node/34" or
- *   "http://example.com/foo". A few notes:
+ *   (optional) The internal path or external URL being linked to, such as
+ *   "node/34" or "http://example.com/foo". The default value is equivalent to
+ *   passing in '<front>'. A few notes:
  *   - If you provide a full URL, it will be considered an external URL.
  *   - If you provide only the path (e.g. "node/34"), it will be
  *     considered an internal link. In this case, it should be a system URL,
@@ -2058,7 +2062,8 @@ function format_username($account) {
  *     include them in $path, or use $options['query'] to let this function
  *     URL encode them.
  * @param $options
- *   An associative array of additional options, with the following elements:
+ *   (optional) An associative array of additional options, with the following
+ *   elements:
  *   - 'query': An array of query key/value-pairs (without any URL-encoding) to
  *     append to the URL.
  *   - 'fragment': A fragment identifier (named anchor) to append to the URL.
@@ -5653,8 +5658,9 @@ function drupal_render_page($page) {
  * any children, it is the responsibility of the theme function to render
  * these children. For elements that are not allowed to have any children,
  * e.g. buttons or textfields, the theme function can be used to render the
- * element itself. If #theme is not present and the element has children, they
- * are rendered and concatenated into a string by drupal_render_children().
+ * element itself. If #theme is not present and the element has children, each
+ * child is itself rendered by a call to drupal_render(), and the results are
+ * concatenated.
  *
  * The #theme_wrappers property contains an array of theme functions which will
  * be called, in order, after #theme has run. These can be used to add further
@@ -6216,7 +6222,19 @@ function element_info_property($type, $property_name, $default = NULL) {
 }
 
 /**
- * Function used by uasort to sort structured arrays by weight, without the property weight prefix.
+ * Sorts a structured array by the 'weight' element.
+ *
+ * Note that the sorting is by the 'weight' array element, not by the render
+ * element property '#weight'.
+ *
+ * Callback for uasort() used in various functions.
+ *
+ * @param $a
+ *   First item for comparison. The compared items should be associative arrays
+ *   that optionally include a 'weight' element. For items without a 'weight'
+ *   element, a default value of 0 will be used.
+ * @param $b
+ *   Second item for comparison.
  */
 function drupal_sort_weight($a, $b) {
   $a_weight = (is_array($a) && isset($a['weight'])) ? $a['weight'] : 0;
@@ -6490,7 +6508,7 @@ function drupal_array_set_nested_value(array &$array, array $parents, $value, $f
  *
  * @see drupal_array_set_nested_value()
  */
-function drupal_array_get_nested_value(array &$array, array $parents, &$key_exists = NULL) {
+function &drupal_array_get_nested_value(array &$array, array $parents, &$key_exists = NULL) {
   $ref = &$array;
   foreach ($parents as $parent) {
     if (is_array($ref) && array_key_exists($parent, $ref)) {
@@ -6498,7 +6516,8 @@ function drupal_array_get_nested_value(array &$array, array $parents, &$key_exis
     }
     else {
       $key_exists = FALSE;
-      return NULL;
+      $null = NULL;
+      return $null;
     }
   }
   $key_exists = TRUE;
@@ -6748,7 +6767,7 @@ function drupal_common_theme() {
 }
 
 /**
- * @ingroup schemaapi
+ * @addtogroup schemaapi
  * @{
  */
 
@@ -6896,6 +6915,10 @@ function drupal_schema_fields_sql($table, $prefix = NULL) {
 /**
  * Saves (inserts or updates) a record to the database based upon the schema.
  *
+ * Do not use drupal_write_record() within hook_update_N() functions, since the
+ * database schema cannot be relied upon when a user is running a series of
+ * updates. Instead, use db_insert() or db_update() to save the record.
+ *
  * @param $table
  *   The name of the table; this must be defined by a hook_schema()
  *   implementation.
@@ -7051,7 +7074,7 @@ function drupal_write_record($table, &$record, $primary_keys = array()) {
 }
 
 /**
- * @} End of "ingroup schemaapi".
+ * @} End of "addtogroup schemaapi".
  */
 
 /**
@@ -7774,6 +7797,44 @@ function entity_label($entity_type, $entity) {
   return $label;
 }
 
+/**
+ * Returns the language of an entity.
+ *
+ * @param $entity_type
+ *   The entity type; e.g., 'node' or 'user'.
+ * @param $entity
+ *   The entity for which to get the language.
+ *
+ * @return
+ *   A valid language code or NULL if the entity has no language support.
+ */
+function entity_language($entity_type, $entity) {
+  $info = entity_get_info($entity_type);
+
+  // Invoke the callback to get the language. If there is no callback, try to
+  // get it from a property of the entity, otherwise NULL.
+  if (isset($info['language callback']) && function_exists($info['language callback'])) {
+    $langcode = $info['language callback']($entity_type, $entity);
+  }
+  elseif (!empty($info['entity keys']['language']) && isset($entity->{$info['entity keys']['language']})) {
+    $langcode = $entity->{$info['entity keys']['language']};
+  }
+  else {
+    // The value returned in D8 would be LANGUAGE_NONE, we cannot use it here to
+    // preserve backward compatibility. In fact this function has been
+    // introduced very late in the D7 life cycle, mainly as the proper default
+    // for field_attach_form(). By returning LANGUAGE_NONE when no language
+    // information is available, we would introduce a potentially BC-breaking
+    // API change, since field_attach_form() defaults to the default language
+    // instead of LANGUAGE_NONE. Moreover this allows us to distinguish between
+    // entities that have no language specified from ones that do not have
+    // language support at all.
+    $langcode = NULL;
+  }
+
+  return $langcode;
+}
+
 /**
  * Helper function for attaching field API validation to entity forms.
  */
diff --git a/includes/database/database.inc b/includes/database/database.inc
index 6efe298d2..5bcae67a3 100644
--- a/includes/database/database.inc
+++ b/includes/database/database.inc
@@ -41,7 +41,7 @@
  * $result = db_query_range('SELECT n.nid, n.title, n.created
  *   FROM {node} n WHERE n.uid = :uid', 0, 10, array(':uid' => $uid));
  * foreach ($result as $record) {
- *   // Perform operations on $node->title, etc. here.
+ *   // Perform operations on $record->title, etc. here.
  * }
  * @endcode
  * Curly braces are used around "node" to provide table prefixing via
@@ -988,6 +988,9 @@ abstract class DatabaseConnection extends PDO {
    * @param $name
    *   Optional name of the savepoint.
    *
+   * @return DatabaseTransaction
+   *   A DatabaseTransaction object.
+   *
    * @see DatabaseTransaction
    */
   public function startTransaction($name = '') {
@@ -2669,7 +2672,7 @@ function db_condition($conjunction) {
 
 
 /**
- * @ingroup schemaapi
+ * @addtogroup schemaapi
  * @{
  */
 
@@ -2986,7 +2989,7 @@ function db_change_field($table, $field, $field_new, $spec, $keys_new = array())
 }
 
 /**
- * @} End of "ingroup schemaapi".
+ * @} End of "addtogroup schemaapi".
  */
 
 /**
diff --git a/includes/database/mysql/database.inc b/includes/database/mysql/database.inc
index 7278a2bc8..7ad019e58 100644
--- a/includes/database/mysql/database.inc
+++ b/includes/database/mysql/database.inc
@@ -6,7 +6,7 @@
  */
 
 /**
- * @ingroup database
+ * @addtogroup database
  * @{
  */
 
@@ -198,5 +198,5 @@ class DatabaseConnection_mysql extends DatabaseConnection {
 
 
 /**
- * @} End of "ingroup database".
+ * @} End of "addtogroup database".
  */
diff --git a/includes/database/mysql/query.inc b/includes/database/mysql/query.inc
index 888b6a5a4..2609aba0c 100644
--- a/includes/database/mysql/query.inc
+++ b/includes/database/mysql/query.inc
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * @ingroup database
+ * @addtogroup database
  * @{
  */
 
@@ -103,5 +103,5 @@ class TruncateQuery_mysql extends TruncateQuery {
 }
 
 /**
- * @} End of "ingroup database".
+ * @} End of "addtogroup database".
  */
diff --git a/includes/database/mysql/schema.inc b/includes/database/mysql/schema.inc
index d6aea4d94..949cf4e8a 100644
--- a/includes/database/mysql/schema.inc
+++ b/includes/database/mysql/schema.inc
@@ -7,7 +7,7 @@
 
 
 /**
- * @ingroup schemaapi
+ * @addtogroup schemaapi
  * @{
  */
 
@@ -532,5 +532,5 @@ class DatabaseSchema_mysql extends DatabaseSchema {
 }
 
 /**
- * @} End of "ingroup schemaapi".
+ * @} End of "addtogroup schemaapi".
  */
diff --git a/includes/database/pgsql/database.inc b/includes/database/pgsql/database.inc
index d80b47551..79c16b212 100644
--- a/includes/database/pgsql/database.inc
+++ b/includes/database/pgsql/database.inc
@@ -6,7 +6,7 @@
  */
 
 /**
- * @ingroup database
+ * @addtogroup database
  * @{
  */
 
@@ -208,5 +208,5 @@ class DatabaseConnection_pgsql extends DatabaseConnection {
 }
 
 /**
- * @} End of "ingroup database".
+ * @} End of "addtogroup database".
  */
diff --git a/includes/database/pgsql/select.inc b/includes/database/pgsql/select.inc
index d1d838281..f6a83db7f 100644
--- a/includes/database/pgsql/select.inc
+++ b/includes/database/pgsql/select.inc
@@ -6,7 +6,7 @@
  */
 
 /**
- * @ingroup database
+ * @addtogroup database
  * @{
  */
 
@@ -103,6 +103,6 @@ class SelectQuery_pgsql extends SelectQuery {
 }
 
 /**
- * @} End of "ingroup database".
+ * @} End of "addtogroup database".
  */
 
diff --git a/includes/database/prefetch.inc b/includes/database/prefetch.inc
index 4f2b19d1f..3b36a4e10 100644
--- a/includes/database/prefetch.inc
+++ b/includes/database/prefetch.inc
@@ -9,7 +9,7 @@
  */
 
 /**
- * @ingroup database
+ * @addtogroup database
  * @{
  */
 
@@ -502,6 +502,6 @@ class DatabaseStatementPrefetch implements Iterator, DatabaseStatementInterface
 }
 
 /**
- * @} End of "ingroup database".
+ * @} End of "addtogroup database".
  */
 
diff --git a/includes/database/query.inc b/includes/database/query.inc
index 750aea7a0..612985e02 100644
--- a/includes/database/query.inc
+++ b/includes/database/query.inc
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * @ingroup database
+ * @addtogroup database
  * @{
  */
 
@@ -1955,5 +1955,5 @@ class DatabaseCondition implements QueryConditionInterface, Countable {
 }
 
 /**
- * @} End of "ingroup database".
+ * @} End of "addtogroup database".
  */
diff --git a/includes/database/select.inc b/includes/database/select.inc
index 7e2af85e7..e036904be 100644
--- a/includes/database/select.inc
+++ b/includes/database/select.inc
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * @ingroup database
+ * @addtogroup database
  * @{
  */
 
@@ -1609,5 +1609,5 @@ class SelectQuery extends Query implements SelectQueryInterface {
 }
 
 /**
- * @} End of "ingroup database".
+ * @} End of "addtogroup database".
  */
diff --git a/includes/database/sqlite/database.inc b/includes/database/sqlite/database.inc
index ea91e9143..b302b3e32 100644
--- a/includes/database/sqlite/database.inc
+++ b/includes/database/sqlite/database.inc
@@ -6,7 +6,7 @@
  */
 
 /**
- * @ingroup database
+ * @addtogroup database
  * @{
  */
 
@@ -515,5 +515,5 @@ class DatabaseStatement_sqlite extends DatabaseStatementPrefetch implements Iter
 }
 
 /**
- * @} End of "ingroup database".
+ * @} End of "addtogroup database".
  */
diff --git a/includes/database/sqlite/query.inc b/includes/database/sqlite/query.inc
index 6b8a72f2a..74ff9ba20 100644
--- a/includes/database/sqlite/query.inc
+++ b/includes/database/sqlite/query.inc
@@ -6,7 +6,7 @@
  */
 
 /**
- * @ingroup database
+ * @addtogroup database
  * @{
  */
 
@@ -156,5 +156,5 @@ class TruncateQuery_sqlite extends TruncateQuery {
 }
 
 /**
- * @} End of "ingroup database".
+ * @} End of "addtogroup database".
  */
diff --git a/includes/database/sqlite/select.inc b/includes/database/sqlite/select.inc
index fb926ef04..9037a0e7a 100644
--- a/includes/database/sqlite/select.inc
+++ b/includes/database/sqlite/select.inc
@@ -6,7 +6,7 @@
  */
 
 /**
- * @ingroup database
+ * @addtogroup database
  * @{
  */
 
@@ -21,7 +21,7 @@ class SelectQuery_sqlite extends SelectQuery {
 }
 
 /**
- * @} End of "ingroup database".
+ * @} End of "addtogroup database".
  */
 
 
diff --git a/includes/entity.inc b/includes/entity.inc
index ae7807794..832abe2fd 100644
--- a/includes/entity.inc
+++ b/includes/entity.inc
@@ -634,6 +634,9 @@ class EntityFieldQuery {
 
   /**
    * Adds a condition on field values.
+   * 
+   * Note that entities with empty field values will be excluded from the
+   * EntityFieldQuery results when using this method.
    *
    * @param $field
    *   Either a field name or a field array.
@@ -858,7 +861,9 @@ class EntityFieldQuery {
    * Orders the result set by a given field column.
    *
    * If called multiple times, the query will order by each specified column in
-   * the order this method is called.
+   * the order this method is called. Note that entities with empty field
+   * values will be excluded from the EntityFieldQuery results when using this
+   * method.
    *
    * @param $field
    *   Either a field name or a field array.
@@ -1199,7 +1204,7 @@ class EntityFieldQuery {
     $select_query->addExpression(':entity_type', 'entity_type', array(':entity_type' => $entity_type));
     // Process the property conditions.
     foreach ($this->propertyConditions as $property_condition) {
-      $this->addCondition($select_query, "$base_table." . $property_condition['column'], $property_condition);
+      $this->addCondition($select_query, $base_table . '.' . $property_condition['column'], $property_condition);
     }
     // Process the four possible entity condition.
     // The id field is always present in entity keys.
@@ -1207,7 +1212,7 @@ class EntityFieldQuery {
     $id_map['entity_id'] = $sql_field;
     $select_query->addField($base_table, $sql_field, 'entity_id');
     if (isset($this->entityConditions['entity_id'])) {
-      $this->addCondition($select_query, $sql_field, $this->entityConditions['entity_id']);
+      $this->addCondition($select_query, $base_table . '.' . $sql_field, $this->entityConditions['entity_id']);
     }
 
     // If there is a revision key defined, use it.
@@ -1215,7 +1220,7 @@ class EntityFieldQuery {
       $sql_field = $entity_info['entity keys']['revision'];
       $select_query->addField($base_table, $sql_field, 'revision_id');
       if (isset($this->entityConditions['revision_id'])) {
-        $this->addCondition($select_query, $sql_field, $this->entityConditions['revision_id']);
+        $this->addCondition($select_query, $base_table . '.' . $sql_field, $this->entityConditions['revision_id']);
       }
     }
     else {
@@ -1240,7 +1245,13 @@ class EntityFieldQuery {
     }
     $id_map['bundle'] = $sql_field;
     if (isset($this->entityConditions['bundle'])) {
-      $this->addCondition($select_query, $sql_field, $this->entityConditions['bundle'], $having);
+      if (!empty($entity_info['entity keys']['bundle'])) {
+        $this->addCondition($select_query, $base_table . '.' . $sql_field, $this->entityConditions['bundle'], $having);
+      }
+      else {
+        // This entity has no bundle, so invalidate the query.
+        $select_query->where('1 = 0');
+      }
     }
 
     // Order the query.
@@ -1253,7 +1264,7 @@ class EntityFieldQuery {
         $select_query->orderBy($id_map[$key], $order['direction']);
       }
       elseif ($order['type'] == 'property') {
-        $select_query->orderBy("$base_table." . $order['specifier'], $order['direction']);
+        $select_query->orderBy($base_table . '.' . $order['specifier'], $order['direction']);
       }
     }
 
diff --git a/includes/errors.inc b/includes/errors.inc
index f62bf06a5..9d0df0544 100644
--- a/includes/errors.inc
+++ b/includes/errors.inc
@@ -230,8 +230,10 @@ function _drupal_log_error($error, $fatal = FALSE) {
 
   if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
     if ($fatal) {
-      // When called from JavaScript, simply output the error message.
-      print t('%type: !message in %function (line %line of %file).', $error);
+      if (error_displayable($error)) {
+        // When called from JavaScript, simply output the error message.
+        print t('%type: !message in %function (line %line of %file).', $error);
+      }
       exit;
     }
   }
diff --git a/includes/form.inc b/includes/form.inc
index 3ef32ab41..d7350b3e2 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -164,6 +164,8 @@ function drupal_get_form($form_id) {
  *       automatically loaded by form_get_cache(). By default the current menu
  *       router item's 'file' definition is added, if any. Use
  *       form_load_include() to add include files from a form constructor.
+ *     - form_id: Identification of the primary form being constructed and
+ *       processed.
  *     - base_form_id: Identification for a base form, as declared in a
  *       hook_forms() implementation.
  *   - rebuild_info: Internal. Similar to 'build_info', but pertaining to
@@ -572,7 +574,7 @@ function form_state_keys_no_cache() {
 }
 
 /**
- * Ensures an include file is loaded loaded whenever the form is processed.
+ * Ensures an include file is loaded whenever the form is processed.
  *
  * Example:
  * @code
@@ -721,6 +723,9 @@ function drupal_form_submit($form_id, &$form_state) {
 function drupal_retrieve_form($form_id, &$form_state) {
   $forms = &drupal_static(__FUNCTION__);
 
+  // Record the $form_id.
+  $form_state['build_info']['form_id'] = $form_id;
+
   // Record the filepath of the include file containing the original form, so
   // the form builder callbacks can be loaded when the form is being rebuilt
   // from cache on a different path (such as 'system/ajax'). See
@@ -977,6 +982,10 @@ function drupal_prepare_form($form_id, &$form, &$form_state) {
     '#value' => $form['#build_id'],
     '#id' => $form['#build_id'],
     '#name' => 'form_build_id',
+    // Form processing and validation requires this value, so ensure the
+    // submitted form value appears literally, regardless of custom #tree
+    // and #parents being set elsewhere.
+    '#parents' => array('form_build_id'),
   );
 
   // Add a token, based on either #token or form_id, to any form displayed to
@@ -1000,6 +1009,10 @@ function drupal_prepare_form($form_id, &$form, &$form_state) {
         '#id' => drupal_html_id('edit-' . $form_id . '-form-token'),
         '#type' => 'token',
         '#default_value' => drupal_get_token($form['#token']),
+        // Form processing and validation requires this value, so ensure the
+        // submitted form value appears literally, regardless of custom #tree
+        // and #parents being set elsewhere.
+        '#parents' => array('form_token'),
       );
     }
   }
@@ -1009,6 +1022,10 @@ function drupal_prepare_form($form_id, &$form, &$form_state) {
       '#type' => 'hidden',
       '#value' => $form_id,
       '#id' => drupal_html_id("edit-$form_id"),
+      // Form processing and validation requires this value, so ensure the
+      // submitted form value appears literally, regardless of custom #tree
+      // and #parents being set elsewhere.
+      '#parents' => array('form_id'),
     );
   }
   if (!isset($form['#id'])) {
@@ -1086,7 +1103,7 @@ function drupal_prepare_form($form_id, &$form, &$form_state) {
  *   A keyed array containing the current state of the form. The current
  *   user-submitted data is stored in $form_state['values'], though
  *   form validation functions are passed an explicit copy of the
- *   values for the sake of simplicity. Validation handlers can also
+ *   values for the sake of simplicity. Validation handlers can also use
  *   $form_state to pass information on to submit handlers. For example:
  *     $form_state['data_for_submission'] = $data;
  *   This technique is useful when validation requires file parsing,
@@ -2149,12 +2166,12 @@ function form_state_values_clean(&$form_state) {
     // $form_state['values']['foo']['bar'], which is the level where we can
     // unset 'baz' (that is stored in $last_parent).
     $parents = $button['#parents'];
-    $values = &$form_state['values'];
     $last_parent = array_pop($parents);
-    foreach ($parents as $parent) {
-      $values = &$values[$parent];
+    $key_exists = NULL;
+    $values = &drupal_array_get_nested_value($form_state['values'], $parents, $key_exists);
+    if ($key_exists && is_array($values)) {
+      unset($values[$last_parent]);
     }
-    unset($values[$last_parent]);
   }
 }
 
@@ -2339,30 +2356,27 @@ function form_type_tableselect_value($element, $input = FALSE) {
  */
 function form_type_radios_value(&$element, $input = FALSE) {
   if ($input !== FALSE) {
-    // There may not be a submitted value for multiple radio buttons, if none of
-    // the options was checked by default. If there is no submitted input value
-    // for this element (NULL), _form_builder_handle_input_element()
-    // automatically attempts to use the #default_value (if set) or an empty
-    // string (''). However, an empty string would fail validation in
-    // _form_validate(), in case it is not contained in the list of allowed
-    // values in #options.
-    if (!isset($input)) {
-      // Signify a garbage value to disable the #default_value handling and take
-      // over NULL as #value.
-      $element['#has_garbage_value'] = TRUE;
-      // There was a user submission so validation is a must. If this element is
-      // #required, then an appropriate error message will be output. While an
-      // optional #type 'radios' does not necessarily make sense from a user
-      // interaction perspective, there may be use-cases for that and it is not
-      // the job of Form API to artificially limit possibilities.
+    // When there's user input (including NULL), return it as the value.
+    // However, if NULL is submitted, _form_builder_handle_input_element() will
+    // apply the default value, and we want that validated against #options
+    // unless it's empty. (An empty #default_value, such as NULL or FALSE, can
+    // be used to indicate that no radio button is selected by default.)
+    if (!isset($input) && !empty($element['#default_value'])) {
       $element['#needs_validation'] = TRUE;
     }
-    // The value stays the same, but the flags above will ensure it is
-    // processed properly.
     return $input;
   }
-  elseif (isset($element['#default_value'])) {
-    return $element['#default_value'];
+  else {
+    // For default value handling, simply return #default_value. Additionally,
+    // for a NULL default value, set #has_garbage_value to prevent
+    // _form_builder_handle_input_element() converting the NULL to an empty
+    // string, so that code can distinguish between nothing selected and the
+    // selection of a radio button whose value is an empty string.
+    $value = isset($element['#default_value']) ? $element['#default_value'] : NULL;
+    if (!isset($value)) {
+      $element['#has_garbage_value'] = TRUE;
+    }
+    return $value;
   }
 }
 
diff --git a/includes/graph.inc b/includes/graph.inc
index 9ef86a145..35e683057 100644
--- a/includes/graph.inc
+++ b/includes/graph.inc
@@ -2,12 +2,12 @@
 
 /**
  * @file
- * Directed acyclic graph functions.
+ * Directed acyclic graph manipulation.
  */
 
 
 /**
- * Performs a depth-first sort on a directed acyclic graph.
+ * Performs a depth-first search and sort on a directed acyclic graph.
  *
  * @param $graph
  *   A three dimensional associated array, with the first keys being the names
@@ -52,7 +52,7 @@ function drupal_depth_first_search(&$graph) {
     // The components of the graph.
     'components' => array(),
   );
-  // Perform the actual sort.
+  // Perform the actual search.
   foreach ($graph as $start => $data) {
     _drupal_depth_first_search($graph, $state, $start);
   }
@@ -72,7 +72,7 @@ function drupal_depth_first_search(&$graph) {
 }
 
 /**
- * Performs a depth-first sort on a graph.
+ * Performs a depth-first search on a graph.
  *
  * @param $graph
  *   A three dimensional associated graph array.
diff --git a/includes/locale.inc b/includes/locale.inc
index 7fb8d6424..c168da0a7 100644
--- a/includes/locale.inc
+++ b/includes/locale.inc
@@ -279,6 +279,12 @@ function locale_language_from_url($languages) {
       break;
 
     case LOCALE_LANGUAGE_NEGOTIATION_URL_DOMAIN:
+      // Get only the host, not the port.
+      $http_host= $_SERVER['HTTP_HOST'];
+      if (strpos($http_host, ':') !== FALSE) {
+        $http_host_tmp = explode(':', $http_host);
+        $http_host = current($http_host_tmp);
+      }
       foreach ($languages as $language) {
         // Skip check if the language doesn't have a domain.
         if ($language->domain) {
@@ -286,7 +292,7 @@ function locale_language_from_url($languages) {
           // Remove protocol and add http:// so parse_url works
           $host = 'http://' . str_replace(array('http://', 'https://'), '', $language->domain);
           $host = parse_url($host, PHP_URL_HOST);
-          if ($_SERVER['HTTP_HOST'] == $host) {
+          if ($http_host == $host) {
             $language_url = $language->language;
             break;
           }
@@ -1854,7 +1860,16 @@ function _locale_translate_seek() {
   }
 
   $sql_query = db_select('locales_source', 's');
-  $sql_query->leftJoin('locales_target', 't', 't.lid = s.lid');
+
+  $limit_language = NULL;
+  if ($query['language'] != 'en' && $query['language'] != 'all') {
+    $sql_query->leftJoin('locales_target', 't', "t.lid = s.lid AND t.language = :langcode", array(':langcode' => $query['language']));
+    $limit_language = $query['language'];
+  }
+  else {
+    $sql_query->leftJoin('locales_target', 't', 't.lid = s.lid');
+  }
+
   $sql_query->fields('s', array('source', 'location', 'context', 'lid', 'textgroup'));
   $sql_query->fields('t', array('translation', 'language'));
 
@@ -1883,12 +1898,6 @@ function _locale_translate_seek() {
       break;
   }
 
-  $limit_language = NULL;
-  if ($query['language'] != 'en' && $query['language'] != 'all') {
-    $sql_query->condition('language', $query['language']);
-    $limit_language = $query['language'];
-  }
-
   // Add a condition on the text group.
   if (!empty($query['group']) && $query['group'] != 'all') {
     $sql_query->condition('s.textgroup', $query['group']);
diff --git a/includes/module.inc b/includes/module.inc
index 500bc5ebc..28bca2350 100644
--- a/includes/module.inc
+++ b/includes/module.inc
@@ -178,6 +178,33 @@ function system_list($type) {
           $lists['filepaths'][] = array('type' => $record->type, 'name' => $record->name, 'filepath' => $record->filename);
         }
       }
+      foreach ($lists['theme'] as $key => $theme) {
+        if (!empty($theme->info['base theme'])) {
+          // Make a list of the theme's base themes.
+          $lists['theme'][$key]->base_themes = drupal_find_base_themes($lists['theme'], $key);
+          // Don't proceed if there was a problem with the root base theme.
+          if (!current($lists['theme'][$key]->base_themes)) {
+            continue;
+          }
+          // Determine the root base theme.
+          $base_key = key($lists['theme'][$key]->base_themes);
+          // Add to the list of sub-themes for each of the theme's base themes.
+          foreach (array_keys($lists['theme'][$key]->base_themes) as $base_theme) {
+            $lists['theme'][$base_theme]->sub_themes[$key] = $lists['theme'][$key]->info['name'];
+          }
+          // Add the base theme's theme engine info.
+          $lists['theme'][$key]->info['engine'] = isset($lists['theme'][$base_key]->info['engine']) ? $lists['theme'][$base_key]->info['engine'] : 'theme';
+        }
+        else {
+          // A plain theme is its own engine.
+          $base_key = $key;
+          if (!isset($lists['theme'][$key]->info['engine'])) {
+            $lists['theme'][$key]->info['engine'] = 'theme';
+          }
+        }
+        // Set the theme engine prefix.
+        $lists['theme'][$key]->prefix = ($lists['theme'][$key]->info['engine'] == 'theme') ? $base_key : $lists['theme'][$key]->info['engine'];
+      }
       cache_set('system_list', $lists, 'cache_bootstrap');
     }
     // To avoid a separate database lookup for the filepath, prime the
diff --git a/includes/theme.inc b/includes/theme.inc
index 51e1075ca..c4b712271 100644
--- a/includes/theme.inc
+++ b/includes/theme.inc
@@ -734,21 +734,40 @@ function _theme_build_registry($theme, $base_theme, $theme_engine) {
  *
  * @return
  *   An associative array of the currently available themes. The keys are the
- *   names of the themes and the values are objects having the following
+ *   themes' machine names and the values are objects having the following
  *   properties:
- *   - 'filename': The name of the .info file.
- *   - 'name': The name of the theme.
- *   - 'status': 1 for enabled, 0 for disabled themes.
- *   - 'info': The contents of the .info file.
- *   - 'stylesheets': A two dimensional array, using the first key for the
- *     'media' attribute (e.g. 'all'), the second for the name of the file
- *     (e.g. style.css). The value is a complete filepath
- *     (e.g. themes/bartik/style.css).
- *   - 'scripts': An associative array of JavaScripts, using the filename as key
- *     and the complete filepath as value.
- *   - 'engine': The name of the theme engine.
- *   - 'base theme': The name of the base theme.
- */
+ *   - filename: The filepath and name of the .info file.
+ *   - name: The machine name of the theme.
+ *   - status: 1 for enabled, 0 for disabled themes.
+ *   - info: The contents of the .info file.
+ *   - stylesheets: A two dimensional array, using the first key for the
+ *     media attribute (e.g. 'all'), the second for the name of the file
+ *     (e.g. style.css). The value is a complete filepath (e.g.
+ *     themes/bartik/style.css). Not set if no stylesheets are defined in the
+ *     .info file.
+ *   - scripts: An associative array of JavaScripts, using the filename as key
+ *     and the complete filepath as value. Not set if no scripts are defined in
+ *     the .info file.
+ *   - prefix: The base theme engine prefix.
+ *   - engine: The machine name of the theme engine.
+ *   - base_theme: If this is a sub-theme, the machine name of the base theme
+ *     defined in the .info file. Otherwise, the element is not set.
+ *   - base_themes: If this is a sub-theme, an associative array of the
+ *     base-theme ancestors of this theme, starting with this theme's base
+ *     theme, then the base theme's own base theme, etc. Each entry has an
+ *     array key equal to the theme's machine name, and a value equal to the
+ *     human-readable theme name; if a theme with matching machine name does
+ *     not exist in the system, the value will instead be NULL (and since the
+ *     system would not know whether that theme itself has a base theme, that
+ *     will end the array of base themes). This is not set if the theme is not
+ *     a sub-theme.
+ *   - sub_themes: An associative array of themes on the system that are
+ *     either direct sub-themes (that is, they declare this theme to be
+ *     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. 
+*/
 function list_themes($refresh = FALSE) {
   $list = &drupal_static(__FUNCTION__, array());
 
@@ -803,6 +822,47 @@ function list_themes($refresh = FALSE) {
   return $list;
 }
 
+/**
+ * Find all the base themes for the specified theme.
+ *
+ * Themes can inherit templates and function implementations from earlier themes.
+ *
+ * @param $themes
+ *   An array of available themes.
+ * @param $key
+ *   The name of the theme whose base we are looking for.
+ * @param $used_keys
+ *   A recursion parameter preventing endless loops.
+ * @return
+ *   Returns an array of all of the theme's ancestors; the first element's value
+ *   will be NULL if an error occurred.
+ */
+function drupal_find_base_themes($themes, $key, $used_keys = array()) {
+  $base_key = $themes[$key]->info['base theme'];
+  // Does the base theme exist?
+  if (!isset($themes[$base_key])) {
+    return array($base_key => NULL);
+  }
+
+  $current_base_theme = array($base_key => $themes[$base_key]->info['name']);
+
+  // Is the base theme itself a child of another theme?
+  if (isset($themes[$base_key]->info['base theme'])) {
+    // Do we already know the base themes of this theme?
+    if (isset($themes[$base_key]->base_themes)) {
+      return $themes[$base_key]->base_themes + $current_base_theme;
+    }
+    // Prevent loops.
+    if (!empty($used_keys[$base_key])) {
+      return array($base_key => NULL);
+    }
+    $used_keys[$base_key] = TRUE;
+    return drupal_find_base_themes($themes, $base_key, $used_keys) + $current_base_theme;
+  }
+  // If we get here, then this is our parent theme.
+  return $current_base_theme;
+}
+
 /**
  * Generates themed output.
  *
@@ -811,11 +871,28 @@ function list_themes($refresh = FALSE) {
  * @link themeable theme function or template @endlink, by checking the theme
  * registry.
  *
- * The first argument to this function is the name of the theme hook. For
- * instance, to theme a table, the theme hook name is 'table'. By default, this
- * theme hook could be implemented by a function called 'theme_table' or a
- * template file called 'table.tpl.php', but hook_theme() can override the
- * default function or template name.
+ * Most commonly, the first argument to this function is the name of the theme
+ * hook. For instance, to theme a taxonomy term, the theme hook name is
+ * 'taxonomy_term'. Modules register theme hooks within a hook_theme()
+ * implementation and provide a default implementation via a function named
+ * theme_HOOK() (e.g., theme_taxonomy_term()) or via a template file named
+ * according to the value of the 'template' key registered with the theme hook
+ * (see hook_theme() for details). Default templates are implemented with the
+ * PHPTemplate rendering engine and are named the same as the theme hook, with
+ * underscores changed to hyphens, so for the 'taxonomy_term' theme hook, the
+ * default template is 'taxonomy-term.tpl.php'.
+ *
+ * Themes may also register new theme hooks within a hook_theme()
+ * implementation, but it is more common for themes to override default
+ * implementations provided by modules than to register entirely new theme
+ * hooks. Themes can override a default implementation by implementing a
+ * function named THEME_HOOK() (for example, the 'bartik' theme overrides the
+ * default implementation of the 'menu_tree' theme hook by implementing a
+ * bartik_menu_tree() function), or by adding a template file within its folder
+ * structure that follows the template naming structure used by the theme's
+ * rendering engine (for example, since the Bartik theme uses the PHPTemplate
+ * rendering engine, it overrides the default implementation of the 'page' theme
+ * hook by containing a 'page.tpl.php' file within its folder structure).
  *
  * If the implementation is a template file, several functions are called
  * before the template file is invoked, to modify the $variables array. These
@@ -824,42 +901,44 @@ function list_themes($refresh = FALSE) {
  * 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.
- * - template_preprocess_HOOK(&$variables): Should be implemented by
- *   the module that registers the theme hook, to set up default 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.
  * - ENGINE_engine_preprocess(&$variables, $hook): Allows the theme engine to
- *   set necessary variables for all theme hooks.
+ *   set necessary variables for all theme hooks with template implementations.
  * - ENGINE_engine_preprocess_HOOK(&$variables): Allows the theme engine to set
  *   necessary variables for the particular theme hook.
  * - THEME_preprocess(&$variables, $hook): Allows the theme to set necessary
- *   variables for all theme hooks.
+ *   variables for all theme hooks with template implementations.
  * - THEME_preprocess_HOOK(&$variables): Allows the theme to set necessary
  *   variables specific to the particular theme hook.
- * - template_process(&$variables, $hook): Creates a default set of variables
- *   for all theme hooks.
- * - template_process_HOOK(&$variables): This is the first processor specific
- *   to the theme hook; it should be implemented by the module that registers
- *   it.
+ * - template_process(&$variables, $hook): Creates an additional set of default
+ *   variables for all theme hooks with template implementations. The variables
+ *   created in this function are derived from ones created by
+ *   template_preprocess(), but potentially altered by the other preprocess
+ *   functions listed above. For example, any preprocess function can add to or
+ *   modify the $variables['attributes_array'] variable, and after all of them
+ *   have finished executing, template_process() flattens it into a
+ *   $variables['attributes'] string for convenient use by templates.
+ * - template_process_HOOK(&$variables): Should be implemented by the module
+ *   that registers the theme hook, if it needs to perform additional variable
+ *   processing after all preprocess functions have finished.
  * - MODULE_process(&$variables, $hook): hook_process() is invoked on all
  *   implementing modules.
  * - MODULE_process_HOOK(&$variables): hook_process_HOOK() is invoked on
  *   on all implementing modules, so that modules that didn't define the theme
  *   hook can alter the variables.
- * - ENGINE_engine_process(&$variables, $hook): Allows the theme engine to set
- *   necessary variables for all theme hooks.
- * - ENGINE_engine_process_HOOK(&$variables): Allows the theme engine to set
- *   necessary variables for the particular theme hook.
- * - ENGINE_process(&$variables, $hook): Allows the theme engine to process the
- *   variables.
- * - ENGINE_process_HOOK(&$variables): Allows the theme engine to process the
- *   variables specific to the theme hook.
+ * - ENGINE_engine_process(&$variables, $hook): Allows the theme engine to
+ *   process variables for all theme hooks with template implementations.
+ * - ENGINE_engine_process_HOOK(&$variables): Allows the theme engine to process
+ *   the variables specific to the theme hook.
  * - THEME_process(&$variables, $hook):  Allows the theme to process the
- *   variables.
+ *   variables for all theme hooks with template implementations.
  * - THEME_process_HOOK(&$variables):  Allows the theme to process the
  *   variables specific to the theme hook.
  *
@@ -911,6 +990,9 @@ function list_themes($refresh = FALSE) {
  *   An HTML string representing the themed output.
  *
  * @see themeable
+ * @see hook_theme()
+ * @see template_preprocess()
+ * @see template_process()
  */
 function theme($hook, $variables = array()) {
   // If called before all modules are loaded, we do not necessarily have a full
@@ -1473,7 +1555,7 @@ function theme_disable($theme_list) {
 }
 
 /**
- * @ingroup themeable
+ * @addtogroup themeable
  * @{
  */
 
@@ -2172,7 +2254,7 @@ function theme_indentation($variables) {
 }
 
 /**
- * @} End of "ingroup themeable".
+ * @} End of "addtogroup themeable".
  */
 
 /**
@@ -2218,11 +2300,15 @@ function _theme_table_cell($cell, $header = FALSE) {
 
 /**
  * Adds a default set of helper variables for variable processors and templates.
- * This comes in before any other preprocess function which makes it possible to
- * be used in default theme implementations (non-overridden theme functions).
  *
- * For more detailed information, see theme().
+ * This function is called for theme hooks implemented as templates only, not
+ * for theme hooks implemented as functions. This preprocess function is the
+ * first in the sequence of preprocessing and processing functions that is
+ * called when preparing variables for a template. See theme() for more details
+ * about the full sequence.
  *
+ * @see theme()
+ * @see template_process()
  */
 function template_preprocess(&$variables, $hook) {
   global $user;
@@ -2299,10 +2385,19 @@ function _template_preprocess_default_variables() {
 }
 
 /**
- * A default process function used to alter variables as late as possible.
+ * Adds helper variables derived from variables defined during preprocessing.
  *
- * For more detailed information, see theme().
+ * When preparing variables for a theme hook implementation, all 'preprocess'
+ * functions run first, then all 'process' functions (see theme() for details
+ * about the full sequence).
  *
+ * This function serializes array variables manipulated during the preprocessing
+ * phase into strings for convenient use by templates. As with
+ * template_preprocess(), this function does not get called for theme hooks
+ * implemented as functions.
+ *
+ * @see theme()
+ * @see template_preprocess()
  */
 function template_process(&$variables, $hook) {
   // Flatten out classes.
diff --git a/includes/update.inc b/includes/update.inc
index 24001a085..d8fec64df 100644
--- a/includes/update.inc
+++ b/includes/update.inc
@@ -1488,5 +1488,5 @@ function update_retrieve_dependencies() {
  */
 
 /**
- * @} End of "defgroup update-api-6.x-to-7.x"
+ * @} End of "defgroup update-api-6.x-to-7.x".
  */
diff --git a/misc/autocomplete.js b/misc/autocomplete.js
index 267d4b79b..8f7ac6011 100644
--- a/misc/autocomplete.js
+++ b/misc/autocomplete.js
@@ -99,10 +99,12 @@ Drupal.jsAC.prototype.onkeyup = function (input, e) {
       return true;
 
     default: // All other keys.
-      if (input.value.length > 0)
+      if (input.value.length > 0 && !input.readOnly) {
         this.populatePopup();
-      else
+      }
+      else {
         this.hidePopup(e.keyCode);
+      }
       return true;
   }
 };
diff --git a/misc/states.js b/misc/states.js
index 00eeba17b..594f8187b 100644
--- a/misc/states.js
+++ b/misc/states.js
@@ -16,10 +16,11 @@ var states = Drupal.states = {
  */
 Drupal.behaviors.states = {
   attach: function (context, settings) {
+    var $context = $(context);
     for (var selector in settings.states) {
       for (var state in settings.states[selector]) {
         new states.Dependent({
-          element: $(selector),
+          element: $context.find(selector),
           state: states.State.sanitize(state),
           constraints: settings.states[selector][state]
         });
diff --git a/misc/tableselect.js b/misc/tableselect.js
index 5a88ac20c..fee63a9fd 100644
--- a/misc/tableselect.js
+++ b/misc/tableselect.js
@@ -17,7 +17,8 @@ Drupal.tableSelect = function () {
   var table = this, checkboxes, lastChecked;
   var strings = { 'selectAll': Drupal.t('Select all rows in this table'), 'selectNone': Drupal.t('Deselect all rows in this table') };
   var updateSelectAll = function (state) {
-    $('th.select-all input:checkbox', table).each(function () {
+    // Update table's select-all checkbox (and sticky header's if available).
+    $(table).prev('table.sticky-header').andSelf().find('th.select-all input:checkbox').each(function() {
       $(this).attr('title', state ? strings.selectNone : strings.selectAll);
       this.checked = state;
     });
diff --git a/modules/aggregator/aggregator.info b/modules/aggregator/aggregator.info
index 4ffccff46..75fe82b95 100644
--- a/modules/aggregator/aggregator.info
+++ b/modules/aggregator/aggregator.info
@@ -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 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/aggregator/tests/aggregator_test.info b/modules/aggregator/tests/aggregator_test.info
index 3cf09c5d2..29baa019d 100644
--- a/modules/aggregator/tests/aggregator_test.info
+++ b/modules/aggregator/tests/aggregator_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/block/block.info b/modules/block/block.info
index 10f3ede51..386997798 100644
--- a/modules/block/block.info
+++ b/modules/block/block.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = block.test
 configure = admin/structure/block
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/block/block.install b/modules/block/block.install
index b2ab477d9..a78c885e7 100644
--- a/modules/block/block.install
+++ b/modules/block/block.install
@@ -456,6 +456,15 @@ function block_update_7007() {
   ));
 }
 
+/**
+ * @} End of "addtogroup updates-6.x-to-7.x".
+ */
+
+/**
+ * @addtogroup updates-7.x-extra
+ * @{
+ */
+
 /**
  * Update database to match Drupal 7 schema.
  */
@@ -464,5 +473,5 @@ function block_update_7008() {
 }
 
 /**
- * @} End of "addtogroup updates-6.x-to-7.x"
+ * @} End of "addtogroup updates-7.x-extra".
  */
diff --git a/modules/block/block.test b/modules/block/block.test
index cdd0d4589..8e6e47042 100644
--- a/modules/block/block.test
+++ b/modules/block/block.test
@@ -97,7 +97,7 @@ class BlockTestCase extends DrupalWebTestCase {
 
     // Set visibility only for authenticated users, to verify delete functionality.
     $edit = array();
-    $edit['roles[2]'] = TRUE;
+    $edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'] = TRUE;
     $this->drupalPost('admin/structure/block/manage/block/' . $bid . '/configure', $edit, t('Save block'));
 
     // Delete the created custom block & verify that it's been deleted and no longer appearing on the page.
@@ -171,7 +171,7 @@ class BlockTestCase extends DrupalWebTestCase {
     // authenticated users.
     $edit = array();
     $edit['pages'] = 'user*';
-    $edit['roles[2]'] = TRUE;
+    $edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'] = TRUE;
     $this->drupalPost('admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', $edit, t('Save block'));
 
     // Move block to the first sidebar.
diff --git a/modules/block/tests/block_test.info b/modules/block/tests/block_test.info
index 2ea89b0bc..8a34798ce 100644
--- a/modules/block/tests/block_test.info
+++ b/modules/block/tests/block_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/block/tests/themes/block_test_theme/block_test_theme.info b/modules/block/tests/themes/block_test_theme/block_test_theme.info
index bcf507f12..b7381ae79 100644
--- a/modules/block/tests/themes/block_test_theme/block_test_theme.info
+++ b/modules/block/tests/themes/block_test_theme/block_test_theme.info
@@ -13,8 +13,8 @@ regions[footer] = Footer
 regions[highlighted] = Highlighted
 regions[help] = Help
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/blog/blog.info b/modules/blog/blog.info
index ce4ef4a90..1ff2214fe 100644
--- a/modules/blog/blog.info
+++ b/modules/blog/blog.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 files[] = blog.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/book/book.info b/modules/book/book.info
index 2af6a01d8..166521794 100644
--- a/modules/book/book.info
+++ b/modules/book/book.info
@@ -7,8 +7,8 @@ files[] = book.test
 configure = admin/content/book/settings
 stylesheets[all][] = book.css
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/book/book.module b/modules/book/book.module
index 61061f011..1fb0c0b11 100644
--- a/modules/book/book.module
+++ b/modules/book/book.module
@@ -213,7 +213,17 @@ function _book_outline_access($node) {
  * @see book_menu()
  */
 function _book_outline_remove_access($node) {
-  return isset($node->book) && ($node->book['bid'] != $node->nid) && _book_outline_access($node);
+  return _book_node_is_removable($node) && _book_outline_access($node);
+}
+
+/**
+ * Determines if a node can be removed from the book.
+ *
+ * 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.
+ */
+function _book_node_is_removable($node) {
+  return (!empty($node->book['bid']) && (($node->book['bid'] != $node->nid) || !$node->book['has_children']));
 }
 
 /**
@@ -518,13 +528,12 @@ function _book_add_form_elements(&$form, &$form_state, $node) {
     '#collapsed' => TRUE,
     '#group' => 'additional_settings',
     '#attributes' => array(
-      'class' => array('book-form'),
+      'class' => array('book-outline-form'),
     ),
     '#attached' => array(
       'js' => array(drupal_get_path('module', 'book') . '/book.js'),
     ),
     '#tree' => TRUE,
-    '#attributes' => array('class' => array('book-outline-form')),
   );
   foreach (array('menu_name', 'mlid', 'nid', 'router_path', 'has_children', 'options', 'module', 'original_bid', 'parent_depth_limit') as $key) {
     $form['book'][$key] = array(
diff --git a/modules/book/book.pages.inc b/modules/book/book.pages.inc
index 5a05c9f1d..583eb7a81 100644
--- a/modules/book/book.pages.inc
+++ b/modules/book/book.pages.inc
@@ -137,7 +137,7 @@ function book_outline_form($form, &$form_state, $node) {
   $form['remove'] = array(
     '#type' => 'submit',
     '#value' => t('Remove from book outline'),
-    '#access' => $node->nid != $node->book['bid'] && $node->book['bid'],
+    '#access' => _book_node_is_removable($node),
     '#weight' => 20,
     '#submit' => array('book_remove_button_submit'),
   );
@@ -216,8 +216,7 @@ function book_remove_form($form, &$form_state, $node) {
  */
 function book_remove_form_submit($form, &$form_state) {
   $node = $form['#node'];
-  if ($node->nid != $node->book['bid']) {
-    // Only allowed when this is not a book (top-level page).
+  if (_book_node_is_removable($node)) {
     menu_link_delete($node->book['mlid']);
     db_delete('book')
       ->condition('nid', $node->nid)
diff --git a/modules/book/book.test b/modules/book/book.test
index 6c351b8ec..d1f527387 100644
--- a/modules/book/book.test
+++ b/modules/book/book.test
@@ -32,7 +32,7 @@ class BookTestCase extends DrupalWebTestCase {
     // Create users.
     $this->book_author = $this->drupalCreateUser(array('create new books', 'create book content', 'edit own book content', 'add content to books'));
     $this->web_user = $this->drupalCreateUser(array('access printer-friendly version', 'node test view'));
-    $this->admin_user = $this->drupalCreateUser(array('create new books', 'create book content', 'edit own book content', 'add content to books', 'administer blocks', 'administer permissions'));
+    $this->admin_user = $this->drupalCreateUser(array('create new books', 'create book content', 'edit own book content', 'add content to books', 'administer blocks', 'administer permissions', 'administer book outlines', 'node test view'));
   }
 
   /**
@@ -279,8 +279,8 @@ class BookTestCase extends DrupalWebTestCase {
 
      // Give anonymous users the permission 'node test view'.
      $edit = array();
-     $edit['1[node test view]'] = TRUE;
-     $this->drupalPost('admin/people/permissions/1', $edit, t('Save permissions'));
+     $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."));
 
     // Test correct display of the block.
@@ -315,8 +315,8 @@ class BookTestCase extends DrupalWebTestCase {
 
      // Give anonymous users the permission 'node test view'.
      $edit = array();
-     $edit['1[node test view]'] = TRUE;
-     $this->drupalPost('admin/people/permissions/1', $edit, t('Save permissions'));
+     $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.'));
 
      // Create a book.
@@ -332,4 +332,29 @@ class BookTestCase extends DrupalWebTestCase {
      $this->drupalGet('node/' . $this->book->nid);
      $this->assertText($block_title, t('Book navigation block is displayed to anonymous users.'));
    }
+
+  /**
+   * Tests the access for deleting top-level book nodes.
+   */
+   function testBookDelete() {
+     $nodes = $this->createBook();
+     $this->drupalLogin($this->admin_user);
+     $edit = array();
+
+     // 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->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.'));
+
+     // Delete all child book nodes and retest top-level node deletion.
+     foreach ($nodes as $node) {
+       $nids[] = $node->nid;
+     }
+     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.'));
+   }
 }
diff --git a/modules/color/color.info b/modules/color/color.info
index dd13c03a7..5e4912302 100644
--- a/modules/color/color.info
+++ b/modules/color/color.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 files[] = color.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/color/color.install b/modules/color/color.install
index 2a6b9cdd1..3a9aea355 100644
--- a/modules/color/color.install
+++ b/modules/color/color.install
@@ -41,6 +41,11 @@ function color_requirements($phase) {
   return $requirements;
 }
 
+/**
+ * @addtogroup updates-7.x-extra
+ * @{
+ */
+
 /**
  * Warn site administrator if unsafe CSS color codes are found in the database.
  */
@@ -55,3 +60,7 @@ function color_update_7001() {
     }
   }
 }
+
+/**
+ * @} End of "addtogroup updates-7.x-extra".
+ */
diff --git a/modules/comment/comment.info b/modules/comment/comment.info
index f6c17f96a..a6ca0456a 100644
--- a/modules/comment/comment.info
+++ b/modules/comment/comment.info
@@ -9,8 +9,8 @@ files[] = comment.test
 configure = admin/content/comment
 stylesheets[all][] = comment.css
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/comment/comment.install b/modules/comment/comment.install
index 7312e2a31..e4da58f38 100644
--- a/modules/comment/comment.install
+++ b/modules/comment/comment.install
@@ -344,6 +344,15 @@ function comment_update_7006(&$sandbox) {
   }
 }
 
+/**
+ * @} End of "addtogroup updates-6.x-to-7.x".
+ */
+
+/**
+ * @addtogroup updates-7.x-extra
+ * @{
+ */
+
 /**
  * Add an index to the created column.
  */
@@ -371,15 +380,6 @@ function comment_update_7008() {
   db_drop_index('comment', 'nid');
 }
 
-/**
- * @} End of "addtogroup updates-6.x-to-7.x"
- */
-
-/**
- * @addtogroup updates-7.x-extra
- * @{
- */
-
 /**
  * Change the last_comment_timestamp column description.
  */
@@ -393,7 +393,7 @@ function comment_update_7009() {
 }
 
 /**
- * @} End of "addtogroup updates-7.x-extra"
+ * @} End of "addtogroup updates-7.x-extra".
  */
 
 /**
diff --git a/modules/comment/comment.module b/modules/comment/comment.module
index 69388337b..429c3b01b 100644
--- a/modules/comment/comment.module
+++ b/modules/comment/comment.module
@@ -103,6 +103,7 @@ function comment_entity_info() {
         'id' => 'cid',
         'bundle' => 'node_type',
         'label' => 'subject',
+        'language' => 'language',
       ),
       'bundles' => array(),
       'view modes' => array(
diff --git a/modules/comment/comment.pages.inc b/modules/comment/comment.pages.inc
index 7e88bffcb..482e3f2ff 100644
--- a/modules/comment/comment.pages.inc
+++ b/modules/comment/comment.pages.inc
@@ -23,8 +23,12 @@
  *   Some comments are replies to other comments. In those cases, $pid is the parent
  *   comment's cid.
  *
- * @return
- *   The rendered parent node or comment plus the new comment form.
+ * @return array
+ *   An associative array containing:
+ *   - An array for rendering the node or parent comment.
+ *     - comment_node: If the comment is a reply to the node.
+ *     - comment_parent: If the comment is a reply to another comment.
+ *   - comment_form: The comment form as a renderable array.
  */
 function comment_reply($node, $pid = NULL) {
   // Set the breadcrumb trail.
diff --git a/modules/comment/comment.test b/modules/comment/comment.test
index 4c6755522..e787d25d1 100644
--- a/modules/comment/comment.test
+++ b/modules/comment/comment.test
@@ -2196,3 +2196,28 @@ class CommentThreadingTestCase extends CommentHelperCase {
     $this->assertEqual($reply_loaded->thread, '02.01/');
   }
 }
+
+/**
+ * Tests that comments behave correctly when the node is changed.
+ */
+class CommentNodeChangesTestCase extends CommentHelperCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Comment deletion on node changes',
+      'description' => 'Tests that comments behave correctly when the node is changed.',
+      'group' => 'Comment',
+    );
+  }
+
+  /**
+   * Tests that comments are deleted with the node.
+   */
+  function testNodeDeletion() {
+    $this->drupalLogin($this->web_user);
+    $comment = $this->postComment($this->node, $this->randomName(), $this->randomName());
+    $this->assertTrue(comment_load($comment->id), 'The comment could be loaded.');
+    node_delete($this->node->nid);
+    $this->assertFalse(comment_load($comment->id), 'The comment could not be loaded after the node was deleted.');
+  }
+}
diff --git a/modules/contact/contact.info b/modules/contact/contact.info
index f43bb6b0a..609f4dcc4 100644
--- a/modules/contact/contact.info
+++ b/modules/contact/contact.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = contact.test
 configure = admin/structure/contact
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/contact/contact.install b/modules/contact/contact.install
index f6015581b..fba5cfd4b 100644
--- a/modules/contact/contact.install
+++ b/modules/contact/contact.install
@@ -164,5 +164,5 @@ function contact_update_7003() {
 }
 
 /**
- * @} End of "addtogroup updates-6.x-to-7.x"
+ * @} End of "addtogroup updates-6.x-to-7.x".
  */
diff --git a/modules/contextual/contextual.info b/modules/contextual/contextual.info
index 45c71d98c..2a4220758 100644
--- a/modules/contextual/contextual.info
+++ b/modules/contextual/contextual.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 files[] = contextual.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/dashboard/dashboard.info b/modules/dashboard/dashboard.info
index 106f8b124..4218e2c1b 100644
--- a/modules/dashboard/dashboard.info
+++ b/modules/dashboard/dashboard.info
@@ -7,8 +7,8 @@ files[] = dashboard.test
 dependencies[] = block
 configure = admin/dashboard/customize
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/dblog/dblog.info b/modules/dblog/dblog.info
index d2bff75a4..359de0db4 100644
--- a/modules/dblog/dblog.info
+++ b/modules/dblog/dblog.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 files[] = dblog.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/dblog/dblog.install b/modules/dblog/dblog.install
index 759c7bc1a..1eedcb0d6 100644
--- a/modules/dblog/dblog.install
+++ b/modules/dblog/dblog.install
@@ -138,5 +138,5 @@ function dblog_update_7001() {
 }
 
 /**
- * @} End of "addtogroup updates-6.x-to-7.x"
+ * @} End of "addtogroup updates-6.x-to-7.x".
  */
diff --git a/modules/dblog/dblog.test b/modules/dblog/dblog.test
index 2e9810b86..a91356c85 100644
--- a/modules/dblog/dblog.test
+++ b/modules/dblog/dblog.test
@@ -424,7 +424,7 @@ class DBLogTestCase extends DrupalWebTestCase {
       $severity = WATCHDOG_EMERGENCY;
       for ($j = 0; $j < 3; $j++) {
         $types[] = $type = array(
-          'count' => mt_rand(1, 5),
+          'count' => $j + 1,
           'type' => $type_name,
           'severity' => $severity++,
         );
@@ -473,7 +473,7 @@ class DBLogTestCase extends DrupalWebTestCase {
       $count = $this->getTypeCount($types);
       $this->assertEqual(array_sum($count), $type['count'], 'Count matched');
     }
-    
+
     // Clear all logs and make sure the confirmation message is found.
     $this->drupalPost('admin/reports/dblog', array(), t('Clear log messages'));
     $this->assertText(t('Database log cleared.'), t('Confirmation message found'));
diff --git a/modules/field/field.api.php b/modules/field/field.api.php
index 134af6615..0d01c59fa 100644
--- a/modules/field/field.api.php
+++ b/modules/field/field.api.php
@@ -676,7 +676,7 @@ function hook_field_is_empty($item, $field) {
 }
 
 /**
- * @} End of "defgroup field_types"
+ * @} End of "defgroup field_types".
  */
 
 /**
@@ -934,6 +934,38 @@ function hook_field_widget_WIDGET_TYPE_form_alter(&$element, &$form_state, $cont
   $element['#autocomplete_path'] = 'mymodule/autocomplete_path';
 }
 
+/**
+ * Alters the widget properties of a field instance before it gets displayed.
+ *
+ * Note that instead of hook_field_widget_properties_alter(), which is called
+ * for all fields on all entity types,
+ * hook_field_widget_properties_ENTITY_TYPE_alter() may be used to alter widget
+ * properties for fields on a specific entity type only.
+ *
+ * This hook is called once per field per added or edit entity. If the result
+ * of the hook involves reading from the database, it is highly recommended to
+ * statically cache the information.
+ *
+ * @param $widget
+ *   The instance's widget properties.
+ * @param $context
+ *   An associative array containing:
+ *   - entity_type: The entity type; e.g., 'node' or 'user'.
+ *   - entity: The entity object.
+ *   - field: The field that the widget belongs to.
+ *   - instance: The instance of the field.
+ *
+ * @see hook_field_widget_properties_ENTITY_TYPE_alter()
+ */
+function hook_field_widget_properties_alter(&$widget, $context) {
+  // Change a widget's type according to the time of day.
+  $field = $context['field'];
+  if ($context['entity_type'] == 'node' && $field['field_name'] == 'field_foo') {
+    $time = date('H');
+    $widget['type'] = $time < 12 ? 'widget_am' : 'widget_pm';
+  }
+}
+
 /**
  * Flag a field-level validation error.
  *
@@ -954,12 +986,12 @@ function hook_field_widget_WIDGET_TYPE_form_alter(&$element, &$form_state, $cont
  *   An associative array containing the current state of the form.
  */
 function hook_field_widget_error($element, $error, $form, &$form_state) {
-  form_error($element['value'], $error['message']);
+  form_error($element, $error['message']);
 }
 
 
 /**
- * @} End of "defgroup field_widget"
+ * @} End of "defgroup field_widget".
  */
 
 
@@ -1198,7 +1230,7 @@ function hook_field_formatter_view($entity_type, $entity, $field, $instance, $la
 }
 
 /**
- * @} End of "defgroup field_formatter"
+ * @} End of "defgroup field_formatter".
  */
 
 /**
@@ -1554,11 +1586,11 @@ function hook_field_attach_delete_bundle($entity_type, $bundle, $instances) {
 }
 
 /**
- * @} End of "defgroup field_attach"
+ * @} End of "defgroup field_attach".
  */
 
 /**
- * @ingroup field_storage
+ * @addtogroup field_storage
  * @{
  */
 
@@ -2326,38 +2358,6 @@ function hook_field_extra_fields_display_alter(&$displays, $context) {
   }
 }
 
-/**
- * Alters the widget properties of a field instance before it gets displayed.
- *
- * Note that instead of hook_field_widget_properties_alter(), which is called
- * for all fields on all entity types,
- * hook_field_widget_properties_ENTITY_TYPE_alter() may be used to alter widget
- * properties for fields on a specific entity type only.
- *
- * This hook is called once per field per added or edit entity. If the result
- * of the hook involves reading from the database, it is highly recommended to
- * statically cache the information.
- *
- * @param $widget
- *   The instance's widget properties.
- * @param $context
- *   An associative array containing:
- *   - entity_type: The entity type; e.g., 'node' or 'user'.
- *   - entity: The entity object.
- *   - field: The field that the widget belongs to.
- *   - instance: The instance of the field.
- *
- * @see hook_field_widget_properties_ENTITY_TYPE_alter()
- */
-function hook_field_widget_properties_alter(&$widget, $context) {
-  // Change a widget's type according to the time of day.
-  $field = $context['field'];
-  if ($context['entity_type'] == 'node' && $field['field_name'] == 'field_foo') {
-    $time = date('H');
-    $widget['type'] = $time < 12 ? 'widget_am' : 'widget_pm';
-  }
-}
-
 /**
  * Alters the widget properties of a field instance on a given entity type
  * before it gets displayed.
@@ -2391,11 +2391,11 @@ function hook_field_widget_properties_ENTITY_TYPE_alter(&$widget, $context) {
 }
 
 /**
- * @} End of "ingroup field_storage"
+ * @} End of "addtogroup field_storage".
  */
 
 /**
- * @ingroup field_crud
+ * @addtogroup field_crud
  * @{
  */
 
@@ -2644,7 +2644,7 @@ function hook_field_storage_purge($entity_type, $entity, $field, $instance) {
 }
 
 /**
- * @} End of "ingroup field_crud"
+ * @} End of "addtogroup field_crud".
  */
 
 /**
@@ -2675,5 +2675,5 @@ function hook_field_access($op, $field, $entity_type, $entity, $account) {
 }
 
 /**
- * @} End of "addtogroup hooks"
+ * @} End of "addtogroup hooks".
  */
diff --git a/modules/field/field.attach.inc b/modules/field/field.attach.inc
index 36117eb7a..868d7bd75 100644
--- a/modules/field/field.attach.inc
+++ b/modules/field/field.attach.inc
@@ -65,7 +65,7 @@ define('FIELD_STORAGE_UPDATE', 'update');
 define('FIELD_STORAGE_INSERT', 'insert');
 
 /**
- * @} End of "defgroup field_storage"
+ * @} End of "defgroup field_storage".
  */
 
 /**
@@ -1365,5 +1365,5 @@ function field_attach_delete_bundle($entity_type, $bundle) {
 
 
 /**
- * @} End of "defgroup field_attach"
+ * @} End of "defgroup field_attach".
  */
diff --git a/modules/field/field.form.inc b/modules/field/field.form.inc
index 5641375e5..6c27c4329 100644
--- a/modules/field/field.form.inc
+++ b/modules/field/field.form.inc
@@ -37,90 +37,86 @@ function field_default_form($entity_type, $entity, $field, $instance, $langcode,
 
   // Collect widget elements.
   $elements = array();
-  if (field_access('edit', $field, $entity_type, $entity)) {
-    // Store field information in $form_state.
-    if (!field_form_get_state($parents, $field_name, $langcode, $form_state)) {
-      $field_state = array(
-        'field' => $field,
-        'instance' => $instance,
-        'items_count' => count($items),
-        'array_parents' => array(),
-        'errors' => array(),
-      );
-      field_form_set_state($parents, $field_name, $langcode, $form_state, $field_state);
-    }
 
-    // If field module handles multiple values for this form element, and we
-    // are displaying an individual element, process the multiple value form.
-    if (!isset($get_delta) && field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
-      // Store the entity in the form.
-      $form['#entity'] = $entity;
-      $elements = field_multiple_value_form($field, $instance, $langcode, $items, $form, $form_state);
-    }
-    // If the widget is handling multiple values (e.g Options), or if we are
-    // displaying an individual element, just get a single form element and
-    // make it the $delta value.
-    else {
-      $delta = isset($get_delta) ? $get_delta : 0;
-      $function = $instance['widget']['module'] . '_field_widget_form';
-      if (function_exists($function)) {
-        $element = array(
-          '#entity' => $entity,
-          '#entity_type' => $instance['entity_type'],
-          '#bundle' => $instance['bundle'],
-          '#field_name' => $field_name,
-          '#language' => $langcode,
-          '#field_parents' => $parents,
-          '#columns' => array_keys($field['columns']),
-          '#title' => check_plain($instance['label']),
-          '#description' => field_filter_xss($instance['description']),
-          // Only the first widget should be required.
-          '#required' => $delta == 0 && $instance['required'],
-          '#delta' => $delta,
+  // Store field information in $form_state.
+  if (!field_form_get_state($parents, $field_name, $langcode, $form_state)) {
+    $field_state = array(
+      'field' => $field,
+      'instance' => $instance,
+      'items_count' => count($items),
+      'array_parents' => array(),
+      'errors' => array(),
+    );
+    field_form_set_state($parents, $field_name, $langcode, $form_state, $field_state);
+  }
+
+  // If field module handles multiple values for this form element, and we are
+  // displaying an individual element, process the multiple value form.
+  if (!isset($get_delta) && field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
+    // Store the entity in the form.
+    $form['#entity'] = $entity;
+    $elements = field_multiple_value_form($field, $instance, $langcode, $items, $form, $form_state);
+  }
+  // If the widget is handling multiple values (e.g Options), or if we are
+  // displaying an individual element, just get a single form element and make
+  // it the $delta value.
+  else {
+    $delta = isset($get_delta) ? $get_delta : 0;
+    $function = $instance['widget']['module'] . '_field_widget_form';
+    if (function_exists($function)) {
+      $element = array(
+        '#entity' => $entity,
+        '#entity_type' => $instance['entity_type'],
+        '#bundle' => $instance['bundle'],
+        '#field_name' => $field_name,
+        '#language' => $langcode,
+        '#field_parents' => $parents,
+        '#columns' => array_keys($field['columns']),
+        '#title' => check_plain($instance['label']),
+        '#description' => field_filter_xss($instance['description']),
+        // Only the first widget should be required.
+        '#required' => $delta == 0 && $instance['required'],
+        '#delta' => $delta,
+      );
+      if ($element = $function($form, $form_state, $field, $instance, $langcode, $items, $delta, $element)) {
+        // Allow modules to alter the field widget form element.
+        $context = array(
+          'form' => $form,
+          'field' => $field,
+          'instance' => $instance,
+          'langcode' => $langcode,
+          'items' => $items,
+          'delta' => $delta,
         );
-        if ($element = $function($form, $form_state, $field, $instance, $langcode, $items, $delta, $element)) {
-          // Allow modules to alter the field widget form element.
-          $context = array(
-            'form' => $form,
-            'field' => $field,
-            'instance' => $instance,
-            'langcode' => $langcode,
-            'items' => $items,
-            'delta' => $delta,
-          );
-          drupal_alter(array('field_widget_form', 'field_widget_' . $instance['widget']['type'] . '_form'), $element, $form_state, $context);
-
-          // If we're processing a specific delta value for a field where the
-          // field module handles multiples, set the delta in the result.
-          // For fields that handle their own processing, we can't make
-          // assumptions about how the field is structured, just merge in the
-          // returned element.
-          if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
-            $elements[$delta] = $element;
-          }
-          else {
-            $elements = $element;
-          }
+        drupal_alter(array('field_widget_form', 'field_widget_' . $instance['widget']['type'] . '_form'), $element, $form_state, $context);
+
+        // If we're processing a specific delta value for a field where the
+        // field module handles multiples, set the delta in the result.
+        // For fields that handle their own processing, we can't make
+        // assumptions about how the field is structured, just merge in the
+        // returned element.
+        if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
+          $elements[$delta] = $element;
+        }
+        else {
+          $elements = $element;
         }
       }
     }
   }
 
-  if ($elements) {
-    // Also aid in theming of field widgets by rendering a classified
-    // container.
-    $addition[$field_name] = array(
-      '#type' => 'container',
-      '#attributes' => array(
-        'class' => array(
-          'field-type-' . drupal_html_class($field['type']),
-          'field-name-' . drupal_html_class($field_name),
-          'field-widget-' . drupal_html_class($instance['widget']['type']),
-        ),
+  // Also aid in theming of field widgets by rendering a classified container.
+  $addition[$field_name] = array(
+    '#type' => 'container',
+    '#attributes' => array(
+      'class' => array(
+        'field-type-' . drupal_html_class($field['type']),
+        'field-name-' . drupal_html_class($field_name),
+        'field-widget-' . drupal_html_class($instance['widget']['type']),
       ),
-      '#weight' => $instance['widget']['weight'],
-    );
-  }
+    ),
+    '#weight' => $instance['widget']['weight'],
+  );
 
   // Populate the 'array_parents' information in $form_state['field'] after
   // the form is built, so that we catch changes in the form structure performed
@@ -136,6 +132,7 @@ function field_default_form($entity_type, $entity, $field, $instance, $langcode,
     // when $langcode is unknown.
     '#language' => $langcode,
     $langcode => $elements,
+    '#access' => field_access('edit', $field, $entity_type, $entity),
   );
 
   return $addition;
@@ -362,31 +359,33 @@ function field_default_form_errors($entity_type, $entity, $field, $instance, $la
   $field_state = field_form_get_state($form['#parents'], $field['field_name'], $langcode, $form_state);
 
   if (!empty($field_state['errors'])) {
-    $function = $instance['widget']['module'] . '_field_widget_error';
-    $function_exists = function_exists($function);
-
-    // Locate the correct element in the the form.
+    // Locate the correct element in the form.
     $element = drupal_array_get_nested_value($form_state['complete form'], $field_state['array_parents']);
-
-    $multiple_widget = field_behaviors_widget('multiple values', $instance) != FIELD_BEHAVIOR_DEFAULT;
-    foreach ($field_state['errors'] as $delta => $delta_errors) {
-      // For multiple single-value widgets, pass errors by delta.
-      // For a multiple-value widget, all errors are passed to the main widget.
-      $error_element = $multiple_widget ? $element : $element[$delta];
-      foreach ($delta_errors as $error) {
-        if ($function_exists) {
-          $function($error_element, $error, $form, $form_state);
-        }
-        else {
-          // Make sure that errors are reported (even incorrectly flagged) if
-          // the widget module fails to implement hook_field_widget_error().
-          form_error($error_element, $error['error']);
+    // Only set errors if the element is accessible.
+    if (!isset($element['#access']) || $element['#access']) {
+      $function = $instance['widget']['module'] . '_field_widget_error';
+      $function_exists = function_exists($function);
+
+      $multiple_widget = field_behaviors_widget('multiple values', $instance) != FIELD_BEHAVIOR_DEFAULT;
+      foreach ($field_state['errors'] as $delta => $delta_errors) {
+        // For multiple single-value widgets, pass errors by delta.
+        // For a multiple-value widget, pass all errors to the main widget.
+        $error_element = $multiple_widget ? $element : $element[$delta];
+        foreach ($delta_errors as $error) {
+          if ($function_exists) {
+            $function($error_element, $error, $form, $form_state);
+          }
+          else {
+            // Make sure that errors are reported (even incorrectly flagged) if
+            // the widget module fails to implement hook_field_widget_error().
+            form_error($error_element, $error['message']);
+          }
         }
       }
+      // Reinitialize the errors list for the next submit.
+      $field_state['errors'] = array();
+      field_form_set_state($form['#parents'], $field['field_name'], $langcode, $form_state, $field_state);
     }
-    // Reinitialize the errors list for the next submit.
-    $field_state['errors'] = array();
-    field_form_set_state($form['#parents'], $field['field_name'], $langcode, $form_state, $field_state);
   }
 }
 
diff --git a/modules/field/field.info b/modules/field/field.info
index 9ff281132..b950f2e44 100644
--- a/modules/field/field.info
+++ b/modules/field/field.info
@@ -10,8 +10,8 @@ dependencies[] = field_sql_storage
 required = TRUE
 stylesheets[all][] = theme/field.css
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/field/field.info.inc b/modules/field/field.info.inc
index e7eaaf0c6..eb5cc5ca7 100644
--- a/modules/field/field.info.inc
+++ b/modules/field/field.info.inc
@@ -613,7 +613,8 @@ function field_info_fields() {
  * @return
  *   The field array, as returned by field_read_fields(), with an
  *   additional element 'bundles', whose value is an array of all the bundles
- *   this field belongs to keyed by entity type.
+ *   this field belongs to keyed by entity type. NULL if the field was not
+ *   found.
  *
  * @see field_info_field_by_id()
  */
@@ -890,5 +891,5 @@ function field_info_storage_settings($type) {
 }
 
 /**
- * @} End of "defgroup field_info"
+ * @} End of "defgroup field_info".
  */
diff --git a/modules/field/field.install b/modules/field/field.install
index dff3949fb..5934a264c 100644
--- a/modules/field/field.install
+++ b/modules/field/field.install
@@ -434,7 +434,7 @@ function field_update_7001() {
 }
 
 /**
- * @} End of "addtogroup updates-6.x-to-7.x"
+ * @} End of "addtogroup updates-6.x-to-7.x".
  */
 
 /**
@@ -458,5 +458,5 @@ function field_update_7002() {
 }
 
 /**
- * @} End of "addtogroup updates-7.x-extra"
+ * @} End of "addtogroup updates-7.x-extra".
  */
diff --git a/modules/field/field.module b/modules/field/field.module
index dedf8470c..6fc97a2bf 100644
--- a/modules/field/field.module
+++ b/modules/field/field.module
@@ -423,13 +423,9 @@ function field_modules_disabled($modules) {
 function field_sync_field_status() {
   // Refresh the 'active' and 'storage_active' columns according to the current
   // set of enabled modules.
-  $all_modules = system_rebuild_module_data();
-  $modules = array();
-  foreach ($all_modules as $module_name => $module) {
-    if ($module->status) {
-      $modules[] = $module_name;
-      field_associate_fields($module_name);
-    }
+  $modules = module_list();
+  foreach ($modules as $module_name) {
+    field_associate_fields($module_name);
   }
   db_update('field_config')
     ->fields(array('active' => 0))
@@ -555,51 +551,33 @@ function _field_sort_items_value_helper($a, $b) {
 /**
  * Gets or sets administratively defined bundle settings.
  *
- * For each bundle, settings are provided as a nested array with the following
- * structure:
- * @code
- * array(
- *   'view_modes' => array(
- *     // One sub-array per view mode for the entity type:
- *     'full' => array(
- *       'custom_display' => Whether the view mode uses custom display
- *         settings or settings of the 'default' mode,
- *     ),
- *     'teaser' => ...
- *   ),
- *   'extra_fields' => array(
- *     'form' => array(
- *       // One sub-array per pseudo-field in displayed entities:
- *       'extra_field_1' => array(
- *         'weight' => The weight of the pseudo-field,
- *       ),
- *       'extra_field_2' => ...
- *     ),
- *     'display' => array(
- *       // One sub-array per pseudo-field in displayed entities:
- *       'extra_field_1' => array(
- *         // One sub-array per view mode for the entity type, including
- *         // the 'default' mode:
- *         'default' => array(
- *           'weight' => The weight of the pseudo-field,
- *           'visible' => TRUE if the pseudo-field is visible, FALSE if hidden,
- *         ),
- *         'full' => ...
- *       ),
- *       'extra_field_2' => ...
- *     ),
- *   ),
- * );
- * @endcode
- *
- * @param $entity_type
+ * @param string $entity_type
  *   The type of $entity; e.g., 'node' or 'user'.
- * @param $bundle
+ * @param string $bundle
  *   The bundle name.
- * @param $settings
- *   (optional) The settings to store.
+ * @param array|null $settings
+ *   (optional) The settings to store, an associative array with the following
+ *   elements:
+ *   - view_modes: An associative array keyed by view mode, with the following
+ *     key/value pairs:
+ *     - custom_settings: Boolean specifying whether the view mode uses a
+ *       dedicated set of display options (TRUE), or the 'default' options
+ *       (FALSE). Defaults to FALSE.
+ *   - extra_fields: An associative array containing the form and display
+ *     settings for extra fields (also known as pseudo-fields):
+ *     - form: An associative array whose keys are the names of extra fields,
+ *       and whose values are associative arrays with the following elements:
+ *       - weight: The weight of the extra field, determining its position on an
+ *         entity form.
+ *     - display: An associative array whose keys are the names of extra fields,
+ *       and whose values are associative arrays keyed by the name of view
+ *       modes. This array must include an item for the 'default' view mode.
+ *       Each view mode sub-array contains the following elements:
+ *       - weight: The weight of the extra field, determining its position when
+ *         an entity is viewed.
+ *       - visible: TRUE if the extra field is visible, FALSE otherwise.
  *
- * @return
+ * @return array|null
  *   If no $settings are passed, the current settings are returned.
  */
 function field_bundle_settings($entity_type, $bundle, $settings = NULL) {
@@ -972,6 +950,10 @@ function field_has_data($field) {
     ->fieldCondition($field)
     ->range(0, 1)
     ->count()
+    // Neutralize the 'entity_field_access' query tag added by
+    // field_sql_storage_field_storage_query(). The result cannot depend on the
+    // access grants of the current user.
+    ->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT')
     ->execute();
 }
 
@@ -1112,7 +1094,7 @@ function template_process_field(&$variables, $hook) {
   }
 }
 /**
- * @} End of "defgroup field"
+ * @} End of "defgroup field".
  */
 
 /**
diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.info b/modules/field/modules/field_sql_storage/field_sql_storage.info
index 532cb8381..125b4a51e 100644
--- a/modules/field/modules/field_sql_storage/field_sql_storage.info
+++ b/modules/field/modules/field_sql_storage/field_sql_storage.info
@@ -7,8 +7,8 @@ dependencies[] = field
 files[] = field_sql_storage.test
 required = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.install b/modules/field/modules/field_sql_storage/field_sql_storage.install
index 647296e4e..78c520fcf 100644
--- a/modules/field/modules/field_sql_storage/field_sql_storage.install
+++ b/modules/field/modules/field_sql_storage/field_sql_storage.install
@@ -211,5 +211,5 @@ function field_sql_storage_update_7002() {
 }
 
 /**
- * @} End of "addtogroup updates-6.x-to-7.x"
+ * @} End of "addtogroup updates-6.x-to-7.x".
  */
diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.module b/modules/field/modules/field_sql_storage/field_sql_storage.module
index 2ed783507..a75619427 100644
--- a/modules/field/modules/field_sql_storage/field_sql_storage.module
+++ b/modules/field/modules/field_sql_storage/field_sql_storage.module
@@ -512,7 +512,12 @@ function field_sql_storage_field_storage_query(EntityFieldQuery $query) {
     }
     else {
       $select_query = db_select($tablename, $table_alias);
-      $select_query->addTag('entity_field_access');
+      // Allow queries internal to the Field API to opt out of the access
+      // check, for situations where the query's results should not depend on
+      // the access grants for the current user.
+      if (!isset($query->tags['DANGEROUS_ACCESS_CHECK_OPT_OUT'])) {
+        $select_query->addTag('entity_field_access');
+      }
       $select_query->addMetaData('base_table', $tablename);
       $select_query->fields($table_alias, array('entity_type', 'entity_id', 'revision_id', 'bundle'));
       $field_base_table = $table_alias;
diff --git a/modules/field/modules/list/list.info b/modules/field/modules/list/list.info
index d3f92ab85..43300c261 100644
--- a/modules/field/modules/list/list.info
+++ b/modules/field/modules/list/list.info
@@ -7,8 +7,8 @@ dependencies[] = field
 dependencies[] = options
 files[] = tests/list.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/field/modules/list/list.install b/modules/field/modules/list/list.install
index 91c7649c1..2386f0483 100644
--- a/modules/field/modules/list/list.install
+++ b/modules/field/modules/list/list.install
@@ -116,6 +116,11 @@ function _list_update_7001_extract_allowed_values($string, $position_keys) {
   return $values;
 }
 
+/**
+ * @addtogroup updates-7.x-extra
+ * @{
+ */
+
 /**
  * Re-apply list_update_7001() for deleted fields.
  */
@@ -126,4 +131,8 @@ function list_update_7002() {
   // list_update_7001() has the required checks to ensure it is reentrant, so
   // it can simply be executed once more..
   list_update_7001();
-}
\ No newline at end of file
+}
+
+/**
+ * @} End of "addtogroup updates-7.x-extra".
+ */
diff --git a/modules/field/modules/list/tests/list_test.info b/modules/field/modules/list/tests/list_test.info
index b524e183d..666ab1e7e 100644
--- a/modules/field/modules/list/tests/list_test.info
+++ b/modules/field/modules/list/tests/list_test.info
@@ -5,8 +5,8 @@ package = Testing
 version = VERSION
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/field/modules/number/number.info b/modules/field/modules/number/number.info
index ed98de241..261376831 100644
--- a/modules/field/modules/number/number.info
+++ b/modules/field/modules/number/number.info
@@ -6,8 +6,8 @@ core = 7.x
 dependencies[] = field
 files[] = number.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/field/modules/options/options.info b/modules/field/modules/options/options.info
index 65e620b85..ef5c87b12 100644
--- a/modules/field/modules/options/options.info
+++ b/modules/field/modules/options/options.info
@@ -6,8 +6,8 @@ core = 7.x
 dependencies[] = field
 files[] = options.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/field/modules/text/text.info b/modules/field/modules/text/text.info
index 6e1aba775..7c21f9bb2 100644
--- a/modules/field/modules/text/text.info
+++ b/modules/field/modules/text/text.info
@@ -7,8 +7,8 @@ dependencies[] = field
 files[] = text.test
 required = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/field/tests/field.test b/modules/field/tests/field.test
index f7d9dddb2..739ddbe99 100644
--- a/modules/field/tests/field.test
+++ b/modules/field/tests/field.test
@@ -1650,6 +1650,18 @@ class FieldFormTestCase extends FieldTestCase {
 
     $langcode = LANGUAGE_NONE;
 
+    // Test that the form structure includes full information for each delta
+    // apart from #access.
+    $entity_type = 'test_entity';
+    $entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
+
+    $form = array();
+    $form_state = form_state_defaults();
+    field_attach_form($entity_type, $entity, $form, $form_state);
+
+    $this->assertEqual($form[$field_name_no_access][$langcode][0]['value']['#entity_type'], $entity_type, 'The correct entity type is set in the field structure.');
+    $this->assertFalse($form[$field_name_no_access]['#access'], 'Field #access is FALSE for the field without edit access.');
+
     // Display creation form.
     $this->drupalGet('test-entity/add/test-bundle');
     $this->assertNoFieldByName("{$field_name_no_access}[$langcode][0][value]", '', t('Widget is not displayed if field access is denied.'));
@@ -2794,7 +2806,7 @@ class FieldTranslationsTestCase extends FieldTestCase {
     $options = array();
     $entities = array();
     $entity_type = 'test_entity';
-    $entity_count = mt_rand(2, 5);
+    $entity_count = 5;
     $available_languages = field_available_languages($this->entity_type, $this->field);
 
     for ($id = 1; $id <= $entity_count; ++$id) {
diff --git a/modules/field/tests/field_test.info b/modules/field/tests/field_test.info
index 0262b5b95..75a84caaa 100644
--- a/modules/field/tests/field_test.info
+++ b/modules/field/tests/field_test.info
@@ -6,8 +6,8 @@ files[] = field_test.entity.inc
 version = VERSION
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/field/tests/field_test.module b/modules/field/tests/field_test.module
index 0015cd905..37ea7b1dd 100644
--- a/modules/field/tests/field_test.module
+++ b/modules/field/tests/field_test.module
@@ -259,3 +259,14 @@ function field_test_field_widget_form_alter(&$element, &$form_state, $context) {
       break;
   }
 }
+
+/**
+ * Implements hook_query_TAG_alter() for tag 'efq_table_prefixing_test'.
+ *
+ * @see EntityFieldQueryTestCase::testTablePrefixing()
+ */
+function field_test_query_efq_table_prefixing_test_alter(&$query) {
+  // Add an additional join onto the entity base table. This will cause an
+  // exception if the EFQ does not properly prefix the base table.
+  $query->join('test_entity','te2','%alias.ftid = test_entity.ftid');
+}
diff --git a/modules/field_ui/field_ui.admin.inc b/modules/field_ui/field_ui.admin.inc
index 33ce2f05c..44770acb9 100644
--- a/modules/field_ui/field_ui.admin.inc
+++ b/modules/field_ui/field_ui.admin.inc
@@ -162,7 +162,8 @@ function field_ui_table_pre_render($elements) {
 
         // Add tabledrag indentation to the first row cell.
         if ($depth = count($parents[$name])) {
-          $cell = current(element_children($row));
+          $children = element_children($row);
+          $cell = current($children);
           $row[$cell]['#prefix'] = theme('indentation', array('size' => $depth)) . (isset($row[$cell]['#prefix']) ? $row[$cell]['#prefix'] : '');
         }
 
@@ -317,7 +318,7 @@ function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle
       t('Weight'),
       t('Parent'),
       t('Machine name'),
-      t('Field'),
+      t('Field type'),
       t('Widget'),
       array('data' => t('Operations'), 'colspan' => 2),
     ),
diff --git a/modules/field_ui/field_ui.api.php b/modules/field_ui/field_ui.api.php
index 882f467a6..05d9f053f 100644
--- a/modules/field_ui/field_ui.api.php
+++ b/modules/field_ui/field_ui.api.php
@@ -200,5 +200,5 @@ function hook_field_formatter_settings_summary($field, $instance, $view_mode) {
 }
 
 /**
- * @} End of "addtogroup field_types"
+ * @} End of "addtogroup field_types".
  */
diff --git a/modules/field_ui/field_ui.info b/modules/field_ui/field_ui.info
index 10760760a..8757a5299 100644
--- a/modules/field_ui/field_ui.info
+++ b/modules/field_ui/field_ui.info
@@ -6,8 +6,8 @@ core = 7.x
 dependencies[] = field
 files[] = field_ui.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/field_ui/field_ui.js b/modules/field_ui/field_ui.js
index 1017937b6..65b28d049 100644
--- a/modules/field_ui/field_ui.js
+++ b/modules/field_ui/field_ui.js
@@ -97,7 +97,7 @@ jQuery.fn.fieldUIPopulateOptions = function (options, selected) {
       html += '<option value="' + value + '"' + (is_selected ? ' selected="selected"' : '') + '>' + text + '</option>';
     });
 
-    $(this).html(html).attr('disabled', disabled ? 'disabled' : '');
+    $(this).html(html).attr('disabled', disabled ? 'disabled' : false);
   });
 };
 
diff --git a/modules/field_ui/field_ui.test b/modules/field_ui/field_ui.test
index 75a70846f..d0a822a82 100644
--- a/modules/field_ui/field_ui.test
+++ b/modules/field_ui/field_ui.test
@@ -173,7 +173,7 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
     $table_headers = array(
       t('Label'),
       t('Machine name'),
-      t('Field'),
+      t('Field type'),
       t('Widget'),
       t('Operations'),
     );
diff --git a/modules/file/file.field.inc b/modules/file/file.field.inc
index 7a5697ccb..1189704fd 100644
--- a/modules/file/file.field.inc
+++ b/modules/file/file.field.inc
@@ -261,11 +261,8 @@ function file_field_update($entity_type, $entity, $field, $instance, $langcode,
     $current_fids[] = $item['fid'];
   }
 
-  // Create a bare-bones entity so that we can load its previous values.
-  $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']));
-
   // Compare the original field values with the ones that are being saved.
+  $original = $entity->original;
   $original_fids = array();
   if (!empty($original->{$field['field_name']}[$langcode])) {
     foreach ($original->{$field['field_name']}[$langcode] as $original_item) {
@@ -630,10 +627,9 @@ function file_field_widget_process($element, &$form_state, $form) {
   // Add the description field if enabled.
   if (!empty($instance['settings']['description_field']) && $item['fid']) {
     $element['description'] = array(
-      '#type' => 'textfield',
+      '#type' => variable_get('file_description_type', 'textfield'),
       '#title' => t('Description'),
       '#value' => isset($item['description']) ? $item['description'] : '',
-      '#type' => variable_get('file_description_type', 'textfield'),
       '#maxlength' => variable_get('file_description_length', 128),
       '#description' => t('The description may be used as the label of the link to the file.'),
     );
diff --git a/modules/file/file.info b/modules/file/file.info
index bf896788c..99b08f96d 100644
--- a/modules/file/file.info
+++ b/modules/file/file.info
@@ -6,8 +6,8 @@ core = 7.x
 dependencies[] = field
 files[] = tests/file.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/file/file.js b/modules/file/file.js
index 1a9f87e4f..577480bbc 100644
--- a/modules/file/file.js
+++ b/modules/file/file.js
@@ -110,7 +110,7 @@ Drupal.file = Drupal.file || {
     var $fieldsToTemporarilyDisable = $('div.form-managed-file input.form-file').not($enabledFields).not(':disabled');
     $fieldsToTemporarilyDisable.attr('disabled', 'disabled');
     setTimeout(function (){
-      $fieldsToTemporarilyDisable.attr('disabled', '');
+      $fieldsToTemporarilyDisable.attr('disabled', false);
     }, 1000);
   },
   /**
diff --git a/modules/file/tests/file.test b/modules/file/tests/file.test
index 7fa6d6f01..76708a3c7 100644
--- a/modules/file/tests/file.test
+++ b/modules/file/tests/file.test
@@ -551,7 +551,7 @@ class FileFieldWidgetTestCase extends FileFieldTestCase {
 
     // Remove access comments permission from anon user.
     $edit = array(
-      '1[access comments]' => FALSE,
+      DRUPAL_ANONYMOUS_RID . '[access comments]' => FALSE,
     );
     $this->drupalPost('admin/people/permissions', $edit, t('Save permissions'));
 
diff --git a/modules/file/tests/file_module_test.info b/modules/file/tests/file_module_test.info
index a7a6f55b3..7c1f6e62d 100644
--- a/modules/file/tests/file_module_test.info
+++ b/modules/file/tests/file_module_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/filter/filter.info b/modules/filter/filter.info
index a4823170a..70af4048f 100644
--- a/modules/filter/filter.info
+++ b/modules/filter/filter.info
@@ -7,8 +7,8 @@ files[] = filter.test
 required = TRUE
 configure = admin/config/content/formats
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/filter/filter.install b/modules/filter/filter.install
index 19fd8aa18..9d17eb54b 100644
--- a/modules/filter/filter.install
+++ b/modules/filter/filter.install
@@ -490,5 +490,5 @@ function filter_update_7010() {
 }
 
 /**
- * @} End of "addtogroup updates-6.x-to-7.x"
+ * @} End of "addtogroup updates-6.x-to-7.x".
  */
diff --git a/modules/filter/filter.test b/modules/filter/filter.test
index 1a21ecbbd..aa1693fba 100644
--- a/modules/filter/filter.test
+++ b/modules/filter/filter.test
@@ -314,7 +314,7 @@ class FilterAdminTestCase extends DrupalWebTestCase {
     $edit = array();
     $edit['format'] = drupal_strtolower($this->randomName());
     $edit['name'] = $this->randomName();
-    $edit['roles[2]'] = 1;
+    $edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'] = 1;
     $edit['filters[' . $second_filter . '][status]'] = TRUE;
     $edit['filters[' . $first_filter . '][status]'] = TRUE;
     $this->drupalPost('admin/config/content/formats/add', $edit, t('Save configuration'));
@@ -324,7 +324,7 @@ class FilterAdminTestCase extends DrupalWebTestCase {
     $format = filter_format_load($edit['format']);
     $this->assertNotNull($format, t('Format found in database.'));
 
-    $this->assertFieldByName('roles[2]', '', t('Role found.'));
+    $this->assertFieldByName('roles[' . DRUPAL_AUTHENTICATED_RID . ']', '', t('Role found.'));
     $this->assertFieldByName('filters[' . $second_filter . '][status]', '', t('Line break filter found.'));
     $this->assertFieldByName('filters[' . $first_filter . '][status]', '', t('Url filter found.'));
 
@@ -335,8 +335,8 @@ class FilterAdminTestCase extends DrupalWebTestCase {
     // Allow authenticated users on full HTML.
     $format = filter_format_load($full);
     $edit = array();
-    $edit['roles[1]'] = 0;
-    $edit['roles[2]'] = 1;
+    $edit['roles[' . DRUPAL_ANONYMOUS_RID . ']'] = 0;
+    $edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'] = 1;
     $this->drupalPost('admin/config/content/formats/' . $full, $edit, t('Save configuration'));
     $this->assertRaw(t('The text format %format has been updated.', array('%format' => $format->name)), t('Full HTML format successfully updated.'));
 
@@ -386,10 +386,10 @@ class FilterAdminTestCase extends DrupalWebTestCase {
 
     // Full HTML.
     $edit = array();
-    $edit['roles[2]'] = FALSE;
+    $edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'] = FALSE;
     $this->drupalPost('admin/config/content/formats/' . $full, $edit, t('Save configuration'));
     $this->assertRaw(t('The text format %format has been updated.', array('%format' => $format->name)), t('Full HTML format successfully reverted.'));
-    $this->assertFieldByName('roles[2]', $edit['roles[2]'], t('Changes reverted.'));
+    $this->assertFieldByName('roles[' . DRUPAL_AUTHENTICATED_RID . ']', $edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'], t('Changes reverted.'));
 
     // Filter order.
     $edit = array();
@@ -1195,6 +1195,11 @@ class FilterUnitTestCase extends DrupalUnitTestCase {
     // - absolute, mail, partial
     // - characters/encoding, surrounding markup, security
 
+    // Create a e-mail that is too long.
+    $long_email = str_repeat('a', 254) . '@example.com';
+    $too_long_email = str_repeat('b', 255) . '@example.com';
+
+
     // Filter selection/pattern matching.
     $tests = array(
       // HTTP URLs.
@@ -1206,10 +1211,12 @@ http://example.com or www.example.com
       ),
       // MAILTO URLs.
       '
-person@example.com or mailto:person2@example.com
+person@example.com or mailto:person2@example.com or ' . $long_email . ' but not ' . $too_long_email . '
 ' => array(
         '<a href="mailto:person@example.com">person@example.com</a>' => TRUE,
         '<a href="mailto:person2@example.com">mailto:person2@example.com</a>' => TRUE,
+        '<a href="mailto:' . $long_email . '">' . $long_email . '</a>' => TRUE,
+        '<a href="mailto:' . $too_long_email . '">' . $too_long_email . '</a>' => FALSE,
       ),
       // URI parts and special characters.
       '
@@ -1800,7 +1807,7 @@ class FilterHooksTestCase extends DrupalWebTestCase {
     $edit = array();
     $edit['format'] = drupal_strtolower($this->randomName());
     $edit['name'] = $name;
-    $edit['roles[1]'] = 1;
+    $edit['roles[' . DRUPAL_ANONYMOUS_RID . ']'] = 1;
     $this->drupalPost('admin/config/content/formats/add', $edit, t('Save configuration'));
     $this->assertRaw(t('Added text format %format.', array('%format' => $name)), t('New format created.'));
     $this->assertText('hook_filter_format_insert invoked.', t('hook_filter_format_insert was invoked.'));
@@ -1809,7 +1816,7 @@ class FilterHooksTestCase extends DrupalWebTestCase {
 
     // Update text format.
     $edit = array();
-    $edit['roles[2]'] = 1;
+    $edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'] = 1;
     $this->drupalPost('admin/config/content/formats/' . $format_id, $edit, t('Save configuration'));
     $this->assertRaw(t('The text format %format has been updated.', array('%format' => $name)), t('Format successfully updated.'));
     $this->assertText('hook_filter_format_update invoked.', t('hook_filter_format_update() was invoked.'));
diff --git a/modules/forum/forum-icon.tpl.php b/modules/forum/forum-icon.tpl.php
index 9cf2cd8d3..fd1cd1308 100644
--- a/modules/forum/forum-icon.tpl.php
+++ b/modules/forum/forum-icon.tpl.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Default theme implementation to display an appropriate icon for a forum post.
+ * Displays an appropriate icon for a forum post.
  *
  * Available variables:
  * - $new_posts: Indicates whether or not the topic contains new posts.
@@ -12,6 +12,8 @@
  *
  * @see template_preprocess_forum_icon()
  * @see theme_forum_icon()
+ *
+ * @ingroup themeable
  */
 ?>
 <div class="topic-status-<?php print $icon_class ?>" title="<?php print $icon_title ?>">
diff --git a/modules/forum/forum-list.tpl.php b/modules/forum/forum-list.tpl.php
index 257cea947..01c74a34c 100644
--- a/modules/forum/forum-list.tpl.php
+++ b/modules/forum/forum-list.tpl.php
@@ -2,34 +2,35 @@
 
 /**
  * @file
- * Default theme implementation to display a list of forums and containers.
+ * Displays a list of forums and containers.
  *
  * Available variables:
  * - $forums: An array of forums and containers to display. It is keyed to the
- *   numeric id's of all child forums and containers.
- * - $forum_id: Forum id for the current forum. Parent to all items within
- *   the $forums array.
- *
- * Each $forum in $forums contains:
- * - $forum->is_container: Is TRUE if the forum can contain other forums. Is
- *   FALSE if the forum can contain only topics.
- * - $forum->depth: How deep the forum is in the current hierarchy.
- * - $forum->zebra: 'even' or 'odd' string used for row class.
- * - $forum->icon_class: 'default' or 'new' string used for forum icon class.
- * - $forum->icon_title: Text alternative for the forum icon.
- * - $forum->name: The name of the forum.
- * - $forum->link: The URL to link to this forum.
- * - $forum->description: The description of this forum.
- * - $forum->new_topics: True if the forum contains unread posts.
- * - $forum->new_url: A URL to the forum's unread posts.
- * - $forum->new_text: Text for the above URL which tells how many new posts.
- * - $forum->old_topics: A count of posts that have already been read.
- * - $forum->num_posts: The total number of posts in the forum.
- * - $forum->last_reply: Text representing the last time a forum was posted or
- *   commented in.
+ *   numeric IDs of all child forums and containers. Each $forum in $forums
+ *   contains:
+ *   - $forum->is_container: TRUE if the forum can contain other forums. FALSE
+ *     if the forum can contain only topics.
+ *   - $forum->depth: How deep the forum is in the current hierarchy.
+ *   - $forum->zebra: 'even' or 'odd' string used for row class.
+ *   - $forum->icon_class: 'default' or 'new' string used for forum icon class.
+ *   - $forum->icon_title: Text alternative for the forum icon.
+ *   - $forum->name: The name of the forum.
+ *   - $forum->link: The URL to link to this forum.
+ *   - $forum->description: The description of this forum.
+ *   - $forum->new_topics: TRUE if the forum contains unread posts.
+ *   - $forum->new_url: A URL to the forum's unread posts.
+ *   - $forum->new_text: Text for the above URL, which tells how many new posts.
+ *   - $forum->old_topics: A count of posts that have already been read.
+ *   - $forum->num_posts: The total number of posts in the forum.
+ *   - $forum->last_reply: Text representing the last time a forum was posted or
+ *     commented in.
+ * - $forum_id: Forum ID for the current forum. Parent to all items within the
+ *   $forums array.
  *
  * @see template_preprocess_forum_list()
  * @see theme_forum_list()
+ *
+ * @ingroup themeable
  */
 ?>
 <table id="forum-<?php print $forum_id; ?>">
diff --git a/modules/forum/forum-rtl.css b/modules/forum/forum-rtl.css
index 81dd4d396..b475e4286 100644
--- a/modules/forum/forum-rtl.css
+++ b/modules/forum/forum-rtl.css
@@ -1,3 +1,7 @@
+/**
+ * @file
+ * Right-to-left styling for the Forum module.
+ */
 
 #forum td.forum .icon {
   float: right;
diff --git a/modules/forum/forum-submitted.tpl.php b/modules/forum/forum-submitted.tpl.php
index d310448c7..18fea8f1b 100644
--- a/modules/forum/forum-submitted.tpl.php
+++ b/modules/forum/forum-submitted.tpl.php
@@ -2,18 +2,20 @@
 
 /**
  * @file
- * Default theme implementation to format a simple string indicated when and
- * by whom a topic was submitted.
+ * Formats a forum post submission string.
  *
- * Available variables:
+ * The submission string indicates when and by whom a topic was submitted.
  *
+ * Available variables:
  * - $author: The author of the post.
  * - $time: How long ago the post was created.
- * - $topic: An object with the raw data of the post. Unsafe, be sure
- *   to clean this data before printing.
+ * - $topic: An object with the raw data of the post. Potentially unsafe. Be
+ *   sure to clean this data before printing.
  *
  * @see template_preprocess_forum_submitted()
  * @see theme_forum_submitted()
+ *
+ * @ingroup themeable
  */
 ?>
 <?php if ($time): ?>
diff --git a/modules/forum/forum-topic-list.tpl.php b/modules/forum/forum-topic-list.tpl.php
index 33907036f..64278141e 100644
--- a/modules/forum/forum-topic-list.tpl.php
+++ b/modules/forum/forum-topic-list.tpl.php
@@ -2,35 +2,39 @@
 
 /**
  * @file
- * Default theme implementation to display a list of forum topics.
+ * Displays a list of forum topics.
  *
  * Available variables:
  * - $header: The table header. This is pre-generated with click-sorting
  *   information. If you need to change this, see
  *   template_preprocess_forum_topic_list().
  * - $pager: The pager to display beneath the table.
- * - $topics: An array of topics to be displayed.
- * - $topic_id: Numeric id for the current forum topic.
- *
- * Each $topic in $topics contains:
- * - $topic->icon: The icon to display.
- * - $topic->moved: A flag to indicate whether the topic has been moved to
- *   another forum.
- * - $topic->title: The title of the topic. Safe to output.
- * - $topic->message: If the topic has been moved, this contains an
- *   explanation and a link.
- * - $topic->zebra: 'even' or 'odd' string used for row class.
- * - $topic->comment_count: The number of replies on this topic.
- * - $topic->new_replies: A flag to indicate whether there are unread comments.
- * - $topic->new_url: If there are unread replies, this is a link to them.
- * - $topic->new_text: Text containing the translated, properly pluralized count.
- * - $topic->created: An outputtable string represented when the topic was posted.
- * - $topic->last_reply: An outputtable string representing when the topic was
- *   last replied to.
- * - $topic->timestamp: The raw timestamp this topic was posted.
+ * - $topics: An array of topics to be displayed. Each $topic in $topics
+ *   contains:
+ *   - $topic->icon: The icon to display.
+ *   - $topic->moved: A flag to indicate whether the topic has been moved to
+ *     another forum.
+ *   - $topic->title: The title of the topic. Safe to output.
+ *   - $topic->message: If the topic has been moved, this contains an
+ *     explanation and a link.
+ *   - $topic->zebra: 'even' or 'odd' string used for row class.
+ *   - $topic->comment_count: The number of replies on this topic.
+ *   - $topic->new_replies: A flag to indicate whether there are unread
+ *     comments.
+ *   - $topic->new_url: If there are unread replies, this is a link to them.
+ *   - $topic->new_text: Text containing the translated, properly pluralized
+ *     count.
+ *   - $topic->created: A string representing when the topic was posted. Safe
+ *     to output.
+ *   - $topic->last_reply: An outputtable string representing when the topic was
+ *     last replied to.
+ *   - $topic->timestamp: The raw timestamp this topic was posted.
+ * - $topic_id: Numeric ID for the current forum topic.
  *
  * @see template_preprocess_forum_topic_list()
  * @see theme_forum_topic_list()
+ *
+ * @ingroup themeable
  */
 ?>
 <table id="forum-topic-<?php print $topic_id; ?>">
diff --git a/modules/forum/forum.admin.inc b/modules/forum/forum.admin.inc
index 49c71d90a..712cf546e 100644
--- a/modules/forum/forum.admin.inc
+++ b/modules/forum/forum.admin.inc
@@ -2,7 +2,22 @@
 
 /**
  * @file
- * Administrative page callbacks for the forum module.
+ * Administrative page callbacks for the Forum module.
+ */
+
+/**
+ * Page callback: Returns a form for creating a new forum or container.
+ *
+ * @param $type
+ *   What is being added. Possible values are 'forum' and 'container'.
+ * @param $edit
+ *   (optional) Associative array containing a forum term to be edited.
+ *   Defaults to an empty array.
+ *
+ * @return
+ *   A form for creating a new forum or container.
+ *
+ * @see forum_menu()
  */
 function forum_form_main($type, $edit = array()) {
   $edit = (array) $edit;
@@ -20,11 +35,14 @@ function forum_form_main($type, $edit = array()) {
 }
 
 /**
- * Returns a form for adding a forum to the forum vocabulary
+ * Form constructor for adding and editing a forum.
+ *
+ * @param $edit
+ *   (optional) Associative array containing a forum term to be added or edited.
+ *   Defaults to an empty array.
  *
- * @param $edit Associative array containing a forum term to be added or edited.
- * @ingroup forms
  * @see forum_form_submit()
+ * @ingroup forms
  */
 function forum_form_forum($form, &$form_state, $edit = array()) {
   $edit += array(
@@ -67,7 +85,7 @@ function forum_form_forum($form, &$form_state, $edit = array()) {
 }
 
 /**
- * Process forum form and container form submissions.
+ * Form submission handler for forum_form_forum() and forum_form_container().
  */
 function forum_form_submit($form, &$form_state) {
   if ($form['form_id']['#value'] == 'forum_form_container') {
@@ -104,8 +122,8 @@ function forum_form_submit($form, &$form_state) {
 /**
  * Returns HTML for a forum form.
  *
- * By default this does not alter the appearance of a form at all,
- * but is provided as a convenience for themers.
+ * By default this does not alter the appearance of a form at all, but is
+ * provided as a convenience for themers.
  *
  * @param $variables
  *   An associative array containing:
@@ -118,11 +136,14 @@ function theme_forum_form($variables) {
 }
 
 /**
- * Returns a form for adding a container to the forum vocabulary
+ * Form constructor for adding and editing forum containers.
+ *
+ * @param $edit
+ *   (optional) Associative array containing a container term to be added or edited.
+ *   Defaults to an empty array.
  *
- * @param $edit Associative array containing a container term to be added or edited.
- * @ingroup forms
  * @see forum_form_submit()
+ * @ingroup forms
  */
 function forum_form_container($form, &$form_state, $edit = array()) {
   $edit += array(
@@ -176,9 +197,13 @@ function forum_form_container($form, &$form_state, $edit = array()) {
 }
 
 /**
- * Returns a confirmation page for deleting a forum taxonomy term.
+ * Form constructor for confirming deletion of a forum taxonomy term.
+ *
+ * @param $tid
+ *   ID of the term to be deleted.
  *
- * @param $tid ID of the term to be deleted
+ * @see forum_confirm_delete_submit()
+ * @ingroup forms
  */
 function forum_confirm_delete($form, &$form_state, $tid) {
   $term = taxonomy_term_load($tid);
@@ -190,7 +215,7 @@ function forum_confirm_delete($form, &$form_state, $tid) {
 }
 
 /**
- * Implement forms api _submit call. Deletes a forum after confirmation.
+ * Form submission handler for forum_confirm_delete().
  */
 function forum_confirm_delete_submit($form, &$form_state) {
   taxonomy_term_delete($form_state['values']['tid']);
@@ -202,9 +227,11 @@ function forum_confirm_delete_submit($form, &$form_state) {
 }
 
 /**
- * Form builder for the forum settings page.
+ * Form constructor for the forum settings page.
  *
+ * @see forum_menu()
  * @see system_settings_form()
+ * @ingroup forms
  */
 function forum_admin_settings($form) {
   $number = drupal_map_assoc(array(5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 80, 100, 150, 200, 250, 300, 350, 400, 500));
@@ -232,7 +259,13 @@ function forum_admin_settings($form) {
 }
 
 /**
- * Returns an overview list of existing forums and containers
+ * Form constructor for the forum overview form.
+ *
+ * Returns a form for controlling the hierarchy of existing forums and
+ * containers.
+ *
+ * @see forum_menu()
+ * @ingroup forms
  */
 function forum_overview($form, &$form_state) {
   module_load_include('inc', 'taxonomy', 'taxonomy.admin');
@@ -267,11 +300,17 @@ function forum_overview($form, &$form_state) {
 }
 
 /**
- * Returns a select box for available parent terms
+ * Returns a select box for available parent terms.
+ *
+ * @param $tid
+ *   ID of the term that is being added or edited.
+ * @param $title
+ *   Title for the select box.
+ * @param $child_type
+ *   Whether the child is a forum or a container.
  *
- * @param $tid ID of the term which is being added or edited
- * @param $title Title to display the select box with
- * @param $child_type Whether the child is forum or container
+ * @return
+ *   A select form element.
  */
 function _forum_parent_select($tid, $title, $child_type) {
 
diff --git a/modules/forum/forum.css b/modules/forum/forum.css
index 4a67c8bcd..a758bc666 100644
--- a/modules/forum/forum.css
+++ b/modules/forum/forum.css
@@ -1,3 +1,7 @@
+/**
+ * @file
+ * Styling for the Forum module.
+ */
 
 #forum .description {
   font-size: 0.9em;
diff --git a/modules/forum/forum.info b/modules/forum/forum.info
index e05cd92b4..26af81d69 100644
--- a/modules/forum/forum.info
+++ b/modules/forum/forum.info
@@ -9,8 +9,8 @@ files[] = forum.test
 configure = admin/structure/forum
 stylesheets[all][] = forum.css
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/forum/forum.install b/modules/forum/forum.install
index 32a9bb90d..57e116b71 100644
--- a/modules/forum/forum.install
+++ b/modules/forum/forum.install
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Install, update and uninstall functions for the forum module.
+ * Install, update, and uninstall functions for the Forum module.
  */
 
 /**
@@ -219,6 +219,8 @@ function forum_schema() {
     ),
     'indexes' => array(
       'forum_topics' => array('nid', 'tid', 'sticky', 'last_comment_timestamp'),
+      'created' => array('created'),
+      'last_comment_timestamp' => array('last_comment_timestamp'),
     ),
     'foreign keys' => array(
       'tracked_node' => array(
@@ -349,6 +351,11 @@ function forum_update_7001() {
     ->execute();
 }
 
+/**
+ * @addtogroup updates-7.x-extra
+ * @{
+ */
+
 /**
  * Add new index to forum_index table.
  */
@@ -357,11 +364,6 @@ function forum_update_7002() {
   db_add_index('forum_index', 'forum_topics', array('nid', 'tid', 'sticky', 'last_comment_timestamp'));
 }
 
-/**
- * @addtogroup updates-7.x-extra
- * @{
- */
-
 /**
  * Rename field to 'taxonomy_forums'.
  */
@@ -440,11 +442,7 @@ function forum_update_7003() {
 }
 
 /**
- * @} End of "addtogroup updates-7.x-extra"
- */
-
-/**
- * Update {form_index} so that only published nodes are indexed.
+ * Update {forum_index} so that only published nodes are indexed.
  */
 function forum_update_7011() {
   $select = db_select('node', 'n')
@@ -455,3 +453,15 @@ function forum_update_7011() {
     ->condition('nid', $select, 'IN')
     ->execute();
 }
+
+/**
+ * Add 'created' and 'last_comment_timestamp' indexes.
+ */
+function forum_update_7012() {
+  db_add_index('forum_index', 'created', array('created'));
+  db_add_index('forum_index', 'last_comment_timestamp', array('last_comment_timestamp'));
+}
+
+/**
+ * @} End of "addtogroup updates-7.x-extra".
+ */
diff --git a/modules/forum/forum.module b/modules/forum/forum.module
index eddac7978..7e8d81bde 100644
--- a/modules/forum/forum.module
+++ b/modules/forum/forum.module
@@ -233,7 +233,7 @@ function forum_entity_info_alter(&$info) {
 }
 
 /**
- * Entity URI callback.
+ * Entity URI callback used in forum_entity_info_alter().
  */
 function forum_uri($forum) {
   return array(
@@ -242,7 +242,7 @@ function forum_uri($forum) {
 }
 
 /**
- * Check whether a content type can be used in a forum.
+ * Checks whether a node can be used in a forum, based on its content type.
  *
  * @param $node
  *   A node object.
@@ -283,7 +283,8 @@ function forum_node_view($node, $view_mode) {
 /**
  * Implements hook_node_validate().
  *
- * Check in particular that only a "leaf" term in the associated taxonomy.
+ * Checks in particular that the node is assigned only a "leaf" term in the
+ * forum taxonomy.
  */
 function forum_node_validate($node, $form) {
   if (_forum_node_check_node_type($node)) {
@@ -319,7 +320,7 @@ function forum_node_validate($node, $form) {
 /**
  * Implements hook_node_presave().
  *
- * Assign forum taxonomy when adding a topic from within a forum.
+ * Assigns the forum taxonomy when adding a topic from within a forum.
  */
 function forum_node_presave($node) {
   if (_forum_node_check_node_type($node)) {
@@ -481,7 +482,7 @@ function forum_taxonomy_term_delete($term) {
 /**
  * Implements hook_comment_publish().
  *
- * This actually handles the insert and update of published nodes since
+ * This actually handles the insertion and update of published nodes since
  * comment_save() calls hook_comment_publish() for all published comments.
  */
 function forum_comment_publish($comment) {
@@ -491,12 +492,12 @@ function forum_comment_publish($comment) {
 /**
  * Implements hook_comment_update().
  *
- * Comment module doesn't call hook_comment_unpublish() when saving individual
- * comments so we need to check for those here.
+ * The Comment module doesn't call hook_comment_unpublish() when saving
+ * individual comments, so we need to check for those here.
  */
 function forum_comment_update($comment) {
-  // comment_save() calls hook_comment_publish() for all published comments
-  // so we to handle all other values here.
+  // comment_save() calls hook_comment_publish() for all published comments,
+  // so we need to handle all other values here.
   if (!$comment->status) {
     _forum_update_forum_index($comment->nid);
   }
@@ -669,8 +670,8 @@ function forum_block_save($delta = '', $edit = array()) {
 /**
  * Implements hook_block_view().
  *
- * Generates a block containing the currently active forum topics and the
- * most recently added forum topics.
+ * Generates a block containing the currently active forum topics and the most
+ * recently added forum topics.
  */
 function forum_block_view($delta = '') {
   $query = db_select('forum_index', 'f')
@@ -700,13 +701,12 @@ function forum_block_view($delta = '') {
 }
 
 /**
-* A #pre_render callback. Lists nodes based on the element's #query property.
-*
-* @see forum_block_view()
-*
-* @return
-*   A renderable array.
-*/
+ * Render API callback: Lists nodes based on the element's #query property.
+ *
+ * This function can be used as a #pre_render callback.
+ *
+ * @see forum_block_view()
+ */
 function forum_block_view_pre_render($elements) {
   $result = $elements['#query']->execute();
   if ($node_title_list = node_title_list($result)) {
@@ -730,7 +730,7 @@ function forum_form($node, $form_state) {
 
   if (!empty($node->nid)) {
     $forum_terms = $node->taxonomy_forums;
-    // If editing, give option to leave shadows
+    // If editing, give option to leave shadows.
     $shadow = (count($forum_terms) > 1);
     $form['shadow'] = array('#type' => 'checkbox', '#title' => t('Leave shadow copy'), '#default_value' => $shadow, '#description' => t('If you move this topic, you can leave a link in the old forum to the new forum.'));
     $form['forum_tid'] = array('#type' => 'value', '#value' => $node->forum_tid);
@@ -743,13 +743,15 @@ function forum_form($node, $form_state) {
  * Returns a tree of all forums for a given taxonomy term ID.
  *
  * @param $tid
- *    (optional) Taxonomy ID of the forum, if not givin all forums will be returned.
+ *   (optional) Taxonomy term ID of the forum. If not given all forums will be
+ *   returned.
+ *
  * @return
  *   A tree of taxonomy objects, with the following additional properties:
- *    - 'num_topics': Number of topics in the forum
- *    - 'num_posts': Total number of posts in all topics
- *    - 'last_post': Most recent post for the forum
- *    - 'forums': An array of child forums
+ *   - num_topics: Number of topics in the forum.
+ *   - num_posts: Total number of posts in all topics.
+ *   - last_post: Most recent post for the forum.
+ *   - forums: An array of child forums.
  */
 function forum_forum_load($tid = NULL) {
   $cache = &drupal_static(__FUNCTION__, array());
@@ -857,8 +859,17 @@ function forum_forum_load($tid = NULL) {
 }
 
 /**
- * Calculate the number of nodes the user has not yet read and are newer
- * than NODE_NEW_LIMIT.
+ * Calculates the number of new posts in a forum that the user has not yet read.
+ *
+ * Nodes are new if they are newer than NODE_NEW_LIMIT.
+ *
+ * @param $term
+ *   The term ID of the forum.
+ * @param $uid
+ *   The user ID.
+ *
+ * @return
+ *   The number of new posts in the forum that have not been read by the user.
  */
 function _forum_topics_unread($term, $uid) {
   $query = db_select('node', 'n');
@@ -874,6 +885,23 @@ function _forum_topics_unread($term, $uid) {
     ->fetchField();
 }
 
+/**
+ * Gets all the topics in a forum.
+ *
+ * @param $tid
+ *   The term ID of the forum.
+ * @param $sortby
+ *   One of the following integers indicating the sort criteria:
+ *   - 1: Date - newest first.
+ *   - 2: Date - oldest first.
+ *   - 3: Posts with the most comments first.
+ *   - 4: Posts with the least comments first.
+ * @param $forum_per_page
+ *   The maximum number of topics to display per page.
+ *
+ * @return
+ *   A list of all the topics in a forum.
+ */
 function forum_get_topics($tid, $sortby, $forum_per_page) {
   global $user, $forum_topic_list_header;
 
@@ -944,7 +972,8 @@ function forum_get_topics($tid, $sortby, $forum_per_page) {
   $first_new_found = FALSE;
   foreach ($result as $topic) {
     if ($user->uid) {
-      // folder is new if topic is new or there are new comments since last visit
+      // A forum is new if the topic is new, or if there are new comments since
+      // the user's last visit.
       if ($topic->forum_tid != $tid) {
         $topic->new = 0;
       }
@@ -981,15 +1010,22 @@ function forum_get_topics($tid, $sortby, $forum_per_page) {
 }
 
 /**
- * Process variables for forums.tpl.php
+ * Preprocesses variables for forums.tpl.php.
  *
- * The $variables array contains the following arguments:
- * - $forums
- * - $topics
- * - $parents
- * - $tid
- * - $sortby
- * - $forum_per_page
+ * @param $variables
+ *   An array containing the following elements:
+ *   - forums: An array of all forum objects to display for the given taxonomy
+ *     term ID. If tid = 0 then all the top-level forums are displayed.
+ *   - topics: An array of all the topics in the current forum.
+ *   - parents: An array of taxonomy term objects that are ancestors of the
+ *     current term ID.
+ *   - tid: Taxonomy term ID of the current forum.
+ *   - sortby: One of the following integers indicating the sort criteria:
+ *     - 1: Date - newest first.
+ *     - 2: Date - oldest first.
+ *     - 3: Posts with the most comments first.
+ *     - 4: Posts with the least comments first.
+ *   - forum_per_page: The maximum number of topics to display per page.
  *
  * @see forums.tpl.php
  */
@@ -1060,12 +1096,15 @@ function template_preprocess_forums(&$variables) {
 }
 
 /**
- * Process variables to format a forum listing.
+ * Preprocesses variables for forum-list.tpl.php.
  *
- * $variables contains the following information:
- * - $forums
- * - $parents
- * - $tid
+ * @param $variables
+ *   An array containing the following elements:
+ *   - forums: An array of all forum objects to display for the given taxonomy
+ *     term ID. If tid = 0 then all the top-level forums are displayed.
+ *   - parents: An array of taxonomy term objects that are ancestors of the
+ *     current term ID.
+ *   - tid: Taxonomy term ID of the current forum.
  *
  * @see forum-list.tpl.php
  * @see theme_forum_list()
@@ -1106,13 +1145,13 @@ function template_preprocess_forum_list(&$variables) {
 }
 
 /**
- * Preprocess variables to format the topic listing.
+ * Preprocesses variables for forum-topic-list.tpl.php.
  *
- * $variables contains the following data:
- * - $tid
- * - $topics
- * - $sortby
- * - $forum_per_page
+ * @param $variables
+ *   An array containing the following elements:
+ *   - tid: Taxonomy term ID of the current forum.
+ *   - topics: An array of all the topics in the current forum.
+ *   - forum_per_page: The maximum number of topics to display per page.
  *
  * @see forum-topic-list.tpl.php
  * @see theme_forum_topic_list()
@@ -1162,7 +1201,7 @@ function template_preprocess_forum_topic_list(&$variables) {
     }
   }
   else {
-    // Make this safe for the template
+    // Make this safe for the template.
     $variables['topics'] = array();
   }
   // Give meaning to $tid for themers. $tid actually stands for term id.
@@ -1173,14 +1212,16 @@ function template_preprocess_forum_topic_list(&$variables) {
 }
 
 /**
- * Process variables to format the icon for each individual topic.
+ * Preprocesses variables for forum-icon.tpl.php.
  *
- * $variables contains the following data:
- * - $new_posts
- * - $num_posts = 0
- * - $comment_mode = 0
- * - $sticky = 0
- * - $first_new
+ * @param $variables
+ *   An array containing the following elements:
+ *   - new_posts: Indicates whether or not the topic contains new posts.
+ *   - num_posts: The total number of posts in all topics.
+ *   - comment_mode: An integer indicating whether comments are open, closed,
+ *     or hidden.
+ *   - sticky: Indicates whether the topic is sticky.
+ *   - first_new: Indicates whether this is the first topic with new posts.
  *
  * @see forum-icon.tpl.php
  * @see theme_forum_icon()
@@ -1208,9 +1249,14 @@ function template_preprocess_forum_icon(&$variables) {
 }
 
 /**
- * Process variables to format submission info for display in the forum list and topic list.
+ * Preprocesses variables for forum-submitted.tpl.php.
+ *
+ * The submission information will be displayed in the forum list and topic
+ * list.
  *
- * $variables will contain: $topic
+ * @param $variables
+ *   An array containing the following elements:
+ *   - topic: The topic object.
  *
  * @see forum-submitted.tpl.php
  * @see theme_forum_submitted()
@@ -1220,6 +1266,16 @@ function template_preprocess_forum_submitted(&$variables) {
   $variables['time'] = isset($variables['topic']->created) ? format_interval(REQUEST_TIME - $variables['topic']->created) : '';
 }
 
+/**
+ * Gets the last time the user viewed a node.
+ *
+ * @param $nid
+ *   The node ID.
+ *
+ * @return
+ *   The timestamp when the user last viewed this node, if the user has
+ *   previously viewed the node; otherwise NODE_NEW_LIMIT.
+ */
 function _forum_user_last_visit($nid) {
   global $user;
   $history = &drupal_static(__FUNCTION__, array());
@@ -1233,6 +1289,21 @@ function _forum_user_last_visit($nid) {
   return isset($history[$nid]) ? $history[$nid] : NODE_NEW_LIMIT;
 }
 
+/**
+ * Gets topic sorting information based on an integer code.
+ *
+ * @param $sortby
+ *   One of the following integers indicating the sort criteria:
+ *   - 1: Date - newest first.
+ *   - 2: Date - oldest first.
+ *   - 3: Posts with the most comments first.
+ *   - 4: Posts with the least comments first.
+ *
+ * @return
+ *   An array with the following values:
+ *   - field: A field for an SQL query.
+ *   - sort: 'asc' or 'desc'.
+ */
 function _forum_get_topic_order($sortby) {
   switch ($sortby) {
     case 1:
diff --git a/modules/forum/forum.pages.inc b/modules/forum/forum.pages.inc
index 29307e719..8538310ac 100644
--- a/modules/forum/forum.pages.inc
+++ b/modules/forum/forum.pages.inc
@@ -2,11 +2,20 @@
 
 /**
  * @file
- * User page callbacks for the forum module.
+ * User page callbacks for the Forum module.
  */
 
 /**
- * Menu callback; prints a forum listing.
+ * Page callback: Prints a forum listing.
+ *
+ * @param $forum_term
+ *   A tree of all forums for a given taxonomy term ID. Defaults to NULL. See
+ *   the return object of forum_forum_load() for a complete definition.
+ *
+ * @return
+ *   A string containing HTML representing the themed forum listing.
+ *
+ * @see forum_menu()
  */
 function forum_page($forum_term = NULL) {
   if (!isset($forum_term)) {
diff --git a/modules/forum/forum.test b/modules/forum/forum.test
index 612b09cff..d78d962de 100644
--- a/modules/forum/forum.test
+++ b/modules/forum/forum.test
@@ -5,14 +5,49 @@
  * Tests for forum.module.
  */
 
+/**
+ * Provides automated tests for the Forum module.
+ */
 class ForumTestCase extends DrupalWebTestCase {
+
+  /**
+   * A user with various administrative privileges.
+   */
   protected $admin_user;
+
+  /**
+   * A user that can create forum topics and edit its own topics.
+   */
   protected $edit_own_topics_user;
+
+  /**
+   * A user that can create, edit, and delete forum topics.
+   */
   protected $edit_any_topics_user;
+
+  /**
+   * A user with no special privileges.
+   */
   protected $web_user;
+
+  /**
+   * An array representing a container.
+   */
   protected $container;
+
+  /**
+   * An array representing a forum.
+   */
   protected $forum;
+
+  /**
+   * An array representing a root forum.
+   */
   protected $root_forum;
+
+  /**
+   * An array of forum topic node IDs.
+   */
   protected $nids;
 
   public static function getInfo() {
@@ -23,9 +58,6 @@ class ForumTestCase extends DrupalWebTestCase {
     );
   }
 
-  /**
-   * Enable modules and create users with specific permissions.
-   */
   function setUp() {
     parent::setUp('taxonomy', 'comment', 'forum');
     // Create users.
@@ -53,12 +85,12 @@ class ForumTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Tests disabling and re-enabling forum.
+   * Tests disabling and re-enabling the Forum module.
    */
   function testEnableForumField() {
     $this->drupalLogin($this->admin_user);
 
-    // Disable the forum module.
+    // Disable the Forum module.
     $edit = array();
     $edit['modules[Core][forum][enable]'] = FALSE;
     $this->drupalPost('admin/modules', $edit, t('Save configuration'));
@@ -66,7 +98,7 @@ class ForumTestCase extends DrupalWebTestCase {
     module_list(TRUE);
     $this->assertFalse(module_exists('forum'), t('Forum module is not enabled.'));
 
-    // Attempt to re-enable the forum module and ensure it does not try to
+    // Attempt to re-enable the Forum module and ensure it does not try to
     // recreate the taxonomy_forums field.
     $edit = array();
     $edit['modules[Core][forum][enable]'] = 'forum';
@@ -77,7 +109,7 @@ class ForumTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Login users, create forum nodes, and test forum functionality through the admin and user interfaces.
+   * Tests forum functionality through the admin and user interfaces.
    */
   function testForum() {
     //Check that the basic forum install creates a default forum topic
@@ -168,7 +200,10 @@ class ForumTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Forum nodes should not be created without choosing forum from select list.
+   * Tests that forum nodes can't be added without a parent.
+   *
+   * Verifies that forum nodes are not created without choosing "forum" from the
+   * select list.
    */
   function testAddOrphanTopic() {
     // Must remove forum topics to test creating orphan topics.
@@ -190,9 +225,10 @@ class ForumTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Run admin tests on the admin user.
+   * Runs admin tests on the admin user.
    *
-   * @param object $user The logged in user.
+   * @param object $user
+   *   The logged in user.
    */
   private function doAdminTests($user) {
     // Login the user.
@@ -270,7 +306,7 @@ class ForumTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Edit the forum taxonomy.
+   * Edits the forum taxonomy.
    */
   function editForumTaxonomy() {
     // Backup forum taxonomy.
@@ -308,15 +344,16 @@ class ForumTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Create a forum container or a forum.
+   * Creates a forum container or a forum.
    *
    * @param $type
-   *   Forum type (forum container or forum).
+   *   The forum type (forum container or forum).
    * @param $parent
-   *   Forum parent (default = 0 = a root forum; >0 = a forum container or
+   *   The forum parent. This defaults to 0, indicating a root forum.
    *   another forum).
+   *
    * @return
-   *   taxonomy_term_data created.
+   *   The created taxonomy term data.
    */
   function createForum($type, $parent = 0) {
     // Generate a random name/description.
@@ -349,7 +386,7 @@ class ForumTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Delete a forum.
+   * Deletes a forum.
    *
    * @param $tid
    *   The forum ID.
@@ -370,7 +407,7 @@ class ForumTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Run basic tests on the indicated user.
+   * Runs basic tests on the indicated user.
    *
    * @param $user
    *   The logged in user.
@@ -389,15 +426,15 @@ class ForumTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Create forum topic.
+   * Creates forum topic.
    *
    * @param array $forum
-   *   Forum array.
+   *   A forum array.
    * @param boolean $container
-   *   True if $forum is a container.
+   *   TRUE if $forum is a container; FALSE otherwise.
    *
    * @return object
-   *   Topic node created.
+   *   The created topic node.
    */
   function createForumTopic($forum, $container = FALSE) {
     // Generate a random subject/body.
@@ -439,7 +476,7 @@ class ForumTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Verify the logged in user has access to a forum nodes.
+   * Verifies that the logged in user has access to a forum nodes.
    *
    * @param $node_user
    *   The user who creates the node.
@@ -519,10 +556,12 @@ class ForumTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Verify display of forum page.
+   * Verifies display of forum page.
    *
    * @param $forum
-   *   A row from taxonomy_term_data table in array.
+   *   A row from the taxonomy_term_data table in an array.
+   * @param $parent
+   *   (optional) An array representing the forum's parent.
    */
   private function verifyForumView($forum, $parent = NULL) {
     // View forum page.
@@ -542,9 +581,10 @@ class ForumTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Generate forum topics to test display of active forum block.
+   * Generates forum topics to test the display of an active forum block.
    *
-   * @param array $forum Forum array (a row from taxonomy_term_data table).
+   * @param array $forum
+   *   The foorum array (a row from taxonomy_term_data table).
    */
   private function generateForumTopics($forum) {
     $this->nids = array();
@@ -555,10 +595,10 @@ class ForumTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * View forum topics to test display of active forum block.
+   * Views forum topics to test the display of an active forum block.
    *
-   * @todo The logic here is completely incorrect, since the active
-   * forum topics block is determined by comments on the node, not by views.
+   * @todo The logic here is completely incorrect, since the active forum topics
+   *   block is determined by comments on the node, not by views.
    * @todo DIE
    *
    * @param $nids
diff --git a/modules/forum/forums.tpl.php b/modules/forum/forums.tpl.php
index 55a760f57..6a0e02e66 100644
--- a/modules/forum/forums.tpl.php
+++ b/modules/forum/forums.tpl.php
@@ -2,16 +2,18 @@
 
 /**
  * @file
- * Default theme implementation to display a forum which may contain forum
- * containers as well as forum topics.
+ * Displays a forum.
  *
- * Variables available:
- * - $forums: The forums to display (as processed by forum-list.tpl.php)
- * - $topics: The topics to display (as processed by forum-topic-list.tpl.php)
+ * May contain forum containers as well as forum topics.
+ *
+ * Available variables:
+ * - $forums: The forums to display (as processed by forum-list.tpl.php).
+ * - $topics: The topics to display (as processed by forum-topic-list.tpl.php).
  * - $forums_defined: A flag to indicate that the forums are configured.
  *
  * @see template_preprocess_forums()
- * @see theme_forums()
+ *
+ * @ingroup themeable
  */
 ?>
 <?php if ($forums_defined): ?>
diff --git a/modules/help/help.info b/modules/help/help.info
index a973965cc..f92f0b9d7 100644
--- a/modules/help/help.info
+++ b/modules/help/help.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 files[] = help.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/image/image.admin.inc b/modules/image/image.admin.inc
index abcfab449..ab99a49e8 100644
--- a/modules/image/image.admin.inc
+++ b/modules/image/image.admin.inc
@@ -292,7 +292,7 @@ function image_style_name_validate($element, $form_state) {
  * @ingroup forms
  * @see image_style_delete_form_submit()
  */
-function image_style_delete_form($form, $form_state, $style) {
+function image_style_delete_form($form, &$form_state, $style) {
   $form_state['image_style'] = $style;
 
   $replacement_styles = array_diff_key(image_style_options(), array($style['name'] => ''));
diff --git a/modules/image/image.field.inc b/modules/image/image.field.inc
index 078f83fcc..5e80d88a7 100644
--- a/modules/image/image.field.inc
+++ b/modules/image/image.field.inc
@@ -204,11 +204,11 @@ function image_field_prepare_view($entity_type, $entities, $field, $instances, $
     if (empty($items[$id])) {
       $fid = 0;
       // Use the default for the instance if one is available.
-      if ($instances[$id]['settings']['default_image']) {
+      if (!empty($instances[$id]['settings']['default_image'])) {
         $fid = $instances[$id]['settings']['default_image'];
       }
       // Otherwise, use the default for the field.
-      elseif ($field['settings']['default_image']) {
+      elseif (!empty($field['settings']['default_image'])) {
         $fid = $field['settings']['default_image'];
       }
 
diff --git a/modules/image/image.info b/modules/image/image.info
index ea3c2800c..b7b55c460 100644
--- a/modules/image/image.info
+++ b/modules/image/image.info
@@ -7,8 +7,8 @@ dependencies[] = file
 files[] = image.test
 configure = admin/config/media/image-styles
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/image/image.install b/modules/image/image.install
index 5595a335d..b7aac7152 100644
--- a/modules/image/image.install
+++ b/modules/image/image.install
@@ -253,6 +253,11 @@ function image_update_7000() {
   }
 }
 
+/**
+ * @addtogroup updates-7.x-extra
+ * @{
+ */
+
 /**
  * Rename possibly misnamed {image_effect} table to {image_effects}.
  */
@@ -442,6 +447,10 @@ function image_update_7004() {
   }
 }
 
+/**
+ * @} End of "addtogroup updates-7.x-extra".
+ */
+
 /**
  * Implements hook_requirements() to check the PHP GD Library.
  *
diff --git a/modules/image/tests/image_module_test.info b/modules/image/tests/image_module_test.info
index f94bb2575..d9a756bad 100644
--- a/modules/image/tests/image_module_test.info
+++ b/modules/image/tests/image_module_test.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = image_module_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/locale/locale.datepicker.js b/modules/locale/locale.datepicker.js
index 81f1e17b3..f81928238 100644
--- a/modules/locale/locale.datepicker.js
+++ b/modules/locale/locale.datepicker.js
@@ -1,69 +1,79 @@
 (function ($) {
 
-$.datepicker.regional['drupal-locale'] = {
-  closeText: Drupal.t('Done'),
-  prevText: Drupal.t('Prev'),
-  nextText: Drupal.t('Next'),
-  currentText: Drupal.t('Today'),
-  monthNames: [
-    Drupal.t('January'),
-    Drupal.t('February'),
-    Drupal.t('March'),
-    Drupal.t('April'),
-    Drupal.t('May'),
-    Drupal.t('June'),
-    Drupal.t('July'),
-    Drupal.t('August'),
-    Drupal.t('September'),
-    Drupal.t('October'),
-    Drupal.t('November'),
-    Drupal.t('December')
-  ],
-  monthNamesShort: [
-    Drupal.t('Jan'),
-    Drupal.t('Feb'),
-    Drupal.t('Mar'),
-    Drupal.t('Apr'),
-    Drupal.t('May'),
-    Drupal.t('Jun'),
-    Drupal.t('Jul'),
-    Drupal.t('Aug'),
-    Drupal.t('Sep'),
-    Drupal.t('Oct'),
-    Drupal.t('Nov'),
-    Drupal.t('Dec')
-  ],
-  dayNames: [
-    Drupal.t('Sunday'),
-    Drupal.t('Monday'),
-    Drupal.t('Tuesday'),
-    Drupal.t('Wednesday'),
-    Drupal.t('Thursday'),
-    Drupal.t('Friday'),
-    Drupal.t('Saturday')
-  ],
-  dayNamesShort: [
-    Drupal.t('Sun'),
-    Drupal.t('Mon'),
-    Drupal.t('Tue'),
-    Drupal.t('Wed'),
-    Drupal.t('Thu'),
-    Drupal.t('Fri'),
-    Drupal.t('Sat')
-  ],
-  dayNamesMin: [
-    Drupal.t('Su'),
-    Drupal.t('Mo'),
-    Drupal.t('Tu'),
-    Drupal.t('We'),
-    Drupal.t('Th'),
-    Drupal.t('Fr'),
-    Drupal.t('Sa')
-  ],
-  dateFormat: Drupal.t('mm/dd/yy'),
-  firstDay: Drupal.settings.jqueryuidatepicker.firstDay,
-  isRTL: Drupal.settings.jqueryuidatepicker.rtl
+/**
+ * Attaches language support to the jQuery UI datepicker component.
+ */
+Drupal.behaviors.localeDatepicker = {
+  attach: function(context, settings) {
+    // This code accesses Drupal.settings and localized strings via Drupal.t().
+    // So this code should run after these are initialized. By placing it in an
+    // attach behavior this is assured.
+    $.datepicker.regional['drupal-locale'] = $.extend({
+      closeText: Drupal.t('Done'),
+      prevText: Drupal.t('Prev'),
+      nextText: Drupal.t('Next'),
+      currentText: Drupal.t('Today'),
+      monthNames: [
+        Drupal.t('January'),
+        Drupal.t('February'),
+        Drupal.t('March'),
+        Drupal.t('April'),
+        Drupal.t('May'),
+        Drupal.t('June'),
+        Drupal.t('July'),
+        Drupal.t('August'),
+        Drupal.t('September'),
+        Drupal.t('October'),
+        Drupal.t('November'),
+        Drupal.t('December')
+      ],
+      monthNamesShort: [
+        Drupal.t('Jan'),
+        Drupal.t('Feb'),
+        Drupal.t('Mar'),
+        Drupal.t('Apr'),
+        Drupal.t('May'),
+        Drupal.t('Jun'),
+        Drupal.t('Jul'),
+        Drupal.t('Aug'),
+        Drupal.t('Sep'),
+        Drupal.t('Oct'),
+        Drupal.t('Nov'),
+        Drupal.t('Dec')
+      ],
+      dayNames: [
+        Drupal.t('Sunday'),
+        Drupal.t('Monday'),
+        Drupal.t('Tuesday'),
+        Drupal.t('Wednesday'),
+        Drupal.t('Thursday'),
+        Drupal.t('Friday'),
+        Drupal.t('Saturday')
+      ],
+      dayNamesShort: [
+        Drupal.t('Sun'),
+        Drupal.t('Mon'),
+        Drupal.t('Tue'),
+        Drupal.t('Wed'),
+        Drupal.t('Thu'),
+        Drupal.t('Fri'),
+        Drupal.t('Sat')
+      ],
+      dayNamesMin: [
+        Drupal.t('Su'),
+        Drupal.t('Mo'),
+        Drupal.t('Tu'),
+        Drupal.t('We'),
+        Drupal.t('Th'),
+        Drupal.t('Fr'),
+        Drupal.t('Sa')
+      ],
+      dateFormat: Drupal.t('mm/dd/yy'),
+      firstDay: 0,
+      isRTL: 0
+    }, Drupal.settings.jquery.ui.datepicker);
+    $.datepicker.setDefaults($.datepicker.regional['drupal-locale']);
+  }
 };
-$.datepicker.setDefaults($.datepicker.regional['drupal-locale']);
 
 })(jQuery);
diff --git a/modules/locale/locale.info b/modules/locale/locale.info
index 337223963..37d871d67 100644
--- a/modules/locale/locale.info
+++ b/modules/locale/locale.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = locale.test
 configure = admin/config/regional/language
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/locale/locale.install b/modules/locale/locale.install
index cb7cefe01..2d94c7170 100644
--- a/modules/locale/locale.install
+++ b/modules/locale/locale.install
@@ -126,21 +126,21 @@ function locale_update_7002() {
 }
 
 /**
- * Update "language_count" variable.
+ * @} End of "addtogroup updates-6.x-to-7.x".
  */
-function locale_update_7003() {
-  $languages = language_list('enabled');
-  variable_set('language_count', count($languages[1]));
-}
 
 /**
- * @} End of "addtogroup updates-6.x-to-7.x"
+ * @addtogroup updates-7.x-extra
+ * @{
  */
 
 /**
- * @addtogroup updates-7.x-extra
- * @{
+ * Update "language_count" variable.
  */
+function locale_update_7003() {
+  $languages = language_list('enabled');
+  variable_set('language_count', count($languages[1]));
+}
 
 /**
  * Remove duplicates in {locales_source}.
@@ -202,7 +202,7 @@ function locale_update_7004() {
 }
 
 /**
- * @} End of "addtogroup updates-7.x-extra"
+ * @} End of "addtogroup updates-7.x-extra".
  */
 
 /**
diff --git a/modules/locale/locale.module b/modules/locale/locale.module
index e0981b2fb..a20f3d5d7 100644
--- a/modules/locale/locale.module
+++ b/modules/locale/locale.module
@@ -396,7 +396,7 @@ function locale_form_node_form_alter(&$form, &$form_state) {
 function locale_field_node_form_submit($form, &$form_state) {
   if (field_has_translation_handler('node', 'locale')) {
     $node = (object) $form_state['values'];
-    $available_languages = field_content_languages();
+    $current_language = entity_language('node', $node);
     list(, , $bundle) = entity_extract_ids('node', $node);
 
     foreach (field_info_instances('node', $bundle) as $instance) {
@@ -406,8 +406,8 @@ function locale_field_node_form_submit($form, &$form_state) {
 
       // Handle a possible language change: new language values are inserted,
       // previous ones are deleted.
-      if ($field['translatable'] && $previous_language != $node->language) {
-        $form_state['values'][$field_name][$node->language] = $node->{$field_name}[$previous_language];
+      if ($field['translatable'] && $previous_language != $current_language) {
+        $form_state['values'][$field_name][$current_language] = $node->{$field_name}[$previous_language];
         $form_state['values'][$field_name][$previous_language] = array();
       }
     }
@@ -758,9 +758,8 @@ function locale_get_plural($count, $langcode = NULL) {
   if (!isset($plural_indexes[$langcode][$count])) {
     // Retrieve and statically cache the plural formulas for all languages.
     if (empty($plural_formulas)) {
-      $language_list = language_list();
-      foreach ($language_list as $langcode => $lang) {
-        $plural_formulas[$langcode] = $lang->formula;
+      foreach (language_list() as $installed_language) {
+        $plural_formulas[$installed_language->language] = $installed_language->formula;
       }
     }
     // If there is a plural formula for the language, evaluate it for the given
@@ -951,15 +950,22 @@ function locale_css_alter(&$css) {
  * Provides the language support for the jQuery UI Date Picker.
  */
 function locale_library_alter(&$libraries, $module) {
-  global $language;
-  if ($module == 'system' && isset($libraries['system']['ui.datepicker'])) {
+  if ($module == 'system' && isset($libraries['ui.datepicker'])) {
+    global $language;
+    // locale.datepicker.js should be added in the JS_LIBRARY group, so that
+    // this attach behavior will execute early. JS_LIBRARY is the default for
+    // hook_library_info_alter(), thus does not have to be specified explicitly.
     $datepicker = drupal_get_path('module', 'locale') . '/locale.datepicker.js';
-    $libraries['system']['ui.datepicker']['js'][$datepicker] = array('group' => JS_THEME);
-    $libraries['system']['ui.datepicker']['js'][] = array(
+    $libraries['ui.datepicker']['js'][$datepicker] = array();
+    $libraries['ui.datepicker']['js'][] = array(
       'data' => array(
-        'jqueryuidatepicker' => array(
-          'rtl' => $language->direction == LANGUAGE_RTL,
-          'firstDay' => variable_get('date_first_day', 0),
+        'jquery' => array(
+          'ui' => array(
+            'datepicker' => array(
+              'isRTL' => $language->direction == LANGUAGE_RTL,
+              'firstDay' => variable_get('date_first_day', 0),
+            ),
+          ),
         ),
       ),
       'type' => 'setting',
diff --git a/modules/locale/locale.test b/modules/locale/locale.test
index ffda6f580..6f3135b08 100644
--- a/modules/locale/locale.test
+++ b/modules/locale/locale.test
@@ -179,6 +179,36 @@ class LocaleConfigurationTest extends DrupalWebTestCase {
 
 }
 
+/**
+ * Tests localization of the JavaScript libraries.
+ *
+ * Currently, only the jQuery datepicker is localized using Drupal translations.
+ */
+class LocaleLibraryInfoAlterTest extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Javascript library localisation',
+      'description' => 'Tests the localisation of JavaScript libraries.',
+      'group' => 'Locale',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('locale', 'locale_test');
+  }
+
+  /**
+   * Verifies that the datepicker can be localized.
+   *
+   * @see locale_library_info_alter()
+   */
+  public function testLibraryInfoAlter() {
+    drupal_add_library('system', 'ui.datepicker');
+    $scripts = drupal_get_js();
+    $this->assertTrue(strpos($scripts, 'locale.datepicker.js'), t('locale.datepicker.js added to scripts.'));
+  }
+}
+
 /**
  * Functional tests for JavaScript parsing for translatable strings.
  */
@@ -605,7 +635,7 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
     $this->assertText(t('No strings available.'), t("Search didn't find the string."));
 
     // Ensure untranslated string appears if searching on 'only untranslated
-    // strings'.
+    // strings' in "all" (hasn't been translated to any language).
     $search = array(
       'string' => $name,
       'language' => 'all',
@@ -615,6 +645,17 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     $this->assertNoText(t('No strings available.'), t('Search found the string.'));
 
+    // Ensure untranslated string appears if searching on 'only untranslated
+    // strings' in the custom language (hasn't been translated to that specific language).
+    $search = array(
+      'string' => $name,
+      'language' => $langcode,
+      'translation' => 'untranslated',
+      'group' => 'all',
+    );
+    $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
+    $this->assertNoText(t('No strings available.'), t('Search found the string.'));
+
     // Add translation.
     // Assume this is the only result, given the random name.
     $this->clickLink(t('edit'));
@@ -1515,7 +1556,6 @@ class LocaleUninstallFrenchFunctionalTest extends LocaleUninstallFunctionalTest
   }
 }
 
-
 /**
  * Functional tests for the language switching feature.
  */
@@ -1690,7 +1730,6 @@ class LocaleBrowserDetectionTest extends DrupalUnitTestCase {
       'eh' => 'eh-oh-laa-laa',
 
       // Different qvalues.
-      'en-US,en;q=0.5,fr;q=0.25' => 'en-US',
       'fr,en;q=0.5' => 'fr-CA',
       'fr,en;q=0.5,fr-CA;q=0.25' => 'fr',
 
@@ -2378,7 +2417,7 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase {
       array(
         'language_negotiation' => array(LOCALE_LANGUAGE_NEGOTIATION_URL, LANGUAGE_NEGOTIATION_DEFAULT),
         'locale_language_negotiation_url_part' => LOCALE_LANGUAGE_NEGOTIATION_URL_DOMAIN,
-        'locale_test_domain' => $language_domain,
+        'locale_test_domain' => $language_domain . ':88',
         'path' => 'admin/config',
         'expect' => $language_string,
         'expected_provider' => LOCALE_LANGUAGE_NEGOTIATION_URL,
@@ -2788,12 +2827,14 @@ class LocaleCommentLanguageFunctionalTest extends DrupalWebTestCase {
           ->orderBy('cid', 'DESC')
           ->execute()
           ->fetchObject();
-        $args = array('%node_language' => $node_langcode, '%comment_language' => $comment->language, '%langcode' => $langcode);
-        $this->assertEqual($comment->language, $langcode, t('The comment posted with content language %langcode and belonging to the node with language %node_language has language %comment_language', $args));
+        $comment_langcode = entity_language('comment', $comment);
+        $args = array('%node_language' => $node_langcode, '%comment_language' => $comment_langcode, '%langcode' => $langcode);
+        $this->assertEqual($comment_langcode, $langcode, t('The comment posted with content language %langcode and belonging to the node with language %node_language has language %comment_language', $args));
       }
     }
   }
 }
+
 /**
  * Functional tests for localizing date formats.
  */
diff --git a/modules/locale/tests/locale_test.info b/modules/locale/tests/locale_test.info
index 2923f9ab9..ce010a6ad 100644
--- a/modules/locale/tests/locale_test.info
+++ b/modules/locale/tests/locale_test.info
@@ -5,8 +5,8 @@ package = Testing
 version = VERSION
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/menu/menu.info b/modules/menu/menu.info
index 766998a42..0f4e8a4f3 100644
--- a/modules/menu/menu.info
+++ b/modules/menu/menu.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = menu.test
 configure = admin/structure/menu
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/menu/menu.install b/modules/menu/menu.install
index 7877b996d..346edf9f2 100644
--- a/modules/menu/menu.install
+++ b/modules/menu/menu.install
@@ -70,7 +70,7 @@ function menu_uninstall() {
 }
 
 /**
- * @defgroup updates-7.x-extra Extra updates for 7.x
+ * @addtogroup updates-7.x-extra
  * @{
  */
 
@@ -205,6 +205,6 @@ function menu_update_7003(&$sandbox) {
 }
 
 /**
- * @} End of "defgroup updates-7.x-extra"
+ * @} End of "addtogroup updates-7.x-extra".
  * The next series of updates should start at 8000.
  */
diff --git a/modules/node/content_types.inc b/modules/node/content_types.inc
index 71b3b1a60..72adc3491 100644
--- a/modules/node/content_types.inc
+++ b/modules/node/content_types.inc
@@ -437,7 +437,7 @@ function node_type_delete_confirm_submit($form, &$form_state) {
   variable_del('node_preview_' . $form_state['values']['type']);
   $t_args = array('%name' => $form_state['values']['name']);
   drupal_set_message(t('The content type %name has been deleted.', $t_args));
-  watchdog('menu', 'Deleted content type %name.', $t_args, WATCHDOG_NOTICE);
+  watchdog('node', 'Deleted content type %name.', $t_args, WATCHDOG_NOTICE);
 
   node_types_rebuild();
   menu_rebuild();
diff --git a/modules/node/node.admin.inc b/modules/node/node.admin.inc
index a1967c45d..1508bc054 100644
--- a/modules/node/node.admin.inc
+++ b/modules/node/node.admin.inc
@@ -432,7 +432,8 @@ function node_admin_nodes() {
   $destination = drupal_get_destination();
   $options = array();
   foreach ($nodes as $node) {
-    $l_options = $node->language != LANGUAGE_NONE && isset($languages[$node->language]) ? array('language' => $languages[$node->language]) : array();
+    $langcode = entity_language('node', $node);
+    $l_options = $langcode != LANGUAGE_NONE && isset($languages[$langcode]) ? array('language' => $languages[$langcode]) : array();
     $options[$node->nid] = array(
       'title' => array(
         'data' => array(
@@ -449,11 +450,11 @@ function node_admin_nodes() {
       'changed' => format_date($node->changed, 'short'),
     );
     if ($multilanguage) {
-      if ($node->language == LANGUAGE_NONE || isset($languages[$node->language])) {
-        $options[$node->nid]['language'] = $node->language == LANGUAGE_NONE ? t('Language neutral') : t($languages[$node->language]->name);
+      if ($langcode == LANGUAGE_NONE || isset($languages[$langcode])) {
+        $options[$node->nid]['language'] = $langcode == LANGUAGE_NONE ? t('Language neutral') : t($languages[$langcode]->name);
       }
       else {
-        $options[$node->nid]['language'] = t('Undefined language (@langcode)', array('@langcode' => $node->language));
+        $options[$node->nid]['language'] = t('Undefined language (@langcode)', array('@langcode' => $langcode));
       }
     }
     // Build a list of all the accessible operations for the current node.
diff --git a/modules/node/node.info b/modules/node/node.info
index c15b4944a..d53ee84c9 100644
--- a/modules/node/node.info
+++ b/modules/node/node.info
@@ -9,8 +9,8 @@ required = TRUE
 configure = admin/structure/types
 stylesheets[all][] = node.css
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/node/node.install b/modules/node/node.install
index c54ebfbe3..434410c8d 100644
--- a/modules/node/node.install
+++ b/modules/node/node.install
@@ -846,6 +846,15 @@ function node_update_7010() {
   db_create_table('block_node_type', $schema['block_node_type']);
 }
 
+/**
+ * @} End of "addtogroup updates-6.x-to-7.x".
+ */
+
+/**
+ * @addtogroup updates-7.x-extra
+ * @{
+ */
+
 /**
  * Update the database from Drupal 6 to match the schema.
  */
@@ -890,7 +899,7 @@ function node_update_7012() {
       ->execute();
 
     // Switch field languages to LANGUAGE_NONE, since initially they were
-    // assigned $node->language.
+    // assigned the node language.
     foreach (array('field_data_body', 'field_revision_body') as $table) {
       db_update($table)
         ->fields(array('language' => LANGUAGE_NONE))
@@ -915,5 +924,5 @@ function node_update_7013() {
 }
 
 /**
- * @} End of "addtogroup updates-6.x-to-7.x"
+ * @} End of "addtogroup updates-7.x-extra".
  */
diff --git a/modules/node/node.module b/modules/node/node.module
index 57133c6b0..264816c00 100644
--- a/modules/node/node.module
+++ b/modules/node/node.module
@@ -177,6 +177,7 @@ function node_entity_info() {
         'revision' => 'vid',
         'bundle' => 'type',
         'label' => 'title',
+        'language' => 'language',
       ),
       'bundle keys' => array(
         'bundle' => 'type',
@@ -655,7 +656,7 @@ function node_type_update_nodes($old_type, $type) {
  * @param $rebuild
  *  TRUE to rebuild node types. Equivalent to calling node_types_rebuild().
  * @return
- *   Associative array with two components:
+ *   An object with two properties:
  *   - names: Associative array of the names of node types, keyed by the type.
  *   - types: Associative array of node type objects, keyed by the type.
  *   Both of these arrays will include new types that have been defined by
@@ -1002,8 +1003,6 @@ function node_validate($node, $form, &$form_state) {
  * Prepare node for saving by populating author and creation date.
  */
 function node_submit($node) {
-  global $user;
-
   // A user might assign the node author by entering a user name in the node
   // form, which we then need to translate to a user ID.
   if (isset($node->name)) {
@@ -1684,7 +1683,7 @@ function node_search_execute($keys = NULL, $conditions = NULL) {
       'extra' => $extra,
       'score' => $item->calculated_score,
       'snippet' => search_excerpt($keys, $node->rendered),
-      'language' => $node->language,
+      'language' => entity_language('node', $node),
     );
   }
   return $results;
@@ -3274,8 +3273,9 @@ function _node_query_node_access_alter($query, $type) {
     // @endcode
     //
     // So instead of directly adding to the query object, we need to collect
-    // in a separate db_and() object and then at the end add it to the query.
-    $entity_conditions = db_and();
+    // all of the node access conditions in a separate db_and() object and
+    // then add it to the query at the end.
+    $node_conditions = db_and();
   }
   foreach ($tables as $nalias => $tableinfo) {
     $table = $tableinfo['table'];
@@ -3309,16 +3309,24 @@ function _node_query_node_access_alter($query, $type) {
         $field = 'entity_id';
       }
       $subquery->where("$nalias.$field = na.nid");
-      $query->exists($subquery);
+
+      // For an entity query, attach the subquery to entity conditions.
+      if ($type == 'entity') {
+        $node_conditions->exists($subquery);
+      }
+      // Otherwise attach it to the node query itself.
+      else {
+        $query->exists($subquery);
+      }
     }
   }
 
   if ($type == 'entity' && count($subquery->conditions())) {
     // All the node access conditions are only for field values belonging to
     // nodes.
-    $entity_conditions->condition("$base_alias.entity_type", 'node');
+    $node_conditions->condition("$base_alias.entity_type", 'node');
     $or = db_or();
-    $or->condition($entity_conditions);
+    $or->condition($node_conditions);
     // If the field value belongs to a non-node entity type then this function
     // does not do anything with it.
     $or->condition("$base_alias.entity_type", 'node', '<>');
diff --git a/modules/node/node.pages.inc b/modules/node/node.pages.inc
index 019ed3e8c..1f3e725de 100644
--- a/modules/node/node.pages.inc
+++ b/modules/node/node.pages.inc
@@ -15,6 +15,13 @@ function node_page_edit($node) {
   return drupal_get_form($node->type . '_node_form', $node);
 }
 
+/**
+ * Page callback: Displays add content links for available content types.
+ *
+ * Redirects to node/add/[type] if only one content type is available.
+ *
+ * @see node_menu()
+ */
 function node_add_page() {
   $item = menu_get_item();
   $content = system_admin_menu_block($item);
@@ -299,7 +306,7 @@ function node_form($form, &$form_state, $node) {
   }
   $form += array('#submit' => array());
 
-  field_attach_form('node', $node, $form, $form_state, $node->language);
+  field_attach_form('node', $node, $form, $form_state, entity_language('node', $node));
   return $form;
 }
 
diff --git a/modules/node/node.test b/modules/node/node.test
index f46d2a108..37d05e529 100644
--- a/modules/node/node.test
+++ b/modules/node/node.test
@@ -5,6 +5,26 @@
  * Tests for node.module.
  */
 
+/**
+ * Defines a base class for testing the Node module.
+ */
+class NodeWebTestCase extends DrupalWebTestCase {
+  function setUp() {
+    $modules = func_get_args();
+    if (isset($modules[0]) && is_array($modules[0])) {
+      $modules = $modules[0];
+    }
+    $modules[] = 'node';
+    parent::setUp($modules);
+
+    // Create Basic page and Article node types.
+    if ($this->profile != 'standard') {
+      $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
+      $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
+    }
+  }
+}
+
 /**
  * Test the node_load_multiple() function.
  */
@@ -2268,15 +2288,16 @@ class NodeTokenReplaceTestCase extends DrupalWebTestCase {
 
     // Generate and test sanitized tokens.
     $tests = array();
+    $langcode = entity_language('node', $node);
     $tests['[node:nid]'] = $node->nid;
     $tests['[node:vid]'] = $node->vid;
     $tests['[node:tnid]'] = $node->tnid;
     $tests['[node:type]'] = 'article';
     $tests['[node:type-name]'] = 'Article';
     $tests['[node:title]'] = check_plain($node->title);
-    $tests['[node:body]'] = _text_sanitize($instance, $node->language, $node->body[$node->language][0], 'value');
-    $tests['[node:summary]'] = _text_sanitize($instance, $node->language, $node->body[$node->language][0], 'summary');
-    $tests['[node:language]'] = check_plain($node->language);
+    $tests['[node:body]'] = _text_sanitize($instance, $langcode, $node->body[$langcode][0], 'value');
+    $tests['[node:summary]'] = _text_sanitize($instance, $langcode, $node->body[$langcode][0], 'summary');
+    $tests['[node:language]'] = check_plain($langcode);
     $tests['[node:url]'] = url('node/' . $node->nid, $url_options);
     $tests['[node:edit-url]'] = url('node/' . $node->nid . '/edit', $url_options);
     $tests['[node:author]'] = check_plain(format_username($account));
@@ -2295,9 +2316,9 @@ class NodeTokenReplaceTestCase extends DrupalWebTestCase {
 
     // Generate and test unsanitized tokens.
     $tests['[node:title]'] = $node->title;
-    $tests['[node:body]'] = $node->body[$node->language][0]['value'];
-    $tests['[node:summary]'] = $node->body[$node->language][0]['summary'];
-    $tests['[node:language]'] = $node->language;
+    $tests['[node:body]'] = $node->body[$langcode][0]['value'];
+    $tests['[node:summary]'] = $node->body[$langcode][0]['summary'];
+    $tests['[node:language]'] = $langcode;
     $tests['[node:author:name]'] = format_username($account);
 
     foreach ($tests as $input => $expected) {
@@ -2493,3 +2514,78 @@ class NodeAccessPagerTestCase extends DrupalWebTestCase {
     $this->assertNoRaw('page=2', t('No third page exists.'));
   }
 }
+
+
+/**
+ * Tests the interaction of the node access system with fields.
+ */
+class NodeAccessFieldTestCase extends NodeWebTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Node access and fields',
+      'description' => 'Tests the interaction of the node access system with fields.',
+      'group' => 'Node',
+    );
+  }
+
+  public function setUp() {
+    parent::setUp('node_access_test', 'field_ui');
+    node_access_rebuild();
+
+    // Create some users.
+    $this->admin_user = $this->drupalCreateUser(array('access content', 'bypass node access'));
+    $this->content_admin_user = $this->drupalCreateUser(array('access content', 'administer content types'));
+
+    // Add a custom field to the page content type.
+    $this->field_name = drupal_strtolower($this->randomName() . '_field_name');
+    $this->field = field_create_field(array('field_name' => $this->field_name, 'type' => 'text'));
+    $this->instance = field_create_instance(array(
+      'field_name' => $this->field_name,
+      'entity_type' => 'node',
+      'bundle' => 'page',
+    ));
+  }
+
+  /**
+   * Tests administering fields when node access is restricted.
+   */
+  function testNodeAccessAdministerField() {
+    // Create a page node.
+    $langcode = LANGUAGE_NONE;
+    $field_data = array();
+    $value = $field_data[$langcode][0]['value'] = $this->randomName();
+    $node = $this->drupalCreateNode(array($this->field_name => $field_data));
+
+    // Log in as the administrator and confirm that the field value is present.
+    $this->drupalLogin($this->admin_user);
+    $this->drupalGet("node/{$node->nid}");
+    $this->assertText($value, 'The saved field value is visible to an administrator.');
+
+    // Log in as the content admin and try to view the node.
+    $this->drupalLogin($this->content_admin_user);
+    $this->drupalGet("node/{$node->nid}");
+    $this->assertText('Access denied', 'Access is denied for the content admin.');
+
+    // Modify the field default as the content admin.
+    $edit = array();
+    $default = 'Sometimes words have two meanings';
+    $edit["{$this->field_name}[$langcode][0][value]"] = $default;
+    $this->drupalPost(
+      "admin/structure/types/manage/page/fields/{$this->field_name}",
+      $edit,
+      t('Save settings')
+    );
+
+    // Log in as the administrator.
+    $this->drupalLogin($this->admin_user);
+
+    // Confirm that the existing node still has the correct field value.
+    $this->drupalGet("node/{$node->nid}");
+    $this->assertText($value, 'The original field value is visible to an administrator.');
+
+    // Confirm that the new default value appears when creating a new node.
+    $this->drupalGet('node/add/page');
+    $this->assertRaw($default, 'The updated default value is displayed when creating a new node.');
+  }
+}
diff --git a/modules/node/node.tokens.inc b/modules/node/node.tokens.inc
index 491ec81c4..e43db5e7d 100644
--- a/modules/node/node.tokens.inc
+++ b/modules/node/node.tokens.inc
@@ -144,7 +144,8 @@ function node_tokens($type, $tokens, array $data = array(), array $options = arr
           break;
 
         case 'language':
-          $replacements[$original] = $sanitize ? check_plain($node->language) : $node->language;
+          $langcode = entity_language('node', $node);
+          $replacements[$original] = $sanitize ? check_plain($langcode) : $langcode;
           break;
 
         case 'url':
diff --git a/modules/node/tests/node_access_test.info b/modules/node/tests/node_access_test.info
index df12ab45a..ade2ccc95 100644
--- a/modules/node/tests/node_access_test.info
+++ b/modules/node/tests/node_access_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/node/tests/node_test.info b/modules/node/tests/node_test.info
index 3fe505a09..69d0f3bd9 100644
--- a/modules/node/tests/node_test.info
+++ b/modules/node/tests/node_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/node/tests/node_test_exception.info b/modules/node/tests/node_test_exception.info
index d2daca052..9b4459177 100644
--- a/modules/node/tests/node_test_exception.info
+++ b/modules/node/tests/node_test_exception.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/openid/openid.info b/modules/openid/openid.info
index 078c58345..aaddb3461 100644
--- a/modules/openid/openid.info
+++ b/modules/openid/openid.info
@@ -5,8 +5,8 @@ package = Core
 core = 7.x
 files[] = openid.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/openid/openid.install b/modules/openid/openid.install
index 2df39aa69..4b77b710b 100644
--- a/modules/openid/openid.install
+++ b/modules/openid/openid.install
@@ -156,5 +156,5 @@ function openid_update_6000() {
 }
 
 /**
- * @} End of "addtogroup updates-6.x-to-7.x"
+ * @} End of "addtogroup updates-6.x-to-7.x".
  */
diff --git a/modules/openid/tests/openid_test.info b/modules/openid/tests/openid_test.info
index 83e1beff8..d3ece3ddf 100644
--- a/modules/openid/tests/openid_test.info
+++ b/modules/openid/tests/openid_test.info
@@ -6,8 +6,8 @@ core = 7.x
 dependencies[] = openid
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/overlay/overlay.info b/modules/overlay/overlay.info
index 1b9825235..1331fc605 100644
--- a/modules/overlay/overlay.info
+++ b/modules/overlay/overlay.info
@@ -4,8 +4,8 @@ package = Core
 version = VERSION
 core = 7.x
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/path/path.info b/modules/path/path.info
index 7b6c07291..8e2cb8b90 100644
--- a/modules/path/path.info
+++ b/modules/path/path.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = path.test
 configure = admin/config/search/path
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/path/path.module b/modules/path/path.module
index 9df498865..1bb06f42b 100644
--- a/modules/path/path.module
+++ b/modules/path/path.module
@@ -99,8 +99,9 @@ function path_form_node_form_alter(&$form, $form_state) {
   $path = array();
   if (!empty($form['#node']->nid)) {
     $conditions = array('source' => 'node/' . $form['#node']->nid);
-    if ($form['#node']->language != LANGUAGE_NONE) {
-      $conditions['language'] = $form['#node']->language;
+    $langcode = entity_language('node', $form['#node']);
+    if ($langcode != LANGUAGE_NONE) {
+      $conditions['language'] = $langcode;
     }
     $path = path_load($conditions);
     if ($path === FALSE) {
@@ -111,7 +112,7 @@ function path_form_node_form_alter(&$form, $form_state) {
     'pid' => NULL,
     'source' => isset($form['#node']->nid) ? 'node/' . $form['#node']->nid : NULL,
     'alias' => '',
-    'language' => isset($form['#node']->language) ? $form['#node']->language : LANGUAGE_NONE,
+    'language' => isset($langcode) ? $langcode : LANGUAGE_NONE,
   );
 
   $form['path'] = array(
@@ -192,8 +193,9 @@ function path_node_insert($node) {
     // Only save a non-empty alias.
     if (!empty($path['alias'])) {
       // Ensure fields for programmatic executions.
+      $langcode = entity_language('node', $node);
       $path['source'] = 'node/' . $node->nid;
-      $path['language'] = isset($node->language) ? $node->language : LANGUAGE_NONE;
+      $path['language'] = isset($langcode) ? $langcode : LANGUAGE_NONE;
       path_save($path);
     }
   }
@@ -210,13 +212,7 @@ function path_node_update($node) {
     if (!empty($path['pid']) && empty($path['alias'])) {
       path_delete($path['pid']);
     }
-    // Only save a non-empty alias.
-    if (!empty($path['alias'])) {
-      // Ensure fields for programmatic executions.
-      $path['source'] = 'node/' . $node->nid;
-      $path['language'] = isset($node->language) ? $node->language : LANGUAGE_NONE;
-      path_save($path);
-    }
+    path_node_insert($node);
   }
 }
 
@@ -234,7 +230,10 @@ function path_node_delete($node) {
 function path_form_taxonomy_form_term_alter(&$form, $form_state) {
   // Make sure this does not show up on the delete confirmation form.
   if (empty($form_state['confirm_delete'])) {
-    $path = (isset($form['#term']['tid']) ? path_load('taxonomy/term/' . $form['#term']['tid']) : array());
+    $langcode = entity_language('taxonomy_term', (object) $form['#term']);
+    $langcode = !empty($langcode) ? $langcode : LANGUAGE_NONE;
+    $conditions = array('source' => 'taxonomy/term/' . $form['#term']['tid'], 'language' => $langcode);
+    $path = (isset($form['#term']['tid']) ? path_load($conditions) : array());
     if ($path === FALSE) {
       $path = array();
     }
@@ -242,7 +241,7 @@ function path_form_taxonomy_form_term_alter(&$form, $form_state) {
       'pid' => NULL,
       'source' => isset($form['#term']['tid']) ? 'taxonomy/term/' . $form['#term']['tid'] : NULL,
       'alias' => '',
-      'language' => LANGUAGE_NONE,
+      'language' => $langcode,
     );
     $form['path'] = array(
       '#access' => user_access('create url aliases') || user_access('administer url aliases'),
@@ -274,7 +273,10 @@ function path_taxonomy_term_insert($term) {
     if (!empty($path['alias'])) {
       // Ensure fields for programmatic executions.
       $path['source'] = 'taxonomy/term/' . $term->tid;
-      $path['language'] = LANGUAGE_NONE;
+      // Core does not provide a way to store the term language but contrib
+      // modules can do it so we need to take this into account.
+      $langcode = entity_language('taxonomy_term', $term);
+      $path['language'] = !empty($langcode) ? $langcode : LANGUAGE_NONE;
       path_save($path);
     }
   }
@@ -295,7 +297,10 @@ function path_taxonomy_term_update($term) {
     if (!empty($path['alias'])) {
       // Ensure fields for programmatic executions.
       $path['source'] = 'taxonomy/term/' . $term->tid;
-      $path['language'] = LANGUAGE_NONE;
+      // Core does not provide a way to store the term language but contrib
+      // modules can do it so we need to take this into account.
+      $langcode = entity_language('taxonomy_term', $term);
+      $path['language'] = !empty($langcode) ? $langcode : LANGUAGE_NONE;
       path_save($path);
     }
   }
diff --git a/modules/php/php.info b/modules/php/php.info
index 18a7f2f5c..241c8ee23 100644
--- a/modules/php/php.info
+++ b/modules/php/php.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 files[] = php.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/php/php.test b/modules/php/php.test
index 50fb55283..b68bd501d 100644
--- a/modules/php/php.test
+++ b/modules/php/php.test
@@ -33,8 +33,8 @@ class PHPTestCase extends DrupalWebTestCase {
 
     // Verify that anonymous and authenticated user roles do not have access.
     $this->drupalGet('admin/config/content/formats/' . $php_format_id);
-    $this->assertFieldByName('roles[1]', FALSE, t('Anonymous users do not have access to PHP code format.'));
-    $this->assertFieldByName('roles[2]', FALSE, t('Authenticated users do not have access to PHP code format.'));
+    $this->assertFieldByName('roles[' . DRUPAL_ANONYMOUS_RID . ']', FALSE, t('Anonymous users do not have access to PHP code format.'));
+    $this->assertFieldByName('roles[' . DRUPAL_AUTHENTICATED_RID . ']', FALSE, t('Authenticated users do not have access to PHP code format.'));
   }
 
   /**
diff --git a/modules/poll/poll.info b/modules/poll/poll.info
index 93cbb0f89..3b4aea98a 100644
--- a/modules/poll/poll.info
+++ b/modules/poll/poll.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = poll.test
 stylesheets[all][] = poll.css
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/poll/poll.install b/modules/poll/poll.install
index 8c73cf43a..8c58025bb 100644
--- a/modules/poll/poll.install
+++ b/modules/poll/poll.install
@@ -197,6 +197,11 @@ function poll_update_7003() {
   ));
 }
 
+/**
+ * @addtogroup updates-7.x-extra
+ * @{
+ */
+
 /**
  * Update the database to match the schema.
  */
@@ -204,3 +209,7 @@ function poll_update_7004() {
   // Remove field default.
   db_change_field('poll_vote', 'chid', 'chid', array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE));
 }
+
+/**
+ * @} End of "addtogroup updates-7.x-extra".
+ */
diff --git a/modules/profile/profile.info b/modules/profile/profile.info
index 88de22523..e90986c33 100644
--- a/modules/profile/profile.info
+++ b/modules/profile/profile.info
@@ -11,8 +11,8 @@ configure = admin/config/people/profile
 ; See user_system_info_alter().
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/rdf/rdf.info b/modules/rdf/rdf.info
index c02ddeee2..f04ab1d10 100644
--- a/modules/rdf/rdf.info
+++ b/modules/rdf/rdf.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 files[] = rdf.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/rdf/tests/rdf_test.info b/modules/rdf/tests/rdf_test.info
index 34ec20b4b..6b18b3532 100644
--- a/modules/rdf/tests/rdf_test.info
+++ b/modules/rdf/tests/rdf_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/search/search.info b/modules/search/search.info
index fbea0faab..a859f9295 100644
--- a/modules/search/search.info
+++ b/modules/search/search.info
@@ -8,8 +8,8 @@ files[] = search.test
 configure = admin/config/search/settings
 stylesheets[all][] = search.css
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/search/tests/search_embedded_form.info b/modules/search/tests/search_embedded_form.info
index 17d5f6117..6ec3759bf 100644
--- a/modules/search/tests/search_embedded_form.info
+++ b/modules/search/tests/search_embedded_form.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/search/tests/search_extra_type.info b/modules/search/tests/search_extra_type.info
index 241a86db6..d9e3c8993 100644
--- a/modules/search/tests/search_extra_type.info
+++ b/modules/search/tests/search_extra_type.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/shortcut/shortcut.info b/modules/shortcut/shortcut.info
index 7a135d005..36820cd53 100644
--- a/modules/shortcut/shortcut.info
+++ b/modules/shortcut/shortcut.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = shortcut.test
 configure = admin/config/user-interface/shortcut
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/drupal_web_test_case.php b/modules/simpletest/drupal_web_test_case.php
index 251c5c1bc..d83dbeb6f 100644
--- a/modules/simpletest/drupal_web_test_case.php
+++ b/modules/simpletest/drupal_web_test_case.php
@@ -85,6 +85,10 @@ abstract class DrupalTestCase {
    */
   protected $setup = FALSE;
 
+  protected $setupDatabasePrefix = FALSE;
+
+  protected $setupEnvironment = FALSE;
+
   /**
    * Constructor for DrupalTestCase.
    *
@@ -562,14 +566,21 @@ abstract class DrupalTestCase {
   /**
    * Generates a random string of ASCII characters of codes 32 to 126.
    *
-   * The generated string includes alpha-numeric characters and common misc
-   * characters. Use this method when testing general input where the content
-   * is not restricted.
+   * The generated string includes alpha-numeric characters and common
+   * miscellaneous characters. Use this method when testing general input
+   * where the content is not restricted.
+   *
+   * Do not use this method when special characters are not possible (e.g., in
+   * machine or file names that have already been validated); instead,
+   * use DrupalWebTestCase::randomName().
    *
    * @param $length
    *   Length of random string to generate.
+   *
    * @return
    *   Randomly generated string.
+   *
+   * @see DrupalWebTestCase::randomName()
    */
   public static function randomString($length = 8) {
     $str = '';
@@ -588,10 +599,16 @@ abstract class DrupalTestCase {
    * require machine readable values (i.e. without spaces and non-standard
    * characters) this method is best.
    *
+   * Do not use this method when testing unvalidated user input. Instead, use
+   * DrupalWebTestCase::randomString().
+   *
    * @param $length
    *   Length of random string to generate.
+   *
    * @return
    *   Randomly generated string.
+   *
+   * @see DrupalWebTestCase::randomString()
    */
   public static function randomName($length = 8) {
     $values = array_merge(range(65, 90), range(97, 122), range(48, 57));
@@ -1251,29 +1268,46 @@ class DrupalWebTestCase extends DrupalTestCase {
   }
 
   /**
-   * Generates a random database prefix, runs the install scripts on the
-   * prefixed database and enable the specified modules. After installation
-   * many caches are flushed and the internal browser is setup so that the
-   * page requests will run on the new prefix. A temporary files directory
-   * is created with the same name as the database prefix.
+   * Generates a database prefix for running tests.
    *
-   * @param ...
-   *   List of modules to enable for the duration of the test. This can be
-   *   either a single array or a variable number of string arguments.
+   * The generated database table prefix is used for the Drupal installation
+   * being performed for the test. It is also used as user agent HTTP header
+   * value by the cURL-based browser of DrupalWebTestCase, which is sent
+   * to the Drupal installation of the test. During early Drupal bootstrap, the
+   * user agent HTTP header is parsed, and if it matches, all database queries
+   * use the database table prefix that has been generated here.
+   *
+   * @see DrupalWebTestCase::curlInitialize()
+   * @see drupal_valid_test_ua()
+   * @see DrupalWebTestCase::setUp()
    */
-  protected function setUp() {
-    global $user, $language, $conf;
-
-    // Generate a temporary prefixed database to ensure that tests have a clean starting point.
+  protected function prepareDatabasePrefix() {
     $this->databasePrefix = 'simpletest' . mt_rand(1000, 1000000);
+
+    // As soon as the database prefix is set, the test might start to execute.
+    // All assertions as well as the SimpleTest batch operations are associated
+    // with the testId, so the database prefix has to be associated with it.
     db_update('simpletest_test_id')
       ->fields(array('last_prefix' => $this->databasePrefix))
       ->condition('test_id', $this->testId)
       ->execute();
+  }
 
-    // Reset all statics and variables to perform tests in a clean environment.
-    $conf = array();
-    drupal_static_reset();
+  /**
+   * Changes the database connection to the prefixed one.
+   *
+   * @see DrupalWebTestCase::setUp()
+   */
+  protected function changeDatabasePrefix() {
+    if (empty($this->databasePrefix)) {
+      $this->prepareDatabasePrefix();
+      // If $this->prepareDatabasePrefix() failed to work, return without
+      // setting $this->setupDatabasePrefix to TRUE, so setUp() methods will
+      // know to bail out.
+      if (empty($this->databasePrefix)) {
+        return;
+      }
+    }
 
     // Clone the current connection and replace the current prefix.
     $connection_info = Database::getConnectionInfo('default');
@@ -1285,22 +1319,43 @@ class DrupalWebTestCase extends DrupalTestCase {
     }
     Database::addConnectionInfo('default', 'default', $connection_info['default']);
 
+    // Indicate the database prefix was set up correctly.
+    $this->setupDatabasePrefix = TRUE;
+  }
+
+  /**
+   * Prepares the current environment for running the test.
+   *
+   * Backups various current environment variables and resets them, so they do
+   * not interfere with the Drupal site installation in which tests are executed
+   * and can be restored in tearDown().
+   *
+   * Also sets up new resources for the testing environment, such as the public
+   * filesystem and configuration directories.
+   *
+   * @see DrupalWebTestCase::setUp()
+   * @see DrupalWebTestCase::tearDown()
+   */
+  protected function prepareEnvironment() {
+    global $user, $language, $conf;
+
     // Store necessary current values before switching to prefixed database.
     $this->originalLanguage = $language;
     $this->originalLanguageDefault = variable_get('language_default');
     $this->originalFileDirectory = variable_get('file_public_path', conf_path() . '/files');
     $this->originalProfile = drupal_get_profile();
-    $clean_url_original = variable_get('clean_url', 0);
+    $this->originalCleanUrl = variable_get('clean_url', 0);
+    $this->originalUser = $user;
 
     // Set to English to prevent exceptions from utf8_truncate() from t()
     // during install if the current language is not 'en'.
     // The following array/object conversion is copied from language_default().
     $language = (object) array('language' => 'en', 'name' => 'English', 'native' => 'English', 'direction' => 0, 'enabled' => 1, 'plurals' => 0, 'formula' => '', 'domain' => '', 'prefix' => '', 'weight' => 0, 'javascript' => '');
 
-    // Save and clean shutdown callbacks array because it static cached and
-    // will be changed by the test run. If we don't, then it will contain
-    // callbacks from both environments. So testing environment will try
-    // to call handlers from original environment.
+    // Save and clean the shutdown callbacks array because it is static cached
+    // and will be changed by the test run. Otherwise it will contain callbacks
+    // from both environments and the testing environment will try to call the
+    // handlers defined by the original one.
     $callbacks = &drupal_register_shutdown_function();
     $this->originalShutdownCallbacks = $callbacks;
     $callbacks = array();
@@ -1308,25 +1363,75 @@ class DrupalWebTestCase extends DrupalTestCase {
     // Create test directory ahead of installation so fatal errors and debug
     // information can be logged during installation process.
     // Use temporary files directory with the same prefix as the database.
-    $public_files_directory  = $this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10);
-    $private_files_directory = $public_files_directory . '/private';
-    $temp_files_directory    = $private_files_directory . '/temp';
+    $this->public_files_directory = $this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10);
+    $this->private_files_directory = $this->public_files_directory . '/private';
+    $this->temp_files_directory = $this->private_files_directory . '/temp';
 
     // Create the directories
-    file_prepare_directory($public_files_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
-    file_prepare_directory($private_files_directory, FILE_CREATE_DIRECTORY);
-    file_prepare_directory($temp_files_directory, FILE_CREATE_DIRECTORY);
+    file_prepare_directory($this->public_files_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+    file_prepare_directory($this->private_files_directory, FILE_CREATE_DIRECTORY);
+    file_prepare_directory($this->temp_files_directory, FILE_CREATE_DIRECTORY);
     $this->generatedTestFiles = FALSE;
 
     // Log fatal errors.
     ini_set('log_errors', 1);
-    ini_set('error_log', $public_files_directory . '/error.log');
+    ini_set('error_log', $this->public_files_directory . '/error.log');
 
     // Set the test information for use in other parts of Drupal.
     $test_info = &$GLOBALS['drupal_test_info'];
     $test_info['test_run_id'] = $this->databasePrefix;
     $test_info['in_child_site'] = FALSE;
 
+    // Indicate the environment was set up correctly.
+    $this->setupEnvironment = TRUE;
+  }
+
+  /**
+   * Sets up a Drupal site for running functional and integration tests.
+   *
+   * Generates a random database prefix and installs Drupal with the specified
+   * installation profile in DrupalWebTestCase::$profile into the
+   * prefixed database. Afterwards, installs any additional modules specified by
+   * the test.
+   *
+   * After installation all caches are flushed and several configuration values
+   * are reset to the values of the parent site executing the test, since the
+   * default values may be incompatible with the environment in which tests are
+   * being executed.
+   *
+   * @param ...
+   *   List of modules to enable for the duration of the test. This can be
+   *   either a single array or a variable number of string arguments.
+   *
+   * @see DrupalWebTestCase::prepareDatabasePrefix()
+   * @see DrupalWebTestCase::changeDatabasePrefix()
+   * @see DrupalWebTestCase::prepareEnvironment()
+   */
+  protected function setUp() {
+    global $user, $language, $conf;
+
+    // Create the database prefix for this test.
+    $this->prepareDatabasePrefix();
+
+    // Prepare the environment for running tests.
+    $this->prepareEnvironment();
+    if (!$this->setupEnvironment) {
+      return FALSE;
+    }
+
+    // Reset all statics and variables to perform tests in a clean environment.
+    $conf = array();
+    drupal_static_reset();
+
+    // Change the database prefix.
+    // All static variables need to be reset before the database prefix is
+    // changed, since DrupalCacheArray implementations attempt to
+    // write back to persistent caches when they are destructed.
+    $this->changeDatabasePrefix();
+    if (!$this->setupDatabasePrefix) {
+      return FALSE;
+    }
+
     // Preset the 'install_profile' system variable, so the first call into
     // system_rebuild_module_data() (in drupal_install_system()) will register
     // the test's profile as a module. Without this, the installation profile of
@@ -1334,15 +1439,16 @@ class DrupalWebTestCase extends DrupalTestCase {
     // profile's hook_install() and other hook implementations are never invoked.
     $conf['install_profile'] = $this->profile;
 
+    // Perform the actual Drupal installation.
     include_once DRUPAL_ROOT . '/includes/install.inc';
     drupal_install_system();
 
     $this->preloadRegistry();
 
     // Set path variables.
-    variable_set('file_public_path', $public_files_directory);
-    variable_set('file_private_path', $private_files_directory);
-    variable_set('file_temporary_path', $temp_files_directory);
+    variable_set('file_public_path', $this->public_files_directory);
+    variable_set('file_private_path', $this->private_files_directory);
+    variable_set('file_temporary_path', $this->temp_files_directory);
 
     // Set the 'simpletest_parent_profile' variable to add the parent profile's
     // search path to the child site's search paths.
@@ -1385,18 +1491,20 @@ class DrupalWebTestCase extends DrupalTestCase {
     // the installation process.
     drupal_cron_run();
 
-    // Log in with a clean $user.
-    $this->originalUser = $user;
+    // Ensure that the session is not written to the new environment and replace
+    // the global $user session with uid 1 from the new test site.
     drupal_save_session(FALSE);
+    // Login as uid 1.
     $user = user_load(1);
 
     // Restore necessary variables.
     variable_set('install_task', 'done');
-    variable_set('clean_url', $clean_url_original);
+    variable_set('clean_url', $this->originalCleanUrl);
     variable_set('site_mail', 'simpletest@example.com');
     variable_set('date_default_timezone', date_default_timezone_get());
+
     // Set up English language.
-    unset($GLOBALS['conf']['language_default']);
+    unset($conf['language_default']);
     $language = language_default();
 
     // Use the test mail class instead of the default mail handler class.
@@ -1506,10 +1614,21 @@ class DrupalWebTestCase extends DrupalTestCase {
     // Delete temporary files directory.
     file_unmanaged_delete_recursive($this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10));
 
-    // Remove all prefixed tables (all the tables in the schema).
-    $schema = drupal_get_schema(NULL, TRUE);
-    foreach ($schema as $name => $table) {
-      db_drop_table($name);
+    // Remove all prefixed tables.
+    $tables = db_find_tables($this->databasePrefix . '%');
+    $connection_info = Database::getConnectionInfo('default');
+    $tables = db_find_tables($connection_info['default']['prefix']['default'] . '%');
+    if (empty($tables)) {
+      $this->fail('Failed to find test tables to drop.');
+    }
+    $prefix_length = strlen($connection_info['default']['prefix']['default']);
+    foreach ($tables as $table) {
+      if (db_drop_table(substr($table, $prefix_length))) {
+        unset($tables[$table]);
+      }
+    }
+    if (!empty($tables)) {
+      $this->fail('Failed to drop all prefixed tables.');
     }
 
     // Get back to the original connection.
@@ -1540,6 +1659,9 @@ class DrupalWebTestCase extends DrupalTestCase {
     // Rebuild caches.
     $this->refreshVariables();
 
+    // Reset public files directory.
+    $GLOBALS['conf']['file_public_path'] = $this->originalFileDirectory;
+
     // Reset language.
     $language = $this->originalLanguage;
     if ($this->originalLanguageDefault) {
diff --git a/modules/simpletest/files/README.txt b/modules/simpletest/files/README.txt
index c8f39ad33..680e7feab 100644
--- a/modules/simpletest/files/README.txt
+++ b/modules/simpletest/files/README.txt
@@ -1,4 +1,4 @@
-
-These files are use in some tests that upload files or other operations were
-a file is useful. These files are copied to the files directory as specified
-in the site settings. Other tests files are generated in order to save space.
+These files are useful in tests that upload files or otherwise need to
+manipulate files, in which case they are copied to the files directory as
+specified in the site settings. Dummy files can also be generated by tests in
+order to save space.
diff --git a/modules/simpletest/simpletest.info b/modules/simpletest/simpletest.info
index a1ea1d798..682808719 100644
--- a/modules/simpletest/simpletest.info
+++ b/modules/simpletest/simpletest.info
@@ -54,8 +54,8 @@ files[] = tests/upgrade/upgrade.upload.test
 files[] = tests/upgrade/update.user.test
 files[] = tests/upgrade/upgrade.user.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/simpletest.js b/modules/simpletest/simpletest.js
index 9cab26101..2199fede7 100644
--- a/modules/simpletest/simpletest.js
+++ b/modules/simpletest/simpletest.js
@@ -7,49 +7,50 @@ Drupal.behaviors.simpleTestMenuCollapse = {
   attach: function (context, settings) {
     var timeout = null;
     // Adds expand-collapse functionality.
-    $('div.simpletest-image').each(function () {
-      direction = settings.simpleTest[$(this).attr('id')].imageDirection;
-      $(this).html(settings.simpleTest.images[direction]);
-    });
-
-    // Adds group toggling functionality to arrow images.
-    $('div.simpletest-image').click(function () {
-      var trs = $(this).closest('tbody').children('.' + settings.simpleTest[this.id].testClass);
+    $('div.simpletest-image').once('simpletest-image', function () {
+      var $this = $(this);
       var direction = settings.simpleTest[this.id].imageDirection;
-      var row = direction ? trs.length - 1 : 0;
+      $this.html(settings.simpleTest.images[direction]);
 
-      // If clicked in the middle of expanding a group, stop so we can switch directions.
-      if (timeout) {
-        clearTimeout(timeout);
-      }
+      // Adds group toggling functionality to arrow images.
+      $this.click(function () {
+        var trs = $this.closest('tbody').children('.' + settings.simpleTest[this.id].testClass);
+        var direction = settings.simpleTest[this.id].imageDirection;
+        var row = direction ? trs.length - 1 : 0;
 
-      // Function to toggle an individual row according to the current direction.
-      // We set a timeout of 20 ms until the next row will be shown/hidden to
-      // create a sliding effect.
-      function rowToggle() {
-        if (direction) {
-          if (row >= 0) {
-            $(trs[row]).hide();
-            row--;
-            timeout = setTimeout(rowToggle, 20);
-          }
+        // If clicked in the middle of expanding a group, stop so we can switch directions.
+        if (timeout) {
+          clearTimeout(timeout);
         }
-        else {
-          if (row < trs.length) {
-            $(trs[row]).removeClass('js-hide').show();
-            row++;
-            timeout = setTimeout(rowToggle, 20);
+
+        // Function to toggle an individual row according to the current direction.
+        // We set a timeout of 20 ms until the next row will be shown/hidden to
+        // create a sliding effect.
+        function rowToggle() {
+          if (direction) {
+            if (row >= 0) {
+              $(trs[row]).hide();
+              row--;
+              timeout = setTimeout(rowToggle, 20);
+            }
+          }
+          else {
+            if (row < trs.length) {
+              $(trs[row]).removeClass('js-hide').show();
+              row++;
+              timeout = setTimeout(rowToggle, 20);
+            }
           }
         }
-      }
 
-      // Kick-off the toggling upon a new click.
-      rowToggle();
+        // Kick-off the toggling upon a new click.
+        rowToggle();
 
-      // Toggle the arrow image next to the test group title.
-      $(this).html(settings.simpleTest.images[(direction ? 0 : 1)]);
-      settings.simpleTest[this.id].imageDirection = !direction;
+        // Toggle the arrow image next to the test group title.
+        $this.html(settings.simpleTest.images[(direction ? 0 : 1)]);
+        settings.simpleTest[this.id].imageDirection = !direction;
 
+      });
     });
   }
 };
@@ -60,7 +61,7 @@ Drupal.behaviors.simpleTestMenuCollapse = {
  */
 Drupal.behaviors.simpleTestSelectAll = {
   attach: function (context, settings) {
-    $('td.simpletest-select-all').each(function () {
+    $('td.simpletest-select-all').once('simpletest-select-all', function () {
       var testCheckboxes = settings.simpleTest['simpletest-test-group-' + $(this).attr('id')].testNames;
       var groupCheckbox = $('<input type="checkbox" class="form-checkbox" id="' + $(this).attr('id') + '-select-all" />');
 
diff --git a/modules/simpletest/tests/actions.test b/modules/simpletest/tests/actions.test
index 23587f0c5..4d58b59cc 100644
--- a/modules/simpletest/tests/actions.test
+++ b/modules/simpletest/tests/actions.test
@@ -97,7 +97,7 @@ class ActionLoopTestCase extends DrupalWebTestCase {
     // recursion level should be kept low enough to prevent the xdebug
     // infinite recursion protection mechanism from aborting the request.
     // See http://drupal.org/node/587634.
-    variable_set('actions_max_stack', mt_rand(3, 12));
+    variable_set('actions_max_stack', 7);
     $this->triggerActions();
   }
 
diff --git a/modules/simpletest/tests/actions_loop_test.info b/modules/simpletest/tests/actions_loop_test.info
index 26b9f4ab7..05d94ff38 100644
--- a/modules/simpletest/tests/actions_loop_test.info
+++ b/modules/simpletest/tests/actions_loop_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/ajax_forms_test.info b/modules/simpletest/tests/ajax_forms_test.info
index 28c76fa8b..f7daa105b 100644
--- a/modules/simpletest/tests/ajax_forms_test.info
+++ b/modules/simpletest/tests/ajax_forms_test.info
@@ -5,8 +5,8 @@ package = Testing
 version = VERSION
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/ajax_test.info b/modules/simpletest/tests/ajax_test.info
index de7e8292c..a6f17e5fe 100644
--- a/modules/simpletest/tests/ajax_test.info
+++ b/modules/simpletest/tests/ajax_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/batch.test b/modules/simpletest/tests/batch.test
index f668e5228..e41bc92be 100644
--- a/modules/simpletest/tests/batch.test
+++ b/modules/simpletest/tests/batch.test
@@ -341,8 +341,6 @@ class BatchPercentagesUnitTestCase extends DrupalUnitTestCase {
       '33' => array('total' => 3, 'current' => 1),
       // 2/3 is closer to 67% than to 66%.
       '67' => array('total' => 3, 'current' => 2),
-      // A full 3/3 should equal 100%.
-      '100' => array('total' => 3, 'current' => 3),
       // 1/199 should round up to 1%.
       '1' => array('total' => 199, 'current' => 1),
       // 198/199 should round down to 99%.
diff --git a/modules/simpletest/tests/batch_test.info b/modules/simpletest/tests/batch_test.info
index 3499be54c..681fc263f 100644
--- a/modules/simpletest/tests/batch_test.info
+++ b/modules/simpletest/tests/batch_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/common_test.info b/modules/simpletest/tests/common_test.info
index 0e301d62a..0b4cc4881 100644
--- a/modules/simpletest/tests/common_test.info
+++ b/modules/simpletest/tests/common_test.info
@@ -7,8 +7,8 @@ stylesheets[all][] = common_test.css
 stylesheets[print][] = common_test.print.css
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/common_test_cron_helper.info b/modules/simpletest/tests/common_test_cron_helper.info
index 486984c35..1495c2159 100644
--- a/modules/simpletest/tests/common_test_cron_helper.info
+++ b/modules/simpletest/tests/common_test_cron_helper.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/database_test.info b/modules/simpletest/tests/database_test.info
index 4e9d5c6e5..33cfe605b 100644
--- a/modules/simpletest/tests/database_test.info
+++ b/modules/simpletest/tests/database_test.info
@@ -5,8 +5,8 @@ package = Testing
 version = VERSION
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/drupal_system_listing_compatible_test/drupal_system_listing_compatible_test.info b/modules/simpletest/tests/drupal_system_listing_compatible_test/drupal_system_listing_compatible_test.info
index 5cdd71bfb..24b7bed8d 100644
--- a/modules/simpletest/tests/drupal_system_listing_compatible_test/drupal_system_listing_compatible_test.info
+++ b/modules/simpletest/tests/drupal_system_listing_compatible_test/drupal_system_listing_compatible_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/drupal_system_listing_incompatible_test/drupal_system_listing_incompatible_test.info b/modules/simpletest/tests/drupal_system_listing_incompatible_test/drupal_system_listing_incompatible_test.info
index 474eddec9..5ebfd25ea 100644
--- a/modules/simpletest/tests/drupal_system_listing_incompatible_test/drupal_system_listing_incompatible_test.info
+++ b/modules/simpletest/tests/drupal_system_listing_incompatible_test/drupal_system_listing_incompatible_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/entity_cache_test.info b/modules/simpletest/tests/entity_cache_test.info
index bbd7d35b7..a70afd5b0 100644
--- a/modules/simpletest/tests/entity_cache_test.info
+++ b/modules/simpletest/tests/entity_cache_test.info
@@ -6,8 +6,8 @@ core = 7.x
 dependencies[] = entity_cache_test_dependency
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/entity_cache_test_dependency.info b/modules/simpletest/tests/entity_cache_test_dependency.info
index 94119124a..157387a70 100644
--- a/modules/simpletest/tests/entity_cache_test_dependency.info
+++ b/modules/simpletest/tests/entity_cache_test_dependency.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/entity_crud_hook_test.info b/modules/simpletest/tests/entity_crud_hook_test.info
index e944705f6..22b784e2b 100644
--- a/modules/simpletest/tests/entity_crud_hook_test.info
+++ b/modules/simpletest/tests/entity_crud_hook_test.info
@@ -5,8 +5,8 @@ package = Testing
 version = VERSION
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/entity_query.test b/modules/simpletest/tests/entity_query.test
index ddfd35433..6d77c508b 100644
--- a/modules/simpletest/tests/entity_query.test
+++ b/modules/simpletest/tests/entity_query.test
@@ -20,7 +20,7 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase {
   }
 
   function setUp() {
-    parent::setUp(array('field_test'));
+    parent::setUp(array('node', 'field_test', 'entity_query_access_test', 'node_access_test'));
 
     field_test_create_bundle('bundle1');
     field_test_create_bundle('bundle2');
@@ -1606,6 +1606,26 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase {
     unset($_GET['order']);
   }
 
+  /**
+   * Tests EntityFieldQuery access on non-node entities.
+   */
+  function testEntityFieldQueryAccess() {
+    // Test as a user with ability to bypass node access.
+    $privileged_user = $this->drupalCreateUser(array('bypass node access', 'access content'));
+    $this->drupalLogin($privileged_user);
+    $this->drupalGet('entity-query-access/test/' . $this->fields[0]['field_name']);
+    $this->assertText('Found entity', 'Returned access response with entities.');
+    $this->drupalLogout();
+
+    // Test as a user that does not have ability to bypass node access or view
+    // all nodes.
+    $regular_user = $this->drupalCreateUser(array('access content'));
+    $this->drupalLogin($regular_user);
+    $this->drupalGet('entity-query-access/test/' . $this->fields[0]['field_name']);
+    $this->assertText('Found entity', 'Returned access response with entities.');
+    $this->drupalLogout();
+  }
+
   /**
    * Fetches the results of an EntityFieldQuery and compares.
    *
@@ -1639,4 +1659,23 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase {
       $this->fail('Exception thrown: '. $e->getMessage());
     }
   }
+
+  /**
+   * Tests EFQ table prefixing with multiple conditions and an altered join.
+   *
+   * @see field_test_query_efq_table_prefixing_test_alter()
+   */
+  function testTablePrefixing() {
+    $query = new EntityFieldQuery();
+    $query = $query
+      ->entityCondition('entity_type', 'test_entity')
+      ->entityCondition('bundle', 'test_bundle')
+      ->entityCondition('entity_id', '1')
+      ->addTag('efq_table_prefixing_test');
+
+    $expected = array(array('test_entity', 1));
+
+    $this->assertEntityFieldQuery($query, $expected, 'An EntityFieldQuery returns the expected results when altered with an additional join on the base table.');
+  }
+
 }
diff --git a/modules/simpletest/tests/entity_query_access_test.info b/modules/simpletest/tests/entity_query_access_test.info
new file mode 100644
index 000000000..45b702bd4
--- /dev/null
+++ b/modules/simpletest/tests/entity_query_access_test.info
@@ -0,0 +1,12 @@
+name = "Entity query access test"
+description = "Support module for checking entity query results."
+package = Testing
+version = VERSION
+core = 7.x
+hidden = TRUE
+
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
+project = "drupal"
+datestamp = "1343839327"
+
diff --git a/modules/simpletest/tests/entity_query_access_test.module b/modules/simpletest/tests/entity_query_access_test.module
new file mode 100644
index 000000000..53641af5a
--- /dev/null
+++ b/modules/simpletest/tests/entity_query_access_test.module
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * @file
+ * Helper module for testing EntityFieldQuery access on any type of entity.
+ */
+
+/**
+ * Implements hook_menu().
+ */
+function entity_query_access_test_menu() {
+  $items['entity-query-access/test/%'] = array(
+    'title' => "Retrieve a sample of entity query access data",
+    'page callback' => 'entity_query_access_test_sample_query',
+    'page arguments' => array(2),
+    'access callback' => TRUE,
+    'type' => MENU_CALLBACK,
+  );
+
+  return $items;
+}
+
+/**
+ * Returns the results from an example EntityFieldQuery.
+ */
+function entity_query_access_test_sample_query($field_name) {
+  global $user;
+
+  // Simulate user does not have access to view all nodes.
+  $access = &drupal_static('node_access_view_all_nodes');
+  $access[$user->uid] = FALSE;
+
+  $query = new EntityFieldQuery();
+  $query
+    ->entityCondition('entity_type', 'test_entity_bundle_key')
+    ->fieldCondition($field_name, 'value', 0, '>')
+    ->entityOrderBy('entity_id', 'ASC');
+  $results = array(
+    'items' => array(),
+    'title' => t('EntityFieldQuery results'),
+  );
+  foreach ($query->execute() as $entity_type => $entity_ids) {
+    foreach ($entity_ids as $entity_id => $entity_stub) {
+      $results['items'][] = format_string('Found entity of type @entity_type with id @entity_id', array('@entity_type' => $entity_type, '@entity_id' => $entity_id));
+    }
+  }
+  if (count($results['items']) > 0) {
+    $output = theme('item_list', $results);
+  }
+  else {
+    $output = 'No results found with EntityFieldQuery.';
+  }
+  return $output;
+}
diff --git a/modules/simpletest/tests/error_test.info b/modules/simpletest/tests/error_test.info
index 80b6ca595..dcccf78d0 100644
--- a/modules/simpletest/tests/error_test.info
+++ b/modules/simpletest/tests/error_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/file_test.info b/modules/simpletest/tests/file_test.info
index 7bac12444..d95d91985 100644
--- a/modules/simpletest/tests/file_test.info
+++ b/modules/simpletest/tests/file_test.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = file_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/filter_test.info b/modules/simpletest/tests/filter_test.info
index 30fcbaa0f..b00109e11 100644
--- a/modules/simpletest/tests/filter_test.info
+++ b/modules/simpletest/tests/filter_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/form.test b/modules/simpletest/tests/form.test
index 2f5a9cd14..985abe31b 100644
--- a/modules/simpletest/tests/form.test
+++ b/modules/simpletest/tests/form.test
@@ -52,7 +52,7 @@ class FormsTestCase extends DrupalWebTestCase {
     $elements['radios']['element'] = array('#title' => $this->randomName(), '#type' => 'radios', '#options' => array('' => t('None'), $this->randomName(), $this->randomName(), $this->randomName()));
     $elements['radios']['empty_values'] = $empty_arrays;
 
-    $elements['checkbox']['element'] = array('#title' => $this->randomName(), '#type' => 'checkbox', '#required' => TRUE, '#title' => $this->randomName());
+    $elements['checkbox']['element'] = array('#title' => $this->randomName(), '#type' => 'checkbox', '#required' => TRUE);
     $elements['checkbox']['empty_values'] = $empty_checkbox;
 
     $elements['checkboxes']['element'] = array('#title' => $this->randomName(), '#type' => 'checkboxes', '#options' => array($this->randomName(), $this->randomName(), $this->randomName()));
@@ -173,6 +173,8 @@ class FormsTestCase extends DrupalWebTestCase {
     $this->assertNoFieldChecked('edit-radios-bar');
     $this->assertNoFieldChecked('edit-radios-optional-foo');
     $this->assertNoFieldChecked('edit-radios-optional-bar');
+    $this->assertNoFieldChecked('edit-radios-optional-default-value-false-foo');
+    $this->assertNoFieldChecked('edit-radios-optional-default-value-false-bar');
 
     // Submit again with required fields set and verify that there are no
     // error messages.
@@ -587,7 +589,7 @@ class FormValidationTestCase extends DrupalWebTestCase {
    */
   function testValidateLimitErrors() {
     $edit = array(
-      'test' => 'invalid', 
+      'test' => 'invalid',
       'test_numeric_index[0]' => 'invalid',
       'test_substring[foo]' => 'invalid',
     );
@@ -1167,6 +1169,51 @@ class FormStateValuesCleanTestCase extends DrupalWebTestCase {
   }
 }
 
+/**
+ * Tests $form_state clearance with form elements having buttons.
+ */
+class FormStateValuesCleanAdvancedTestCase extends DrupalWebTestCase {
+  /**
+   * An image file path for uploading.
+   */
+  protected $image;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Form state values clearance (advanced)',
+      'description' => 'Test proper removal of submitted form values using form_state_values_clean() when having forms with elements containing buttons like "managed_file".',
+      'group' => 'Form API',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('form_test');
+  }
+
+  /**
+   * Tests form_state_values_clean().
+   */
+  function testFormStateValuesCleanAdvanced() {
+
+    // Get an image for uploading.
+    $image_files = $this->drupalGetTestFiles('image');
+    $this->image = current($image_files);
+
+    // Check if the physical file is there.
+    $this->assertTrue(is_file($this->image->uri), t("The image file we're going to upload exists."));
+
+    // "Browse" for the desired file.
+    $edit = array('files[image]' => drupal_realpath($this->image->uri));
+
+    // Post the form.
+    $this->drupalPost('form_test/form-state-values-clean-advanced', $edit, t('Submit'));
+
+    // Expecting a 200 HTTP code.
+    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
+    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
+  }
+}
+
 /**
  * Tests form rebuilding.
  *
diff --git a/modules/simpletest/tests/form_test.info b/modules/simpletest/tests/form_test.info
index 2b0b8ade2..691b663cc 100644
--- a/modules/simpletest/tests/form_test.info
+++ b/modules/simpletest/tests/form_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/form_test.module b/modules/simpletest/tests/form_test.module
index 43a6cbecb..e4ac77b12 100644
--- a/modules/simpletest/tests/form_test.module
+++ b/modules/simpletest/tests/form_test.module
@@ -99,6 +99,14 @@ function form_test_menu() {
     'type' => MENU_CALLBACK,
   );
 
+  $items['form_test/form-state-values-clean-advanced'] = array(
+    'title' => 'Form state values clearance advanced test',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('form_test_form_state_values_clean_advanced_form'),
+    'access arguments' => array('access content'),
+    'type' => MENU_CALLBACK,
+  );
+
   $items['form-test/checkbox'] = array(
     'title' => t('Form test'),
     'page callback' => 'drupal_get_form',
@@ -372,6 +380,12 @@ function form_test_validate_required_form($form, &$form_state) {
     '#title' => 'Radios (optional)',
     '#options' => $options,
   );
+  $form['radios_optional_default_value_false'] = array(
+    '#type' => 'radios',
+    '#title' => 'Radios (optional, with a default value of FALSE)',
+    '#options' => $options,
+    '#default_value' => FALSE,
+  );
   $form['actions'] = array('#type' => 'actions');
   $form['actions']['submit'] = array('#type' => 'submit', '#value' => 'Submit');
   return $form;
@@ -872,6 +886,33 @@ function form_test_form_state_values_clean_form_submit($form, &$form_state) {
   exit;
 }
 
+/**
+ * Form constructor for the form_state_values_clean() test.
+ */
+function form_test_form_state_values_clean_advanced_form($form, &$form_state) {
+  // Build an example form containing a managed file and a submit form element.
+  $form['image'] = array(
+    '#type' => 'managed_file',
+    '#title' => t('Image'),
+    '#upload_location' => 'public://',
+    '#default_value' => 0,
+  );
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Submit'),
+  );
+  return $form;
+}
+
+/**
+ * Form submission handler for form_test_form_state_values_clean_advanced_form().
+ */
+function form_test_form_state_values_clean_advanced_form_submit($form, &$form_state) {
+  form_state_values_clean($form_state);
+  print t('You WIN!');
+  exit;
+}
+
 /**
  * Build a form to test a checkbox.
  */
diff --git a/modules/simpletest/tests/image_test.info b/modules/simpletest/tests/image_test.info
index a7b747951..9082d46c9 100644
--- a/modules/simpletest/tests/image_test.info
+++ b/modules/simpletest/tests/image_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/menu.test b/modules/simpletest/tests/menu.test
index a7fb8a484..b31fee6e3 100644
--- a/modules/simpletest/tests/menu.test
+++ b/modules/simpletest/tests/menu.test
@@ -242,12 +242,12 @@ class MenuRouterTestCase extends DrupalWebTestCase {
     $loggedInUser = $this->drupalCreateUser(array());
     $this->drupalLogin($loggedInUser);
 
-    $this->DrupalGet('user/login');
+    $this->drupalGet('user/login');
     // Check that we got to 'user'.
     $this->assertTrue($this->url == url('user', array('absolute' => TRUE)), t("Logged-in user redirected to q=user on accessing q=user/login"));
 
     // user/register should redirect to user/UID/edit.
-    $this->DrupalGet('user/register');
+    $this->drupalGet('user/register');
     $this->assertTrue($this->url == url('user/' . $this->loggedInUser->uid . '/edit', array('absolute' => TRUE)), t("Logged-in user redirected to q=user/UID/edit on accessing q=user/register"));
   }
 
diff --git a/modules/simpletest/tests/menu_test.info b/modules/simpletest/tests/menu_test.info
index b3630c42d..04515d322 100644
--- a/modules/simpletest/tests/menu_test.info
+++ b/modules/simpletest/tests/menu_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/module_test.info b/modules/simpletest/tests/module_test.info
index 4e657f261..d3575f191 100644
--- a/modules/simpletest/tests/module_test.info
+++ b/modules/simpletest/tests/module_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/path_test.info b/modules/simpletest/tests/path_test.info
index 85298ec00..7a265dd90 100644
--- a/modules/simpletest/tests/path_test.info
+++ b/modules/simpletest/tests/path_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/requirements1_test.info b/modules/simpletest/tests/requirements1_test.info
index e26b5622d..16cb274be 100644
--- a/modules/simpletest/tests/requirements1_test.info
+++ b/modules/simpletest/tests/requirements1_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/requirements2_test.info b/modules/simpletest/tests/requirements2_test.info
index 6231da120..d2beee85c 100644
--- a/modules/simpletest/tests/requirements2_test.info
+++ b/modules/simpletest/tests/requirements2_test.info
@@ -7,8 +7,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/session_test.info b/modules/simpletest/tests/session_test.info
index 265961635..f32fd4bec 100644
--- a/modules/simpletest/tests/session_test.info
+++ b/modules/simpletest/tests/session_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/system_dependencies_test.info b/modules/simpletest/tests/system_dependencies_test.info
index ec796e629..177c729e6 100644
--- a/modules/simpletest/tests/system_dependencies_test.info
+++ b/modules/simpletest/tests/system_dependencies_test.info
@@ -6,8 +6,8 @@ core = 7.x
 hidden = TRUE
 dependencies[] = _missing_dependency
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/system_incompatible_core_version_dependencies_test.info b/modules/simpletest/tests/system_incompatible_core_version_dependencies_test.info
index 623be8da7..7f80147e7 100644
--- a/modules/simpletest/tests/system_incompatible_core_version_dependencies_test.info
+++ b/modules/simpletest/tests/system_incompatible_core_version_dependencies_test.info
@@ -6,8 +6,8 @@ core = 7.x
 hidden = TRUE
 dependencies[] = system_incompatible_core_version_test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/system_incompatible_core_version_test.info b/modules/simpletest/tests/system_incompatible_core_version_test.info
index 598534ee8..8b549b1a3 100644
--- a/modules/simpletest/tests/system_incompatible_core_version_test.info
+++ b/modules/simpletest/tests/system_incompatible_core_version_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 5.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/system_incompatible_module_version_dependencies_test.info b/modules/simpletest/tests/system_incompatible_module_version_dependencies_test.info
index ef04a9954..f49369269 100644
--- a/modules/simpletest/tests/system_incompatible_module_version_dependencies_test.info
+++ b/modules/simpletest/tests/system_incompatible_module_version_dependencies_test.info
@@ -7,8 +7,8 @@ hidden = TRUE
 ; system_incompatible_module_version_test declares version 1.0
 dependencies[] = system_incompatible_module_version_test (>2.0)
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/system_incompatible_module_version_test.info b/modules/simpletest/tests/system_incompatible_module_version_test.info
index b13677d68..f36815cb6 100644
--- a/modules/simpletest/tests/system_incompatible_module_version_test.info
+++ b/modules/simpletest/tests/system_incompatible_module_version_test.info
@@ -5,8 +5,8 @@ version = 1.0
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/system_test.info b/modules/simpletest/tests/system_test.info
index f4b5e5dff..664f6a6cc 100644
--- a/modules/simpletest/tests/system_test.info
+++ b/modules/simpletest/tests/system_test.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = system_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/taxonomy_test.info b/modules/simpletest/tests/taxonomy_test.info
index fde85316e..1d6360853 100644
--- a/modules/simpletest/tests/taxonomy_test.info
+++ b/modules/simpletest/tests/taxonomy_test.info
@@ -6,8 +6,8 @@ core = 7.x
 hidden = TRUE
 dependencies[] = taxonomy
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/theme.test b/modules/simpletest/tests/theme.test
index ba6440028..27a8e47b9 100644
--- a/modules/simpletest/tests/theme.test
+++ b/modules/simpletest/tests/theme.test
@@ -124,6 +124,37 @@ class ThemeTestCase extends DrupalWebTestCase {
     module_enable(array('theme_test'), FALSE);
     $this->assertIdentical(theme('theme_test_foo', array('foo' => 'c')), 'c', 'The theme registry contains theme_test_foo again after re-enabling the module.');
   }
+
+  /**
+   * Test the list_themes() function.
+   */
+  function testListThemes() {
+    $themes = list_themes();
+    // Check if drupal_theme_access() retrieves enabled themes properly from list_themes().
+    $this->assertTrue(drupal_theme_access('test_theme'), t('Enabled theme detected'));
+    // Check if list_themes() returns disabled themes.
+    $this->assertTrue(array_key_exists('test_basetheme', $themes), t('Disabled theme detected'));
+    // Check for base theme and subtheme lists.
+    $base_theme_list = array('test_basetheme' => 'Theme test base theme');
+    $sub_theme_list = array('test_subtheme' => 'Theme test subtheme');
+    $this->assertIdentical($themes['test_basetheme']->sub_themes, $sub_theme_list, t('Base theme\'s object includes list of subthemes.'));
+    $this->assertIdentical($themes['test_subtheme']->base_themes, $base_theme_list, t('Subtheme\'s object includes list of base themes.'));
+    // Check for theme engine in subtheme.
+    $this->assertIdentical($themes['test_subtheme']->engine, 'phptemplate', t('Subtheme\'s object includes the theme engine.'));
+    // Check for theme engine prefix.
+    $this->assertIdentical($themes['test_basetheme']->prefix, 'phptemplate', t('Base theme\'s object includes the theme engine prefix.'));
+    $this->assertIdentical($themes['test_subtheme']->prefix, 'phptemplate', t('Subtheme\'s object includes the theme engine prefix.'));
+  }
+
+  /**
+   * Test the theme_get_setting() function.
+   */
+  function testThemeGetSetting() {
+    $GLOBALS['theme_key'] = 'test_theme';
+    $this->assertIdentical(theme_get_setting('theme_test_setting'), 'default value', t('theme_get_setting() uses the default theme automatically.'));
+    $this->assertNotEqual(theme_get_setting('subtheme_override', 'test_basetheme'), theme_get_setting('subtheme_override', 'test_subtheme'), t('Base theme\'s default settings values can be overridden by subtheme.'));
+    $this->assertIdentical(theme_get_setting('basetheme_only', 'test_subtheme'), 'base theme value', t('Base theme\'s default settings values are inherited by subtheme.'));
+  }
 }
 
 /**
diff --git a/modules/simpletest/tests/theme_test.info b/modules/simpletest/tests/theme_test.info
index c7e6ac1b7..341e921d1 100644
--- a/modules/simpletest/tests/theme_test.info
+++ b/modules/simpletest/tests/theme_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/theme_test.module b/modules/simpletest/tests/theme_test.module
index a9bd2ad24..61a12bb70 100644
--- a/modules/simpletest/tests/theme_test.module
+++ b/modules/simpletest/tests/theme_test.module
@@ -25,6 +25,8 @@ function theme_test_theme($existing, $type, $theme, $path) {
  */
 function theme_test_system_theme_info() {
   $themes['test_theme'] = drupal_get_path('module', 'theme_test') . '/themes/test_theme/test_theme.info';
+  $themes['test_basetheme'] = drupal_get_path('module', 'theme_test') . '/themes/test_basetheme/test_basetheme.info';
+  $themes['test_subtheme'] = drupal_get_path('module', 'theme_test') . '/themes/test_subtheme/test_subtheme.info';
   return $themes;
 }
 
diff --git a/modules/simpletest/tests/themes/test_basetheme/test_basetheme.info b/modules/simpletest/tests/themes/test_basetheme/test_basetheme.info
new file mode 100644
index 000000000..8ebbe2c90
--- /dev/null
+++ b/modules/simpletest/tests/themes/test_basetheme/test_basetheme.info
@@ -0,0 +1,13 @@
+name = Theme test base theme
+description = Test theme which acts as a base theme for other test subthemes.
+core = 7.x
+hidden = TRUE
+
+settings[basetheme_only] = base theme value
+settings[subtheme_override] = base theme value
+
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
+project = "drupal"
+datestamp = "1343839327"
+
diff --git a/modules/simpletest/tests/themes/test_subtheme/test_subtheme.info b/modules/simpletest/tests/themes/test_subtheme/test_subtheme.info
new file mode 100644
index 000000000..9e65f1f3d
--- /dev/null
+++ b/modules/simpletest/tests/themes/test_subtheme/test_subtheme.info
@@ -0,0 +1,13 @@
+name = Theme test subtheme
+description = Test theme which uses test_basetheme as the base theme.
+core = 7.x
+base theme = test_basetheme
+hidden = TRUE
+
+settings[subtheme_override] = subtheme value
+
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
+project = "drupal"
+datestamp = "1343839327"
+
diff --git a/modules/simpletest/tests/themes/test_theme/test_theme.info b/modules/simpletest/tests/themes/test_theme/test_theme.info
index a27c73d2b..69711913b 100644
--- a/modules/simpletest/tests/themes/test_theme/test_theme.info
+++ b/modules/simpletest/tests/themes/test_theme/test_theme.info
@@ -15,8 +15,10 @@ hidden = TRUE
 ; file within the theme folder.
 stylesheets[all][] = system.base.css
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+settings[theme_test_setting] = default value
+
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/update_script_test.info b/modules/simpletest/tests/update_script_test.info
index 33ec1a056..85021b464 100644
--- a/modules/simpletest/tests/update_script_test.info
+++ b/modules/simpletest/tests/update_script_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/update_test_1.info b/modules/simpletest/tests/update_test_1.info
index 9508b38e7..879aaddd2 100644
--- a/modules/simpletest/tests/update_test_1.info
+++ b/modules/simpletest/tests/update_test_1.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/update_test_2.info b/modules/simpletest/tests/update_test_2.info
index 9508b38e7..879aaddd2 100644
--- a/modules/simpletest/tests/update_test_2.info
+++ b/modules/simpletest/tests/update_test_2.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/update_test_3.info b/modules/simpletest/tests/update_test_3.info
index 9508b38e7..879aaddd2 100644
--- a/modules/simpletest/tests/update_test_3.info
+++ b/modules/simpletest/tests/update_test_3.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/upgrade/upgrade.test b/modules/simpletest/tests/upgrade/upgrade.test
index 172f30e69..9df8ec779 100644
--- a/modules/simpletest/tests/upgrade/upgrade.test
+++ b/modules/simpletest/tests/upgrade/upgrade.test
@@ -71,7 +71,11 @@ abstract class UpgradePathTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Override of DrupalWebTestCase::setUp() specialized for upgrade testing.
+   * Overrides DrupalWebTestCase::setUp() for upgrade testing.
+   *
+   * @see DrupalWebTestCase::prepareDatabasePrefix()
+   * @see DrupalWebTestCase::changeDatabasePrefix()
+   * @see DrupalWebTestCase::prepareEnvironment()
    */
   protected function setUp() {
     // We are going to set a missing zlib requirement property for usage
@@ -93,55 +97,33 @@ abstract class UpgradePathTestCase extends DrupalWebTestCase {
 
     $this->loadedModules = module_list();
 
-    // Generate a temporary prefixed database to ensure that tests have a clean starting point.
-    $this->databasePrefix = 'simpletest' . mt_rand(1000, 1000000);
-    db_update('simpletest_test_id')
-      ->fields(array('last_prefix' => $this->databasePrefix))
-      ->condition('test_id', $this->testId)
-      ->execute();
+    // Create the database prefix for this test.
+    $this->prepareDatabasePrefix();
 
-    // Clone the current connection and replace the current prefix.
-    $connection_info = Database::getConnectionInfo('default');
-    Database::renameConnection('default', 'simpletest_original_default');
-    foreach ($connection_info as $target => $value) {
-      $connection_info[$target]['prefix'] = array(
-        'default' => $value['prefix']['default'] . $this->databasePrefix,
-      );
+    // Prepare the environment for running tests.
+    $this->prepareEnvironment();
+    if (!$this->setupEnvironment) {
+      return FALSE;
     }
-    Database::addConnectionInfo('default', 'default', $connection_info['default']);
 
-    // Store necessary current values before switching to prefixed database.
-    $this->originalLanguage = $language;
-    $this->originalLanguageDefault = variable_get('language_default');
-    $this->originalFileDirectory = variable_get('file_public_path', conf_path() . '/files');
-    $this->originalProfile = drupal_get_profile();
-    $clean_url_original = variable_get('clean_url', 0);
+    // Reset all statics and variables to perform tests in a clean environment.
+    $conf = array();
+    drupal_static_reset();
+
+    // Change the database prefix.
+    // All static variables need to be reset before the database prefix is
+    // changed, since DrupalCacheArray implementations attempt to
+    // write back to persistent caches when they are destructed.
+    $this->changeDatabasePrefix();
+    if (!$this->setupDatabasePrefix) {
+      return FALSE;
+    }
 
     // Unregister the registry.
     // This is required to make sure that the database layer works properly.
     spl_autoload_unregister('drupal_autoload_class');
     spl_autoload_unregister('drupal_autoload_interface');
 
-    // Create test directories ahead of installation so fatal errors and debug
-    // information can be logged during installation process.
-    // Use mock files directories with the same prefix as the database.
-    $public_files_directory  = $this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10);
-    $private_files_directory = $public_files_directory . '/private';
-    $temp_files_directory    = $private_files_directory . '/temp';
-
-    // Create the directories.
-    file_prepare_directory($public_files_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
-    file_prepare_directory($private_files_directory, FILE_CREATE_DIRECTORY);
-    file_prepare_directory($temp_files_directory, FILE_CREATE_DIRECTORY);
-    $this->generatedTestFiles = FALSE;
-
-    // Log fatal errors.
-    ini_set('log_errors', 1);
-    ini_set('error_log', $public_files_directory . '/error.log');
-
-    // Reset all statics and variables to perform tests in a clean environment.
-    $conf = array();
-
     // Load the database from the portable PHP dump.
     // The files may be gzipped.
     foreach ($this->databaseDumpFiles as $file) {
@@ -152,85 +134,29 @@ abstract class UpgradePathTestCase extends DrupalWebTestCase {
     }
 
     // Set path variables.
-    $this->variable_set('file_public_path', $public_files_directory);
-    $this->variable_set('file_private_path', $private_files_directory);
-    $this->variable_set('file_temporary_path', $temp_files_directory);
+    $this->variable_set('file_public_path', $this->public_files_directory);
+    $this->variable_set('file_private_path', $this->private_files_directory);
+    $this->variable_set('file_temporary_path', $this->temp_files_directory);
 
     $this->pass('Finished loading the dump.');
 
-    // Load user 1.
-    $this->originalUser = $user;
+    // Ensure that the session is not written to the new environment and replace
+    // the global $user session with uid 1 from the new test site.
     drupal_save_session(FALSE);
+    // Login as uid 1.
     $user = db_query('SELECT * FROM {users} WHERE uid = :uid', array(':uid' => 1))->fetchObject();
 
     // Generate and set a D6-compatible session cookie.
     $this->prepareD7Session();
 
     // Restore necessary variables.
-    $this->variable_set('clean_url', $clean_url_original);
+    $this->variable_set('clean_url', $this->originalCleanUrl);
     $this->variable_set('site_mail', 'simpletest@example.com');
 
     drupal_set_time_limit($this->timeLimit);
     $this->setup = TRUE;
   }
 
-  /**
-   * Override of DrupalWebTestCase::tearDown() specialized for upgrade testing.
-   */
-  protected function tearDown() {
-    global $user, $language;
-
-    if (!$this->zlibInstalled) {
-      parent::tearDown();
-      return;
-    }
-
-    // In case a fatal error occurred that was not in the test process read the
-    // log to pick up any fatal errors.
-    simpletest_log_read($this->testId, $this->databasePrefix, get_class($this), TRUE);
-
-    // Delete temporary files directory.
-    file_unmanaged_delete_recursive($this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10));
-
-    // Get back to the original connection.
-    Database::removeConnection('default');
-    Database::renameConnection('simpletest_original_default', 'default');
-
-    // Remove all prefixed tables.
-    $tables = db_find_tables($this->databasePrefix . '%');
-    foreach ($tables as $table) {
-      db_drop_table($table);
-    }
-
-    // Return the user to the original one.
-    $user = $this->originalUser;
-    drupal_save_session(TRUE);
-
-    // Ensure that internal logged in variable and cURL options are reset.
-    $this->loggedInUser = FALSE;
-    $this->additionalCurlOptions = array();
-
-    // Reload module list and implementations to ensure that test module hooks
-    // aren't called after tests.
-    module_list(TRUE);
-    module_implements('', FALSE, TRUE);
-
-    // Reset the Field API.
-    field_cache_clear();
-
-    // Rebuild caches.
-    parent::refreshVariables();
-
-    // Reset language.
-    $language = $this->originalLanguage;
-    if ($this->originalLanguageDefault) {
-      $GLOBALS['conf']['language_default'] = $this->originalLanguageDefault;
-    }
-
-    // Close the CURL handler.
-    $this->curlClose();
-  }
-
   /**
    * Specialized variable_set() that works even if the child site is not upgraded.
    *
diff --git a/modules/simpletest/tests/url_alter_test.info b/modules/simpletest/tests/url_alter_test.info
index efeb1d842..00e73ab7a 100644
--- a/modules/simpletest/tests/url_alter_test.info
+++ b/modules/simpletest/tests/url_alter_test.info
@@ -5,8 +5,8 @@ package = Testing
 version = VERSION
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/simpletest/tests/xmlrpc_test.info b/modules/simpletest/tests/xmlrpc_test.info
index ba2aa341a..36cdc17a8 100644
--- a/modules/simpletest/tests/xmlrpc_test.info
+++ b/modules/simpletest/tests/xmlrpc_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/statistics/statistics.admin.inc b/modules/statistics/statistics.admin.inc
index 6606b8b95..415fd0054 100644
--- a/modules/statistics/statistics.admin.inc
+++ b/modules/statistics/statistics.admin.inc
@@ -2,11 +2,18 @@
 
 /**
  * @file
- * Admin page callbacks for the statistics module.
+ * Admin page callbacks for the Statistics module.
  */
 
 /**
- * Menu callback; presents the "recent hits" page.
+ * Page callback: Displays the "recent hits" page.
+ *
+ * This displays the pages with recent hits in a given time interval that
+ * haven't been flushed yet. The flush interval is set on the statistics
+ * settings form, but is dependent on cron running.
+ *
+ * @return
+ *   A render array containing information about the most recent hits.
  */
 function statistics_recent_hits() {
   $header = array(
@@ -45,7 +52,14 @@ function statistics_recent_hits() {
 }
 
 /**
- * Menu callback; presents the "top pages" page.
+ * Page callback: Displays statistics for the "top pages" (most accesses).
+ *
+ * This displays the pages with the most hits (the "top pages") within a given
+ * time period that haven't been flushed yet. The flush interval is set on the
+ * statistics settings form, but is dependent on cron running.
+ *
+ * @return
+ *   A render array containing information about the the top pages.
  */
 function statistics_top_pages() {
   $header = array(
@@ -57,7 +71,8 @@ function statistics_top_pages() {
 
   $query = db_select('accesslog', 'a', array('target' => 'slave'))->extend('PagerDefault')->extend('TableSort');
   $query->addExpression('COUNT(path)', 'hits');
-  // MAX(title) avoids having empty node titles which otherwise causes duplicates in the top pages list
+  // MAX(title) avoids having empty node titles which otherwise causes
+  // duplicates in the top pages list.
   $query->addExpression('MAX(title)', 'title');
   $query->addExpression('AVG(timer)', 'average_time');
   $query->addExpression('SUM(timer)', 'total_time');
@@ -90,7 +105,14 @@ function statistics_top_pages() {
 }
 
 /**
- * Menu callback; presents the "top visitors" page.
+ * Page callback: Displays the "top visitors" page.
+ *
+ * This displays the pages with the top number of visitors in a given time
+ * interval that haven't been flushed yet. The flush interval is set on the
+ * statistics settings form, but is dependent on cron running.
+ *
+ * @return
+ *   A render array containing the top visitors information.
  */
 function statistics_top_visitors() {
 
@@ -143,7 +165,14 @@ function statistics_top_visitors() {
 }
 
 /**
- * Menu callback; presents the "referrer" page.
+ * Page callback: Displays the "top referrers" in the access logs.
+ *
+ * This displays the pages with the top referrers in a given time interval that
+ * haven't been flushed yet. The flush interval is set on the statistics
+ * settings form, but is dependent on cron running.
+ *
+ * @return
+ *   A render array containing the top referrers information.
  */
 function statistics_top_referrers() {
   drupal_set_title(t('Top referrers in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))), PASS_THROUGH);
@@ -189,7 +218,14 @@ function statistics_top_referrers() {
 }
 
 /**
- * Menu callback; Displays recent page accesses.
+ * Page callback: Gathers page access statistics suitable for rendering.
+ *
+ * @param $aid
+ *   The unique accesslog ID.
+ *
+ * @return
+ *   A render array containing page access statistics. If information for the
+ *   page was not found, drupal_not_found() is called.
  */
 function statistics_access_log($aid) {
   $access = db_query('SELECT a.*, u.name FROM {accesslog} a LEFT JOIN {users} u ON a.uid = u.uid WHERE aid = :aid', array(':aid' => $aid))->fetch();
@@ -233,7 +269,7 @@ function statistics_access_log($aid) {
 }
 
 /**
- * Form builder; Configure access logging.
+ * Form constructor for the statistics administration form.
  *
  * @ingroup forms
  * @see system_settings_form()
diff --git a/modules/statistics/statistics.info b/modules/statistics/statistics.info
index baff9b842..42af6abd5 100644
--- a/modules/statistics/statistics.info
+++ b/modules/statistics/statistics.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = statistics.test
 configure = admin/config/system/statistics
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/statistics/statistics.install b/modules/statistics/statistics.install
index d5855a77f..b85743553 100644
--- a/modules/statistics/statistics.install
+++ b/modules/statistics/statistics.install
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Install, update and uninstall functions for the statistics module.
+ * Install, update, and uninstall functions for the Statistics module.
  */
 
 /**
@@ -154,5 +154,5 @@ function statistics_update_7000() {
 }
 
 /**
- * @} End of "addtogroup updates-6.x-to-7.x"
+ * @} End of "addtogroup updates-6.x-to-7.x".
  */
diff --git a/modules/statistics/statistics.module b/modules/statistics/statistics.module
index 89cda6dcf..81d24b755 100644
--- a/modules/statistics/statistics.module
+++ b/modules/statistics/statistics.module
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Logs access statistics for your site.
+ * Logs and displays access statistics for a site.
  */
 
 /**
@@ -45,7 +45,7 @@ function statistics_help($path, $arg) {
 /**
  * Implements hook_exit().
  *
- * This is where statistics are gathered on page accesses.
+ * Gathers statistics for page accesses.
  */
 function statistics_exit() {
   global $user;
@@ -249,20 +249,20 @@ function statistics_cron() {
 }
 
 /**
- * Returns all time or today top or last viewed node(s).
+ * Returns the most viewed content of all time, today, or the last-viewed node.
  *
  * @param $dbfield
- *   one of
- *   - 'totalcount': top viewed content of all time.
- *   - 'daycount': top viewed content for today.
- *   - 'timestamp': last viewed node.
- *
+ *   The database field to use, one of:
+ *   - 'totalcount': Integer that shows the top viewed content of all time.
+ *   - 'daycount': Integer that shows the top viewed content for today.
+ *   - 'timestamp': Integer that shows only the last viewed node.
  * @param $dbrows
- *   number of rows to be returned.
+ *   The number of rows to be returned.
  *
- * @return
- *   A query result containing n.nid, n.title, u.uid, u.name of the selected node(s)
- *   or FALSE if the query could not be executed correctly.
+ * @return SelectQuery|FALSE
+ *   A query result containing the node ID, title, user ID that owns the node,
+ *   and the username for the selected node(s), or FALSE if the query could not
+ *   be executed correctly.
  */
 function statistics_title_list($dbfield, $dbrows) {
   if (in_array($dbfield, array('totalcount', 'daycount', 'timestamp'))) {
@@ -288,14 +288,15 @@ function statistics_title_list($dbfield, $dbrows) {
  * Retrieves a node's "view statistics".
  *
  * @param $nid
- *   node ID
+ *   The node ID.
  *
  * @return
- *   An array with three entries: [0]=totalcount, [1]=daycount, [2]=timestamp
- *   - totalcount: count of the total number of times that node has been viewed.
- *   - daycount: count of the total number of times that node has been viewed "today".
- *     For the daycount to be reset, cron must be enabled.
- *   - timestamp: timestamp of when that node was last viewed.
+ *   An associative array containing:
+ *   - totalcount: Integer for the total number of times the node has been
+ *     viewed.
+ *   - daycount: Integer for the total number of times the node has been viewed
+ *     "today". For the daycount to be reset, cron must be enabled.
+ *   - timestamp: Integer for the timestamp of when the node was last viewed.
  */
 function statistics_get($nid) {
 
@@ -374,8 +375,15 @@ function statistics_block_view($delta = '') {
 }
 
 /**
- * It is possible to adjust the width of columns generated by the
- * statistics module.
+ * Generates a link to a path, truncating the displayed text to a given width.
+ *
+ * @param $path
+ *   The path to generate the link for.
+ * @param $width
+ *   The width to set the displayed text of the path.
+ *
+ * @return
+ *   A string as a link, truncated to the width, linked to the given $path.
  */
 function _statistics_link($path, $width = 35) {
   $title = drupal_get_path_alias($path);
@@ -383,6 +391,17 @@ function _statistics_link($path, $width = 35) {
   return l($title, $path);
 }
 
+/**
+ * Formats an item for display, including both the item title and the link.
+ *
+ * @param $title
+ *   The text to link to a path; will be truncated to a maximum width of 35.
+ * @param $path
+ *   The path to link to; will default to '/'.
+ *
+ * @return
+ *   An HTML string with $title linked to the $path.
+ */
 function _statistics_format_item($title, $path) {
   $path = ($path ? $path : '/');
   $output  = ($title ? "$title<br />" : '');
diff --git a/modules/statistics/statistics.pages.inc b/modules/statistics/statistics.pages.inc
index bb31f9838..8bd9712f6 100644
--- a/modules/statistics/statistics.pages.inc
+++ b/modules/statistics/statistics.pages.inc
@@ -2,9 +2,16 @@
 
 /**
  * @file
- * User page callbacks for the statistics module.
+ * User page callbacks for the Statistics module.
  */
 
+/**
+ * Page callback: Displays statistics for a node.
+ *
+ * @return
+ *   A render array containing node statistics. If information for the node was
+ *   not found, this will deliver a page not found error via drupal_not_found().
+ */
 function statistics_node_tracker() {
   if ($node = node_load(arg(1))) {
 
@@ -52,6 +59,13 @@ function statistics_node_tracker() {
   }
 }
 
+/**
+ * Page callback: Displays statistics for a user.
+ *
+ * @return array
+ *   A render array containing user statistics. If information for the user was
+ *   not found, this will deliver a page not found error via drupal_not_found().
+ */
 function statistics_user_tracker() {
   if ($account = user_load(arg(1))) {
 
diff --git a/modules/statistics/statistics.test b/modules/statistics/statistics.test
index f12490acf..a40ecc80e 100644
--- a/modules/statistics/statistics.test
+++ b/modules/statistics/statistics.test
@@ -2,11 +2,11 @@
 
 /**
  * @file
- * Tests for statistics.module.
+ * Tests for the Statistics module.
  */
 
 /**
- * Sets up a base class for the Statistics module.
+ * Defines a base class for testing the Statistics module.
  */
 class StatisticsTestCase extends DrupalWebTestCase {
 
@@ -46,10 +46,10 @@ class StatisticsTestCase extends DrupalWebTestCase {
 }
 
 /**
- * Tests that logging via statistics_exit() works for cached and uncached pages.
+ * Tests that logging via statistics_exit() works for all pages.
  *
- * Subclass DrupalWebTestCase rather than StatisticsTestCase, because we want
- * to test requests from an anonymous user.
+ * We subclass DrupalWebTestCase rather than StatisticsTestCase, because we
+ * want to test requests from an anonymous user.
  */
 class StatisticsLoggingTestCase extends DrupalWebTestCase {
   public static function getInfo() {
@@ -282,10 +282,24 @@ class StatisticsBlockVisitorsTestCase extends StatisticsTestCase {
 }
 
 /**
- * Test statistics administration screen.
+ * Tests the statistics administration screen.
  */
 class StatisticsAdminTestCase extends DrupalWebTestCase {
+
+  /**
+   * A user that has permission to administer and access statistics.
+   *
+   * @var object|FALSE
+   *
+   * A fully loaded user object, or FALSE if user creation failed.
+   */
   protected $privileged_user;
+
+  /**
+   * A page node for which to check access statistics.
+   *
+   * @var object
+   */
   protected $test_node;
 
   public static function getInfo() {
@@ -422,7 +436,7 @@ class StatisticsAdminTestCase extends DrupalWebTestCase {
 }
 
 /**
- * Test statistics token replacement in strings.
+ * Tests statistics token replacement in strings.
  */
 class StatisticsTokenReplaceTestCase extends StatisticsTestCase {
   public static function getInfo() {
diff --git a/modules/syslog/syslog.info b/modules/syslog/syslog.info
index 01d2cb4e7..783b2047c 100644
--- a/modules/syslog/syslog.info
+++ b/modules/syslog/syslog.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 files[] = syslog.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/system/image.gd.inc b/modules/system/image.gd.inc
index 39f86dc30..91c0b05ff 100644
--- a/modules/system/image.gd.inc
+++ b/modules/system/image.gd.inc
@@ -6,7 +6,7 @@
  */
 
 /**
- * @ingroup image
+ * @addtogroup image
  * @{
  */
 
@@ -363,5 +363,5 @@ function image_gd_get_info(stdClass $image) {
 }
 
 /**
- * @} End of "ingroup image".
+ * @} End of "addtogroup image".
  */
diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc
index e9682e7dd..23a975b0c 100644
--- a/modules/system/system.admin.inc
+++ b/modules/system/system.admin.inc
@@ -400,7 +400,7 @@ function system_theme_settings($form, &$form_state, $key = '') {
   // Default settings are defined in theme_get_setting() in includes/theme.inc
   if ($key) {
     $var = 'theme_' . $key . '_settings';
-    $themes = system_rebuild_theme_data();
+    $themes = list_themes();
     $features = $themes[$key]->info['features'];
   }
   else {
diff --git a/modules/system/system.api.php b/modules/system/system.api.php
index e28386997..79ac8f169 100644
--- a/modules/system/system.api.php
+++ b/modules/system/system.api.php
@@ -97,6 +97,18 @@ function hook_hook_info_alter(&$hooks) {
  *     instead specify a callback function here, which will be called to
  *     determine the entity label. See also the entity_label() function, which
  *     implements this logic.
+ *   - language callback: (optional) A function taking an entity and an entity
+ *     type as arguments and returning a language code. In most situations, when
+ *     needing to determine this value, inspecting a property named after the
+ *     'language' element of the 'entity keys' should be enough. The language
+ *     callback is meant to be used primarily for temporary alterations of the
+ *     property value: entity-defining modules are encouraged to always define a
+ *     language property, instead of using the callback as main entity language
+ *     source. In fact not having a language property defined is likely to
+ *     prevent an entity from being queried by language. Moreover, given that
+ *     entity_language() is not necessarily used everywhere it would be
+ *     appropriate, modules implementing the language callback should be aware
+ *     that this might not be always called.
  *   - fieldable: Set to TRUE if you want your entity type to accept fields
  *     being attached to it.
  *   - translation: An associative array of modules registered as field
@@ -123,6 +135,13 @@ function hook_hook_info_alter(&$hooks) {
  *       'subject' should be specified here. If complex logic is required to
  *       build the label, a 'label callback' should be defined instead (see
  *       the 'label callback' section above for details).
+ *     - language: The name of the property, typically 'language', that contains
+ *       the language code representing the language the entity has been created
+ *       in. This value may be changed when editing the entity and represents
+ *       the language its textual components are supposed to have. If no
+ *       language property is available, the 'language callback' may be used
+ *       instead. This entry can be omitted if the entities of this type are not
+ *       language-aware.
  *   - bundle keys: An array describing how the Field API can extract the
  *     information it needs from the bundle objects for this type. This entry
  *     is required if the 'path' provided in the 'bundles'/'admin' section
@@ -195,6 +214,7 @@ function hook_entity_info() {
         'id' => 'nid',
         'revision' => 'vid',
         'bundle' => 'type',
+        'language' => 'language',
       ),
       'bundle keys' => array(
         'bundle' => 'type',
@@ -1030,7 +1050,7 @@ function hook_menu_get_item_alter(&$router_item, $path, $original_map) {
  * is invoked to retrieve a value that is used in the path in place of the
  * wildcard. A good example is user.module, which defines
  * user_uid_optional_to_arg() (corresponding to the menu entry
- * 'user/%user_uid_optional'). This function returns the user ID of the
+ * 'tracker/%user_uid_optional'). This function returns the user ID of the
  * current user.
  *
  * The _to_arg() function will get called with three arguments:
@@ -1797,8 +1817,8 @@ function hook_forms($form_id, $args) {
  * used to set up global parameters that are needed later in the request.
  *
  * Only use this hook if your code must run even for cached page views. This
- * hook is called before modules or most include files are loaded into memory.
- * It happens while Drupal is still in bootstrap mode.
+ * hook is called before the theme, modules, or most include files are loaded
+ * into memory. It happens while Drupal is still in bootstrap mode.
  *
  * @see hook_init()
  */
@@ -1813,7 +1833,8 @@ function hook_boot() {
  *
  * This hook is run at the beginning of the page request. It is typically
  * used to set up global parameters that are needed later in the request.
- * When this hook is called, all modules are already loaded in memory.
+ * When this hook is called, the theme and all modules are already loaded in
+ * memory.
  *
  * This hook is not run on cached pages.
  *
@@ -2343,6 +2364,7 @@ function hook_xmlrpc_alter(&$methods) {
  *   - type: The type of message for this entry.
  *   - user: The user object for the user who was logged in when the event
  *     happened.
+ *   - uid: The user ID for the user who was logged in when the event happened.
  *   - request_uri: The request URI for the page the event happened in.
  *   - referer: The page that referred the user to the page where the event
  *     occurred.
@@ -2409,7 +2431,7 @@ function hook_watchdog(array $log_entry) {
     '@ip'            => $log_entry['ip'],
     '@request_uri'   => $log_entry['request_uri'],
     '@referer_uri'   => $log_entry['referer'],
-    '@uid'           => $log_entry['user']->uid,
+    '@uid'           => $log_entry['uid'],
     '@name'          => $log_entry['user']->name,
     '@link'          => strip_tags($log_entry['link']),
     '@message'       => strip_tags($log_entry['message']),
@@ -3226,33 +3248,30 @@ function hook_install() {
 /**
  * Perform a single update.
  *
- * For each patch which requires a database change add a new hook_update_N()
- * which will be called by update.php. The database updates are numbered
- * sequentially according to the version of Drupal you are compatible with.
- *
- * Schema updates should adhere to the Schema API:
- * @link http://drupal.org/node/150215 http://drupal.org/node/150215 @endlink
- *
- * Database updates consist of 3 parts:
- * - 1 digit for Drupal core compatibility
- * - 1 digit for your module's major release version (e.g. is this the 5.x-1.* (1) or 5.x-2.* (2) series of your module?)
- * - 2 digits for sequential counting starting with 00
- *
- * The 2nd digit should be 0 for initial porting of your module to a new Drupal
- * core API.
+ * For each change that requires one or more actions to be performed when
+ * updating a site, add a new hook_update_N(), which will be called by
+ * update.php. The documentation block preceding this function is stripped of
+ * newlines and used as the description for the update on the pending updates
+ * task list. Schema updates should adhere to the
+ * @link http://drupal.org/node/150215 Schema API. @endlink
+ *
+ * Implementations of hook_update_N() are named (module name)_update_(number).
+ * The numbers are composed of three parts:
+ * - 1 digit for Drupal core compatibility.
+ * - 1 digit for your module's major release version (e.g., is this the 7.x-1.*
+ *   (1) or 7.x-2.* (2) series of your module?). This digit should be 0 for
+ *   initial porting of your module to a new Drupal core API.
+ * - 2 digits for sequential counting, starting with 00.
  *
  * Examples:
- * - mymodule_update_5200()
- *   - This is the first update to get the database ready to run mymodule 5.x-2.*.
- * - mymodule_update_6000()
- *   - This is the required update for mymodule to run with Drupal core API 6.x.
- * - mymodule_update_6100()
- *   - This is the first update to get the database ready to run mymodule 6.x-1.*.
- * - mymodule_update_6200()
- *   - This is the first update to get the database ready to run mymodule 6.x-2.*.
- *     Users can directly update from 5.x-2.* to 6.x-2.* and they get all 60XX
- *     and 62XX updates, but not 61XX updates, because those reside in the
- *     6.x-1.x branch only.
+ * - mymodule_update_7000(): This is the required update for mymodule to run
+ *   with Drupal core API 7.x when upgrading from Drupal core API 6.x.
+ * - mymodule_update_7100(): This is the first update to get the database ready
+ *   to run mymodule 7.x-1.*.
+ * - mymodule_update_7200(): This is the first update to get the database ready
+ *   to run mymodule 7.x-2.*. Users can directly update from 6.x-2.* to 7.x-2.*
+ *   and they get all 70xx and 72xx updates, but not 71xx updates, because
+ *   those reside in the 7.x-1.x branch only.
  *
  * A good rule of thumb is to remove updates older than two major releases of
  * Drupal. See hook_update_last_removed() to notify Drupal about the removals.
@@ -3271,8 +3290,8 @@ function hook_install() {
  * information between successive calls, and the $sandbox['#finished'] value
  * to provide feedback regarding completion level.
  *
- * See the batch operations page for more information on how to use the batch API:
- * @link http://drupal.org/node/180528 http://drupal.org/node/180528 @endlink
+ * See the batch operations page for more information on how to use the
+ * @link http://drupal.org/node/180528 Batch API. @endlink
  *
  * @param $sandbox
  *   Stores information for multipass updates. See above for more information.
@@ -3283,9 +3302,14 @@ function hook_install() {
  *   reason, it will throw a PDOException.
  *
  * @return
- *   Optionally update hooks may return a translated string that will be displayed
- *   to the user. If no message is returned, no message will be presented to the
- *   user.
+ *   Optionally, update hooks may return a translated string that will be
+ *   displayed to the user after the update has completed. If no message is
+ *   returned, no message will be presented to the user.
+ *
+ * @see batch
+ * @see schemaapi
+ * @see hook_update_last_removed()
+ * @see update_get_update_list()
  */
 function hook_update_N(&$sandbox) {
   // For non-multipass updates, the signature can simply be;
diff --git a/modules/system/system.base.css b/modules/system/system.base.css
index bf6dd9f71..65383dd34 100644
--- a/modules/system/system.base.css
+++ b/modules/system/system.base.css
@@ -27,6 +27,7 @@
   color: #000;
   cursor: default;
   white-space: pre;
+  zoom: 1; /* IE7 */
 }
 /* Animated throbber */
 html.js input.form-autocomplete {
diff --git a/modules/system/system.info b/modules/system/system.info
index 7a3f8ebd4..da3fc753d 100644
--- a/modules/system/system.info
+++ b/modules/system/system.info
@@ -12,8 +12,8 @@ files[] = system.test
 required = TRUE
 configure = admin/config/system
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/system/system.install b/modules/system/system.install
index c0300000e..1161d6cdd 100644
--- a/modules/system/system.install
+++ b/modules/system/system.install
@@ -2952,6 +2952,16 @@ function system_update_7069() {
   variable_del('site_offline');
 }
 
+/**
+ * @} End of "defgroup updates-6.x-to-7.x".
+ * The next series of updates should start at 8000.
+ */
+
+/**
+ * @defgroup updates-7.x-extra Extra system updates for 7.x
+ * @{
+ */
+
 /**
  * Remove the obsolete 'drupal_badge_color' and 'drupal_badge_size' variables.
  */
@@ -2982,16 +2992,6 @@ function system_update_7072() {
   variable_del('site_offline_message');
 }
 
-/**
- * @} End of "defgroup updates-6.x-to-7.x"
- * The next series of updates should start at 8000.
- */
-
-/**
- * @defgroup updates-7.x-extra Extra system updates for 7.x
- * @{
- */
-
 /**
  * Add binary to {file_managed}, in case system_update_7034() was run without
  * it.
@@ -3016,6 +3016,15 @@ function system_update_7073() {
 }
 
 /**
- * @} End of "defgroup updates-7.x-extra"
+ * This update has been removed and will not run.
+ */
+function system_update_7074() {
+  // This update function previously converted menu_links query strings to
+  // arrays. It has been removed for now due to incompatibility with
+  // PostgreSQL.
+}
+
+/**
+ * @} End of "defgroup updates-7.x-extra".
  * The next series of updates should start at 8000.
  */
diff --git a/modules/system/system.module b/modules/system/system.module
index 072850e01..9897fb25e 100644
--- a/modules/system/system.module
+++ b/modules/system/system.module
@@ -2023,6 +2023,10 @@ function system_block_info() {
     'info' => t('Main page content'),
      // Cached elsewhere.
     'cache' => DRUPAL_NO_CACHE,
+    // Auto-enable in 'content' region by default, which always exists.
+    // @see system_themes_page(), drupal_render_page()
+    'status' => 1,
+    'region' => 'content',
   );
   $blocks['powered-by'] = array(
     'info' => t('Powered by Drupal'),
@@ -2033,6 +2037,9 @@ function system_block_info() {
     'info' => t('System help'),
     'weight' => '5',
     'cache' => DRUPAL_NO_CACHE,
+    // Auto-enable in 'help' region by default, if the theme defines one.
+    'status' => 1,
+    'region' => 'help',
   );
   // System-defined menu blocks.
   foreach (menu_list_system_menus() as $menu_name => $title) {
@@ -2553,7 +2560,7 @@ function _system_rebuild_theme_data() {
   // Now that we've established all our master themes, go back and fill in data
   // for subthemes.
   foreach ($sub_themes as $key) {
-    $themes[$key]->base_themes = system_find_base_themes($themes, $key);
+    $themes[$key]->base_themes = drupal_find_base_themes($themes, $key);
     // Don't proceed if there was a problem with the root base theme.
     if (!current($themes[$key]->base_themes)) {
       continue;
@@ -2648,42 +2655,10 @@ function _system_default_theme_features() {
 /**
  * Find all the base themes for the specified theme.
  *
- * Themes can inherit templates and function implementations from earlier themes.
- *
- * @param $themes
- *   An array of available themes.
- * @param $key
- *   The name of the theme whose base we are looking for.
- * @param $used_keys
- *   A recursion parameter preventing endless loops.
- * @return
- *   Returns an array of all of the theme's ancestors; the first element's value
- *   will be NULL if an error occurred.
+ * This function has been deprecated in favor of drupal_find_base_themes().
  */
 function system_find_base_themes($themes, $key, $used_keys = array()) {
-  $base_key = $themes[$key]->info['base theme'];
-  // Does the base theme exist?
-  if (!isset($themes[$base_key])) {
-    return array($base_key => NULL);
-  }
-
-  $current_base_theme = array($base_key => $themes[$base_key]->info['name']);
-
-  // Is the base theme itself a child of another theme?
-  if (isset($themes[$base_key]->info['base theme'])) {
-    // Do we already know the base themes of this theme?
-    if (isset($themes[$base_key]->base_themes)) {
-      return $themes[$base_key]->base_themes + $current_base_theme;
-    }
-    // Prevent loops.
-    if (!empty($used_keys[$base_key])) {
-      return array($base_key => NULL);
-    }
-    $used_keys[$base_key] = TRUE;
-    return system_find_base_themes($themes, $base_key, $used_keys) + $current_base_theme;
-  }
-  // If we get here, then this is our parent theme.
-  return $current_base_theme;
+  return drupal_find_base_themes($themes, $key, $used_keys);
 }
 
 /**
diff --git a/modules/system/theme.api.php b/modules/system/theme.api.php
index 7fee81cb6..cd7ecfde8 100644
--- a/modules/system/theme.api.php
+++ b/modules/system/theme.api.php
@@ -93,11 +93,13 @@ function hook_form_system_theme_settings_alter(&$form, &$form_state) {
 }
 
 /**
- * Preprocess theme variables.
+ * Preprocess theme variables for templates.
  *
  * This hook allows modules to preprocess theme variables for theme templates.
- * It is called for all invocations of theme(), to allow modules to add to
- * or override variables for all theme hooks.
+ * It is called for all theme hooks implemented as templates, but not for theme
+ * hooks implemented as functions. hook_preprocess_HOOK() can be used to
+ * preprocess variables for a specific theme hook, whether implemented as a
+ * template or function.
  *
  * For more detailed information, see theme().
  *
@@ -159,11 +161,13 @@ function hook_preprocess_HOOK(&$variables) {
 }
 
 /**
- * Process theme variables.
+ * Process theme variables for templates.
  *
- * This hook allows modules to process theme variables for theme templates.
- * It is called for all invocations of theme(), to allow modules to add to
- * or override variables for all theme hooks.
+ * This hook allows modules to process theme variables for theme templates. It
+ * is called for all theme hooks implemented as templates, but not for theme
+ * hooks implemented as functions. hook_process_HOOK() can be used to process
+ * variables for a specific theme hook, whether implemented as a template or
+ * function.
  *
  * For more detailed information, see theme().
  *
@@ -199,7 +203,11 @@ function hook_process(&$variables, $hook) {
  *   The variables array (modify in place).
  */
 function hook_process_HOOK(&$variables) {
-  $variables['classes'] .= ' my_added_class';
+  // @todo There are no use-cases in Drupal core for this hook. Find one from a
+  //   contributed module, or come up with a good example. Coming up with a good
+  //   example might be tough, since the intent is for nearly everything to be
+  //   achievable via preprocess functions, and for process functions to only be
+  //   used when requiring the later execution time.
 }
 
 /**
diff --git a/modules/taxonomy/taxonomy.admin.inc b/modules/taxonomy/taxonomy.admin.inc
index a236cfed1..828fde0ab 100644
--- a/modules/taxonomy/taxonomy.admin.inc
+++ b/modules/taxonomy/taxonomy.admin.inc
@@ -696,7 +696,8 @@ function taxonomy_form_term($form, &$form_state, $edit = array(), $vocabulary =
     '#value' => isset($term->vocabulary_machine_name) ? $term->vocabulary_machine_name : $vocabulary->name,
   );
 
-  field_attach_form('taxonomy_term', $term, $form, $form_state);
+  $langcode = entity_language('taxonomy_term', $term);
+  field_attach_form('taxonomy_term', $term, $form, $form_state, $langcode);
 
   $form['relations'] = array(
     '#type' => 'fieldset',
diff --git a/modules/taxonomy/taxonomy.info b/modules/taxonomy/taxonomy.info
index 4d3401adc..17b467703 100644
--- a/modules/taxonomy/taxonomy.info
+++ b/modules/taxonomy/taxonomy.info
@@ -8,8 +8,8 @@ files[] = taxonomy.module
 files[] = taxonomy.test
 configure = admin/structure/taxonomy
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/taxonomy/taxonomy.install b/modules/taxonomy/taxonomy.install
index f442c95ef..711a0f983 100644
--- a/modules/taxonomy/taxonomy.install
+++ b/modules/taxonomy/taxonomy.install
@@ -592,36 +592,105 @@ function taxonomy_update_7005(&$sandbox) {
     if (!empty($vocabularies)) {
       $sandbox['vocabularies'] = $vocabularies;
     }
+
+    db_create_table('taxonomy_update_7005', array(
+      'description' => 'Stores temporary data for taxonomy_update_7005.',
+      'fields' => array(
+        'n' => array(
+          'description' => 'Preserve order.',
+          'type' => 'serial',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+        ),
+        'vocab_id' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'tid' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+        ),
+        'nid' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+        ),
+        'vid' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => FALSE,
+          'default' => NULL,
+        ),
+        'type' => array(
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'created' => array(
+          'type' => 'int',
+          'not null' => FALSE,
+        ),
+        'sticky' => array(
+          'type' => 'int',
+          'not null' => FALSE,
+        ),
+        'is_current' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => FALSE,
+        ),
+      ),
+      'primary key' => array('n'),
+    ));
+
+    // Query selects all revisions at once and processes them in revision and
+    // term weight order.
+    $query = db_select('taxonomy_term_data', 'td');
+    // We are migrating term-node relationships. If there are none for a
+    // term, we do not need the term_data row.
+    $query->join('taxonomy_term_node', 'tn', 'td.tid = tn.tid');
+    // If a term-node relationship exists for a nid that does not exist, we
+    // cannot migrate it as we have no node to relate it to; thus we do not
+    // need that row from term_node.
+    $query->join('node', 'n', 'tn.nid = n.nid');
+    // If the current term-node relationship is for the current revision of
+    // the node, this left join will match and is_current will be non-NULL
+    // (we also get the current sticky and created in this case). This
+    // tells us whether to insert into the current data tables in addition
+    // to the revision data tables.
+    $query->leftJoin('node', 'n2', 'tn.vid = n2.vid');
+    $query->addField('td', 'vid', 'vocab_id');
+    $query->addField('td', 'tid');
+    $query->addField('tn', 'nid');
+    $query->addField('tn', 'vid');
+    $query->addField('n', 'type');
+    $query->addField('n2', 'created');
+    $query->addField('n2', 'sticky');
+    $query->addField('n2', 'nid', 'is_current');
+    // This query must return a consistent ordering across multiple calls.
+    // We need them ordered by node vid (since we use that to decide when
+    // to reset the delta counters) and by term weight so they appear
+    // within each node in weight order. However, tn.vid,td.weight is not
+    // guaranteed to be unique, so we add tn.tid as an additional sort key
+    // because tn.tid,tn.vid is the primary key of the D6 term_node table
+    // and so is guaranteed unique. Unfortunately it also happens to be in
+    // the wrong order which is less efficient, but c'est la vie.
+    $query->orderBy('tn.vid');
+    $query->orderBy('td.weight');
+    $query->orderBy('tn.tid');
+    db_insert('taxonomy_update_7005')
+      ->from($query)
+      ->execute();
   }
   else {
     // We do each pass in batches of 1000.
     $batch = 1000;
 
-    // Query selects all revisions at once and processes them in revision and
-    // term weight order. Join types:
-    //
-    // - INNER JOIN term_node ON tn.tid: We are migrating term-node
-    //   relationships. If there are none for a term, we do not need the
-    //   term_data row.
-    // - INNER JOIN {node} n ON n.nid: If a term-node relationship exists for a
-    //   nid that does not exist, we cannot migrate it as we have no node to
-    //   relate it to; thus we do not need that row from term_node.
-    // - LEFT JOIN {node} n2 ON n2.vid: If the current term-node relationship
-    //   is for the current revision of the node, this left join will match and
-    //   is_current will be non-NULL (we also get the current sticky and
-    //   created in this case). This tells us whether to insert into the
-    //   current data tables in addition to the revision data tables.
-    //
-    // This query must return a consistent ordering across multiple calls.  We
-    // need them ordered by node vid (since we use that to decide when to reset
-    // the delta counters) and by term weight so they appear within each node
-    // in weight order. However, tn.vid,td.weight is not guaranteed to be
-    // unique, so we add tn.tid as an additional sort key because tn.tid,tn.vid
-    // is the primary key of the D6 term_node table and so is guaranteed
-    // unique. Unfortunately it also happens to be in the wrong order which is
-    // less efficient, but c'est la vie.
-    $query = 'SELECT td.vid AS vocab_id, td.tid, tn.nid, tn.vid, n.type, n2.created, n2.sticky, n2.nid AS is_current FROM {taxonomy_term_data} td INNER JOIN {taxonomy_term_node} tn ON td.tid = tn.tid INNER JOIN {node} n ON tn.nid = n.nid LEFT JOIN {node} n2 ON tn.vid = n2.vid ORDER BY tn.vid, td.weight ASC, tn.tid';
-    $result = db_query_range($query, $sandbox['last'], $batch);
+    $result = db_query_range('SELECT vocab_id, tid, nid, vid, type, created, sticky, is_current FROM {taxonomy_update_7005} ORDER BY n', $sandbox['last'], $batch);
     if (isset($sandbox['cursor'])) {
       $values = $sandbox['cursor']['values'];
       $deltas = $sandbox['cursor']['deltas'];
@@ -714,6 +783,7 @@ function taxonomy_update_7005(&$sandbox) {
     db_drop_table('taxonomy_term_node');
 
     // If there are no vocabs, we're done.
+    db_drop_table('taxonomy_update_7005');
     $sandbox['#finished'] = TRUE;
 
     // Determine necessity of taxonomyextras field.
diff --git a/modules/taxonomy/taxonomy.module b/modules/taxonomy/taxonomy.module
index d7e9b2f1c..d501282fe 100644
--- a/modules/taxonomy/taxonomy.module
+++ b/modules/taxonomy/taxonomy.module
@@ -1136,7 +1136,7 @@ class TaxonomyTermController extends DrupalDefaultEntityController {
     if (isset($conditions['name'])) {
       $query_conditions = &$query->conditions();
       foreach ($query_conditions as $key => $condition) {
-        if ($condition['field'] == 'base.name') {
+        if (is_array($condition) && $condition['field'] == 'base.name') {
           $query_conditions[$key]['operator'] = 'LIKE';
           $query_conditions[$key]['value'] = db_like($query_conditions[$key]['value']);
         }
@@ -1270,7 +1270,8 @@ function taxonomy_vocabulary_machine_name_load($name) {
  *   A term's ID
  *
  * @return
- *   A term object. Results are statically cached.
+ *   A taxonomy term object, or FALSE if the term was not found. Results are
+ *   statically cached.
  */
 function taxonomy_term_load($tid) {
   if (!is_numeric($tid)) {
@@ -1904,5 +1905,37 @@ function taxonomy_taxonomy_term_delete($term) {
 }
 
 /**
- * @} End of "defgroup taxonomy_index"
+ * @} End of "defgroup taxonomy_index".
  */
+
+/**
+ * Implements hook_entity_query_alter().
+ *
+ * Converts EntityFieldQuery instances on taxonomy terms that have an entity
+ * condition on term bundles (vocabulary machine names). Since the vocabulary
+ * machine name is not present in the {taxonomy_term_data} table itself, we have
+ * to convert the bundle condition into a proprety condition of vocabulary IDs
+ * to match against {taxonomy_term_data}.vid.
+ */
+function taxonomy_entity_query_alter($query) {
+  $conditions = &$query->entityConditions;
+
+  // Alter only taxonomy term queries with bundle conditions.
+  if (isset($conditions['entity_type']) && $conditions['entity_type']['value'] == 'taxonomy_term' && isset($conditions['bundle'])) {
+    // Convert vocabulary machine names to vocabulary IDs.
+    $vocabulary_data = taxonomy_vocabulary_get_names();
+    $vids = array();
+    if (is_array($conditions['bundle']['value'])) {
+      foreach ($conditions['bundle']['value'] as $vocabulary_machine_name) {
+        $vids[] = $vocabulary_data[$vocabulary_machine_name]->vid;
+      }
+    }
+    else {
+      $vocabulary_machine_name = $conditions['bundle']['value'];
+      $vids = $vocabulary_data[$vocabulary_machine_name]->vid;
+    }
+
+    $query->propertyCondition('vid', $vids, $conditions['bundle']['operator']);
+    unset($conditions['bundle']);
+  }
+}
diff --git a/modules/taxonomy/taxonomy.test b/modules/taxonomy/taxonomy.test
index 42b4d4767..32ae84d66 100644
--- a/modules/taxonomy/taxonomy.test
+++ b/modules/taxonomy/taxonomy.test
@@ -6,8 +6,8 @@
  */
 
 /**
-* Class with common helper methods.
-*/
+ * Provides common helper methods for Taxonomy module tests.
+ */
 class TaxonomyWebTestCase extends DrupalWebTestCase {
 
   /**
@@ -39,11 +39,12 @@ class TaxonomyWebTestCase extends DrupalWebTestCase {
     taxonomy_term_save($term);
     return $term;
   }
+
 }
 
 /**
-* Tests for the taxonomy vocabulary interface.
-*/
+ * Tests the taxonomy vocabulary interface.
+ */
 class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase {
 
   public static function getInfo() {
@@ -76,17 +77,17 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase {
     $edit['description'] = $this->randomName();
     $edit['machine_name'] = $machine_name;
     $this->drupalPost(NULL, $edit, t('Save'));
-    $this->assertRaw(t('Created new vocabulary %name.', array('%name' => $edit['name'])), t('Vocabulary created successfully'));
+    $this->assertRaw(t('Created new vocabulary %name.', array('%name' => $edit['name'])), 'Vocabulary created successfully.');
 
     // Edit the vocabulary.
     $this->drupalGet('admin/structure/taxonomy');
-    $this->assertText($edit['name'], t('Vocabulary found in the vocabulary overview listing.'));
+    $this->assertText($edit['name'], 'Vocabulary found in the vocabulary overview listing.');
     $this->clickLink(t('edit vocabulary'));
     $edit = array();
     $edit['name'] = $this->randomName();
     $this->drupalPost(NULL, $edit, t('Save'));
     $this->drupalGet('admin/structure/taxonomy');
-    $this->assertText($edit['name'], t('Vocabulary found in the vocabulary overview listing.'));
+    $this->assertText($edit['name'], 'Vocabulary found in the vocabulary overview listing.');
 
     // Try to submit a vocabulary with a duplicate machine name.
     $edit['machine_name'] = $machine_name;
@@ -123,7 +124,7 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase {
 
     // Check that the weights are saved in the database correctly.
     foreach ($vocabularies as $key => $vocabulary) {
-      $this->assertEqual($new_vocabularies[$key]->weight, $vocabularies[$key]->weight, t('The vocabulary weight was changed.'));
+      $this->assertEqual($new_vocabularies[$key]->weight, $vocabularies[$key]->weight, 'The vocabulary weight was changed.');
     }
   }
 
@@ -137,10 +138,10 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase {
       taxonomy_vocabulary_delete($key);
     }
     // Confirm that no vocabularies are found in the database.
-    $this->assertFalse(taxonomy_get_vocabularies(), t('No vocabularies found in the database'));
+    $this->assertFalse(taxonomy_get_vocabularies(), 'No vocabularies found in the database.');
     $this->drupalGet('admin/structure/taxonomy');
     // Check the default message for no vocabularies.
-    $this->assertText(t('No vocabularies available.'), t('No vocabularies were found.'));
+    $this->assertText(t('No vocabularies available.'), 'No vocabularies were found.');
   }
 
   /**
@@ -153,29 +154,29 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase {
       'machine_name' => drupal_strtolower($this->randomName()),
     );
     $this->drupalPost('admin/structure/taxonomy/add', $edit, t('Save'));
-    $this->assertText(t('Created new vocabulary'), t('New vocabulary was created.'));
+    $this->assertText(t('Created new vocabulary'), 'New vocabulary was created.');
 
     // Check the created vocabulary.
     $vocabularies = taxonomy_get_vocabularies();
-    $vid = $vocabularies[count($vocabularies)-1]->vid;
+    $vid = $vocabularies[count($vocabularies) - 1]->vid;
     entity_get_controller('taxonomy_vocabulary')->resetCache();
     $vocabulary = taxonomy_vocabulary_load($vid);
-    $this->assertTrue($vocabulary, t('Vocabulary found in database'));
+    $this->assertTrue($vocabulary, 'Vocabulary found in database.');
 
     // Delete the vocabulary.
     $edit = array();
     $this->drupalPost('admin/structure/taxonomy/' . $vocabulary->machine_name . '/edit', $edit, t('Delete'));
-    $this->assertRaw(t('Are you sure you want to delete the vocabulary %name?', array('%name' => $vocabulary->name)), t('[confirm deletion] Asks for confirmation.'));
-    $this->assertText(t('Deleting a vocabulary will delete all the terms in it. This action cannot be undone.'), t('[confirm deletion] Inform that all terms will be deleted.'));
+    $this->assertRaw(t('Are you sure you want to delete the vocabulary %name?', array('%name' => $vocabulary->name)), '[confirm deletion] Asks for confirmation.');
+    $this->assertText(t('Deleting a vocabulary will delete all the terms in it. This action cannot be undone.'), '[confirm deletion] Inform that all terms will be deleted.');
 
     // Confirm deletion.
     $this->drupalPost(NULL, NULL, t('Delete'));
-    $this->assertRaw(t('Deleted vocabulary %name.', array('%name' => $vocabulary->name)), t('Vocabulary deleted'));
+    $this->assertRaw(t('Deleted vocabulary %name.', array('%name' => $vocabulary->name)), 'Vocabulary deleted.');
     entity_get_controller('taxonomy_vocabulary')->resetCache();
-    $this->assertFalse(taxonomy_vocabulary_load($vid), t('Vocabulary is not found in the database'));
+    $this->assertFalse(taxonomy_vocabulary_load($vid), 'Vocabulary is not found in the database.');
   }
-}
 
+}
 
 /**
  * Tests for taxonomy vocabulary functions.
@@ -207,14 +208,14 @@ class TaxonomyVocabularyTestCase extends TaxonomyWebTestCase {
     $vid = count($vocabularies) + 1;
     $vocabulary = taxonomy_vocabulary_load($vid);
     // This should not return an object because no such vocabulary exists.
-    $this->assertTrue(empty($vocabulary), t('No object loaded.'));
+    $this->assertTrue(empty($vocabulary), 'No object loaded.');
 
     // Create a new vocabulary.
     $this->createVocabulary();
     // Load the vocabulary with the same $vid from earlier.
     // This should return a vocabulary object since it now matches a real vid.
     $vocabulary = taxonomy_vocabulary_load($vid);
-    $this->assertTrue(!empty($vocabulary) && is_object($vocabulary), t('Vocabulary is an object'));
+    $this->assertTrue(!empty($vocabulary) && is_object($vocabulary), 'Vocabulary is an object.');
     $this->assertEqual($vocabulary->vid, $vid, 'Valid vocabulary vid is the same as our previously invalid one.');
   }
 
@@ -257,8 +258,8 @@ class TaxonomyVocabularyTestCase extends TaxonomyWebTestCase {
    */
   function testTaxonomyVocabularyLoadStaticReset() {
     $original_vocabulary = taxonomy_vocabulary_load($this->vocabulary->vid);
-    $this->assertTrue(is_object($original_vocabulary), t('Vocabulary loaded successfully'));
-    $this->assertEqual($this->vocabulary->name, $original_vocabulary->name, t('Vocabulary loaded successfully'));
+    $this->assertTrue(is_object($original_vocabulary), 'Vocabulary loaded successfully.');
+    $this->assertEqual($this->vocabulary->name, $original_vocabulary->name, 'Vocabulary loaded successfully.');
 
     // Change the name and description.
     $vocabulary = $original_vocabulary;
@@ -274,7 +275,7 @@ class TaxonomyVocabularyTestCase extends TaxonomyWebTestCase {
     // Delete the vocabulary.
     taxonomy_vocabulary_delete($this->vocabulary->vid);
     $vocabularies = taxonomy_get_vocabularies();
-    $this->assertTrue(!isset($vocabularies[$this->vocabulary->vid]), t('The vocabulary was deleted'));
+    $this->assertTrue(!isset($vocabularies[$this->vocabulary->vid]), 'The vocabulary was deleted.');
   }
 
   /**
@@ -301,21 +302,21 @@ class TaxonomyVocabularyTestCase extends TaxonomyWebTestCase {
     // Fetch the names for all vocabularies, confirm that they are keyed by
     // machine name.
     $names = taxonomy_vocabulary_get_names();
-    $this->assertEqual($names[$vocabulary1->machine_name]->name, $vocabulary1->name, t('Vocabulary 1 name found.'));
+    $this->assertEqual($names[$vocabulary1->machine_name]->name, $vocabulary1->name, 'Vocabulary 1 name found.');
 
     // Fetch all of the vocabularies using taxonomy_get_vocabularies().
     // Confirm that the vocabularies are ordered by weight.
     $vocabularies = taxonomy_get_vocabularies();
-    $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary1->vid, t('Vocabulary was found in the vocabularies array.'));
-    $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary2->vid, t('Vocabulary was found in the vocabularies array.'));
-    $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary3->vid, t('Vocabulary was found in the vocabularies array.'));
+    $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary1->vid, 'Vocabulary was found in the vocabularies array.');
+    $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary2->vid, 'Vocabulary was found in the vocabularies array.');
+    $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary3->vid, 'Vocabulary was found in the vocabularies array.');
 
     // Fetch the vocabularies with taxonomy_vocabulary_load_multiple(), specifying IDs.
     // Ensure they are returned in the same order as the original array.
     $vocabularies = taxonomy_vocabulary_load_multiple(array($vocabulary3->vid, $vocabulary2->vid, $vocabulary1->vid));
-    $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary3->vid, t('Vocabulary loaded successfully by ID.'));
-    $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary2->vid, t('Vocabulary loaded successfully by ID.'));
-    $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary1->vid, t('Vocabulary loaded successfully by ID.'));
+    $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary3->vid, 'Vocabulary loaded successfully by ID.');
+    $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary2->vid, 'Vocabulary loaded successfully by ID.');
+    $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary1->vid, 'Vocabulary loaded successfully by ID.');
 
     // Fetch vocabulary 1 by name.
     $vocabulary = current(taxonomy_vocabulary_load_multiple(array(), array('name' => $vocabulary1->name)));
@@ -348,7 +349,7 @@ class TaxonomyVocabularyTestCase extends TaxonomyWebTestCase {
     taxonomy_vocabulary_save($this->vocabulary);
 
     // Check that the field instance is still attached to the vocabulary.
-    $this->assertTrue(field_info_instance('taxonomy_term', 'field_test', $new_name), t('The bundle name was updated correctly.'));
+    $this->assertTrue(field_info_instance('taxonomy_term', 'field_test', $new_name), 'The bundle name was updated correctly.');
   }
 
   /**
@@ -383,6 +384,7 @@ class TaxonomyVocabularyTestCase extends TaxonomyWebTestCase {
     field_create_field($this->field);
     field_create_instance($this->instance);
   }
+
 }
 
 /**
@@ -404,7 +406,7 @@ class TaxonomyTermFunctionTestCase extends TaxonomyWebTestCase {
     // Delete a valid term.
     taxonomy_term_delete($valid_term->tid);
     $terms = taxonomy_term_load_multiple(array(), array('vid' => $vocabulary->vid));
-    $this->assertTrue(empty($terms), 'Vocabulary is empty after deletion');
+    $this->assertTrue(empty($terms), 'Vocabulary is empty after deletion.');
 
     // Delete an invalid term. Should not throw any notices.
     taxonomy_term_delete(42);
@@ -442,7 +444,6 @@ class TaxonomyTermFunctionTestCase extends TaxonomyWebTestCase {
      * ---- term[2] | depth: 2
      * ------ term[3] | depth: 3
      */
-
     // Count $term[1] parents with $max_depth = 1.
     $tree = taxonomy_get_tree($vocabulary->vid, $term[1]->tid, 1);
     $this->assertEqual(1, count($tree), 'We have one parent with depth 1.');
@@ -452,7 +453,7 @@ class TaxonomyTermFunctionTestCase extends TaxonomyWebTestCase {
     $this->assertEqual(8, count($tree), 'We have all vocabulary tree elements.');
 
     // Count elements in every tree depth.
-    foreach($tree as $element) {
+    foreach ($tree as $element) {
       if (!isset($depth_count[$element->depth])) {
         $depth_count[$element->depth] = 0;
       }
@@ -462,7 +463,8 @@ class TaxonomyTermFunctionTestCase extends TaxonomyWebTestCase {
     $this->assertEqual(2, $depth_count[1], 'Two elements in taxonomy tree depth 1.');
     $this->assertEqual(2, $depth_count[2], 'Two elements in taxonomy tree depth 2.');
     $this->assertEqual(1, $depth_count[3], 'One element in taxonomy tree depth 3.');
-   }
+  }
+
 }
 
 /**
@@ -498,8 +500,9 @@ class TaxonomyLegacyTestCase extends TaxonomyWebTestCase {
     $this->drupalPost('node/add/article', $edit, t('Save'));
     // Checks that the node has been saved.
     $node = $this->drupalGetNodeByTitle($edit['title']);
-    $this->assertEqual($node->created, strtotime($edit['date']), t('Legacy node was saved with the right date.'));
+    $this->assertEqual($node->created, strtotime($edit['date']), 'Legacy node was saved with the right date.');
   }
+
 }
 
 /**
@@ -572,21 +575,21 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
     // Check the hierarchy.
     $children = taxonomy_get_children($term1->tid);
     $parents = taxonomy_get_parents($term2->tid);
-    $this->assertTrue(isset($children[$term2->tid]), t('Child found correctly.'));
-    $this->assertTrue(isset($parents[$term1->tid]), t('Parent found correctly.'));
+    $this->assertTrue(isset($children[$term2->tid]), 'Child found correctly.');
+    $this->assertTrue(isset($parents[$term1->tid]), 'Parent found correctly.');
 
     // Load and save a term, confirming that parents are still set.
     $term = taxonomy_term_load($term2->tid);
     taxonomy_term_save($term);
     $parents = taxonomy_get_parents($term2->tid);
-    $this->assertTrue(isset($parents[$term1->tid]), t('Parent found correctly.'));
+    $this->assertTrue(isset($parents[$term1->tid]), 'Parent found correctly.');
 
     // Create a third term and save this as a parent of term2.
     $term3 = $this->createTerm($this->vocabulary);
     $term2->parent = array($term1->tid, $term3->tid);
     taxonomy_term_save($term2);
     $parents = taxonomy_get_parents($term2->tid);
-    $this->assertTrue(isset($parents[$term1->tid]) && isset($parents[$term3->tid]), t('Both parents found successfully.'));
+    $this->assertTrue(isset($parents[$term1->tid]) && isset($parents[$term3->tid]), 'Both parents found successfully.');
   }
 
   /**
@@ -604,26 +607,26 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
     $langcode = LANGUAGE_NONE;
     $edit["title"] = $this->randomName();
     $edit["body[$langcode][0][value]"] = $this->randomName();
-    $edit[$this->instance['field_name'] . '[' . $langcode .'][]'] = $term1->tid;
+    $edit[$this->instance['field_name'] . '[' . $langcode . '][]'] = $term1->tid;
     $this->drupalPost('node/add/article', $edit, t('Save'));
 
     // Check that the term is displayed when the node is viewed.
     $node = $this->drupalGetNodeByTitle($edit["title"]);
     $this->drupalGet('node/' . $node->nid);
-    $this->assertText($term1->name, t('Term is displayed when viewing the node.'));
+    $this->assertText($term1->name, 'Term is displayed when viewing the node.');
 
     // Edit the node with a different term.
     $edit[$this->instance['field_name'] . '[' . $langcode . '][]'] = $term2->tid;
     $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
 
     $this->drupalGet('node/' . $node->nid);
-    $this->assertText($term2->name, t('Term is displayed when viewing the node.'));
+    $this->assertText($term2->name, 'Term is displayed when viewing the node.');
 
     // Preview the node.
     $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Preview'));
-    $this->assertNoUniqueText($term2->name, t('Term is displayed when previewing the node.'));
+    $this->assertNoUniqueText($term2->name, 'Term is displayed when previewing the node.');
     $this->drupalPost(NULL, NULL, t('Preview'));
-    $this->assertNoUniqueText($term2->name, t('Term is displayed when previewing the node again.'));
+    $this->assertNoUniqueText($term2->name, 'Term is displayed when previewing the node again.');
   }
 
   /**
@@ -652,19 +655,19 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
     // Preview and verify the terms appear but are not created.
     $this->drupalPost('node/add/page', $edit, t('Preview'));
     foreach ($terms as $term) {
-      $this->assertText($term, t('The term appears on the node preview'));
+      $this->assertText($term, 'The term appears on the node preview.');
     }
     $tree = taxonomy_get_tree($this->vocabulary->vid);
-    $this->assertTrue(empty($tree), t('The terms are not created on preview.'));
+    $this->assertTrue(empty($tree), 'The terms are not created on preview.');
 
     // taxonomy.module does not maintain its static caches.
     drupal_static_reset();
 
     // Save, creating the terms.
     $this->drupalPost('node/add/page', $edit, t('Save'));
-    $this->assertRaw(t('@type %title has been created.', array('@type' => t('Basic page'), '%title' => $edit["title"])), t('The node was created successfully'));
+    $this->assertRaw(t('@type %title has been created.', array('@type' => t('Basic page'), '%title' => $edit["title"])), 'The node was created successfully.');
     foreach ($terms as $term) {
-      $this->assertText($term, t('The term was saved and appears on the node page'));
+      $this->assertText($term, 'The term was saved and appears on the node page.');
     }
 
     // Get the created terms.
@@ -684,29 +687,29 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
     $this->drupalGet('node/' . $node->nid);
 
     foreach ($term_names as $term_name) {
-      $this->assertText($term_name, t('The term %name appears on the node page after one term %deleted was deleted', array('%name' => $term_name, '%deleted' => $term_objects['term1']->name)));
+      $this->assertText($term_name, format_string('The term %name appears on the node page after one term %deleted was deleted', array('%name' => $term_name, '%deleted' => $term_objects['term1']->name)));
     }
-    $this->assertNoText($term_objects['term1']->name, t('The deleted term %name does not appear on the node page.', array('%name' => $term_objects['term1']->name)));
+    $this->assertNoText($term_objects['term1']->name, format_string('The deleted term %name does not appear on the node page.', array('%name' => $term_objects['term1']->name)));
 
     // Test autocomplete on term 2, which contains a comma.
     // The term will be quoted, and the " will be encoded in unicode (\u0022).
     $input = substr($term_objects['term2']->name, 0, 3);
     $this->drupalGet('taxonomy/autocomplete/taxonomy_' . $this->vocabulary->machine_name . '/' . $input);
-    $this->assertRaw('{"\u0022' . $term_objects['term2']->name . '\u0022":"' . $term_objects['term2']->name . '"}', t('Autocomplete returns term %term_name after typing the first 3 letters.', array('%term_name' => $term_objects['term2']->name)));
+    $this->assertRaw('{"\u0022' . $term_objects['term2']->name . '\u0022":"' . $term_objects['term2']->name . '"}', format_string('Autocomplete returns term %term_name after typing the first 3 letters.', array('%term_name' => $term_objects['term2']->name)));
 
     // Test autocomplete on term 3 - it is alphanumeric only, so no extra
     // quoting.
     $input = substr($term_objects['term3']->name, 0, 3);
     $this->drupalGet('taxonomy/autocomplete/taxonomy_' . $this->vocabulary->machine_name . '/' . $input);
-    $this->assertRaw('{"' . $term_objects['term3']->name . '":"' . $term_objects['term3']->name . '"}', t('Autocomplete returns term %term_name after typing the first 3 letters.', array('%term_name' => $term_objects['term3']->name)));
+    $this->assertRaw('{"' . $term_objects['term3']->name . '":"' . $term_objects['term3']->name . '"}', format_string('Autocomplete returns term %term_name after typing the first 3 letters.', array('%term_name' => $term_objects['term3']->name)));
 
     // Test taxonomy autocomplete with a nonexistent field.
     $field_name = $this->randomName();
     $tag = $this->randomName();
     $message = t("Taxonomy field @field_name not found.", array('@field_name' => $field_name));
-    $this->assertFalse(field_info_field($field_name), t('Field %field_name does not exist.', array('%field_name' => $field_name)));
+    $this->assertFalse(field_info_field($field_name), format_string('Field %field_name does not exist.', array('%field_name' => $field_name)));
     $this->drupalGet('taxonomy/autocomplete/' . $field_name . '/' . $tag);
-    $this->assertRaw($message, t('Autocomplete returns correct error message when the taxonomy field does not exist.'));
+    $this->assertRaw($message, 'Autocomplete returns correct error message when the taxonomy field does not exist.');
   }
 
   /**
@@ -735,8 +738,8 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
     $url = url($path, array('absolute' => TRUE));
     $result = drupal_http_request($url);
     $data = drupal_json_decode($result->data);
-    $this->assertEqual($data[$first_term->name], check_plain($first_term->name), 'Autocomplete returned the first matching term');
-    $this->assertEqual($data[$second_term->name], check_plain($second_term->name), 'Autocomplete returned the second matching term');
+    $this->assertEqual($data[$first_term->name], check_plain($first_term->name), 'Autocomplete returned the first matching term.');
+    $this->assertEqual($data[$second_term->name], check_plain($second_term->name), 'Autocomplete returned the second matching term.');
 
     // Try to autocomplete a term name that matches first term.
     // We should only get the first term in a json encoded string.
@@ -778,7 +781,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
 
     $terms = taxonomy_get_term_by_name($edit['name']);
     $term = reset($terms);
-    $this->assertNotNull($term, t('Term found in database'));
+    $this->assertNotNull($term, 'Term found in database.');
 
     // Submitting a term takes us to the add page; we need the List page.
     $this->drupalGet('admin/structure/taxonomy/' . $this->vocabulary->machine_name);
@@ -788,8 +791,8 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
     // the first edit link found on the listing page is to our term.
     $this->clickLink(t('edit'));
 
-    $this->assertRaw($edit['name'], t('The randomly generated term name is present.'));
-    $this->assertText($edit['description[value]'], t('The randomly generated term description is present.'));
+    $this->assertRaw($edit['name'], 'The randomly generated term name is present.');
+    $this->assertText($edit['description[value]'], 'The randomly generated term description is present.');
 
     $edit = array(
       'name' => $this->randomName(14),
@@ -801,13 +804,13 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
 
     // Check that the term is still present at admin UI after edit.
     $this->drupalGet('admin/structure/taxonomy/' . $this->vocabulary->machine_name);
-    $this->assertText($edit['name'], t('The randomly generated term name is present.'));
+    $this->assertText($edit['name'], 'The randomly generated term name is present.');
     $this->assertLink(t('edit'));
 
     // View the term and check that it is correct.
     $this->drupalGet('taxonomy/term/' . $term->tid);
-    $this->assertText($edit['name'], t('The randomly generated term name is present.'));
-    $this->assertText($edit['description[value]'], t('The randomly generated term description is present.'));
+    $this->assertText($edit['name'], 'The randomly generated term name is present.');
+    $this->assertText($edit['description[value]'], 'The randomly generated term description is present.');
 
     // Did this page request display a 'term-listing-heading'?
     $this->assertPattern('|class="taxonomy-term-description"|', 'Term page displayed the term description element.');
@@ -830,7 +833,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
 
     // Assert that the term no longer exists.
     $this->drupalGet('taxonomy/term/' . $term->tid);
-    $this->assertResponse(404, t('The taxonomy term page was not found'));
+    $this->assertResponse(404, 'The taxonomy term page was not found.');
   }
 
   /**
@@ -874,9 +877,9 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
     drupal_static_reset('taxonomy_get_treeparent');
     drupal_static_reset('taxonomy_get_treeterms');
     $terms = taxonomy_get_tree($this->vocabulary->vid);
-    $this->assertEqual($terms[0]->tid, $term2->tid, t('Term 2 was moved above term 1.'));
-    $this->assertEqual($terms[1]->parents, array($term2->tid), t('Term 3 was made a child of term 2.'));
-    $this->assertEqual($terms[2]->tid, $term1->tid, t('Term 1 was moved below term 2.'));
+    $this->assertEqual($terms[0]->tid, $term2->tid, 'Term 2 was moved above term 1.');
+    $this->assertEqual($terms[1]->parents, array($term2->tid), 'Term 3 was made a child of term 2.');
+    $this->assertEqual($terms[2]->tid, $term1->tid, 'Term 1 was moved below term 2.');
 
     $this->drupalPost('admin/structure/taxonomy/' . $this->vocabulary->machine_name, array(), t('Reset to alphabetical'));
     // Submit confirmation form.
@@ -886,10 +889,10 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
     drupal_static_reset('taxonomy_get_treeparent');
     drupal_static_reset('taxonomy_get_treeterms');
     $terms = taxonomy_get_tree($this->vocabulary->vid);
-    $this->assertEqual($terms[0]->tid, $term1->tid, t('Term 1 was moved to back above term 2.'));
-    $this->assertEqual($terms[1]->tid, $term2->tid, t('Term 2 was moved to back below term 1.'));
-    $this->assertEqual($terms[2]->tid, $term3->tid, t('Term 3 is still below term 2.'));
-    $this->assertEqual($terms[2]->parents, array($term2->tid), t('Term 3 is still a child of term 2.').var_export($terms[1]->tid,1));
+    $this->assertEqual($terms[0]->tid, $term1->tid, 'Term 1 was moved to back above term 2.');
+    $this->assertEqual($terms[1]->tid, $term2->tid, 'Term 2 was moved to back below term 1.');
+    $this->assertEqual($terms[2]->tid, $term3->tid, 'Term 3 is still below term 2.');
+    $this->assertEqual($terms[2]->parents, array($term2->tid), 'Term 3 is still a child of term 2.' . var_export($terms[1]->tid, 1));
   }
 
   /**
@@ -911,14 +914,14 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
     // Check that the term was successfully created.
     $terms = taxonomy_get_term_by_name($edit['name']);
     $term = reset($terms);
-    $this->assertNotNull($term, t('Term found in database'));
-    $this->assertEqual($edit['name'], $term->name, t('Term name was successfully saved.'));
-    $this->assertEqual($edit['description[value]'], $term->description, t('Term description was successfully saved.'));
+    $this->assertNotNull($term, 'Term found in database.');
+    $this->assertEqual($edit['name'], $term->name, 'Term name was successfully saved.');
+    $this->assertEqual($edit['description[value]'], $term->description, 'Term description was successfully saved.');
     // Check that the parent tid is still there. The other parent (<root>) is
     // not added by taxonomy_get_parents().
     $parents = taxonomy_get_parents($term->tid);
     $parent = reset($parents);
-    $this->assertEqual($edit['parent[]'][1], $parent->tid, t('Term parents were successfully saved.'));
+    $this->assertEqual($edit['parent[]'][1], $parent->tid, 'Term parents were successfully saved.');
   }
 
   /**
@@ -929,19 +932,19 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
 
     // Load the term with the exact name.
     $terms = taxonomy_get_term_by_name($term->name);
-    $this->assertTrue(isset($terms[$term->tid]), t('Term loaded using exact name.'));
+    $this->assertTrue(isset($terms[$term->tid]), 'Term loaded using exact name.');
 
     // Load the term with space concatenated.
     $terms  = taxonomy_get_term_by_name('  ' . $term->name . '   ');
-    $this->assertTrue(isset($terms[$term->tid]), t('Term loaded with extra whitespace.'));
+    $this->assertTrue(isset($terms[$term->tid]), 'Term loaded with extra whitespace.');
 
     // Load the term with name uppercased.
     $terms = taxonomy_get_term_by_name(strtoupper($term->name));
-    $this->assertTrue(isset($terms[$term->tid]), t('Term loaded with uppercased name.'));
+    $this->assertTrue(isset($terms[$term->tid]), 'Term loaded with uppercased name.');
 
     // Load the term with name lowercased.
     $terms = taxonomy_get_term_by_name(strtolower($term->name));
-    $this->assertTrue(isset($terms[$term->tid]), t('Term loaded with lowercased name.'));
+    $this->assertTrue(isset($terms[$term->tid]), 'Term loaded with lowercased name.');
 
     // Try to load an invalid term name.
     $terms = taxonomy_get_term_by_name('Banana');
@@ -960,12 +963,12 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
 
     // Load multiple terms with the same name.
     $terms = taxonomy_get_term_by_name($term->name);
-    $this->assertEqual(count($terms), 2, t('Two terms loaded with the same name.'));
+    $this->assertEqual(count($terms), 2, 'Two terms loaded with the same name.');
 
     // Load single term when restricted to one vocabulary.
     $terms = taxonomy_get_term_by_name($term->name, $this->vocabulary->machine_name);
-    $this->assertEqual(count($terms), 1, t('One term loaded when restricted by vocabulary.'));
-    $this->assertTrue(isset($terms[$term->tid]), t('Term loaded using exact name and vocabulary machine name.'));
+    $this->assertEqual(count($terms), 1, 'One term loaded when restricted by vocabulary.');
+    $this->assertTrue(isset($terms[$term->tid]), 'Term loaded using exact name and vocabulary machine name.');
 
     // Create a new term with another name.
     $term2 = $this->createTerm($this->vocabulary);
@@ -973,12 +976,13 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
     // Try to load a term by name that doesn't exist in this vocabulary but
     // exists in another vocabulary.
     $terms = taxonomy_get_term_by_name($term2->name, $new_vocabulary->machine_name);
-    $this->assertFalse($terms, t('Invalid term name restricted by vocabulary machine name not loaded.'));
+    $this->assertFalse($terms, 'Invalid term name restricted by vocabulary machine name not loaded.');
 
     // Try to load terms filtering by a non-existing vocabulary.
     $terms = taxonomy_get_term_by_name($term2->name, 'non_existing_vocabulary');
-    $this->assertEqual(count($terms), 0, t('No terms loaded when restricted by a non-existing vocabulary.'));
+    $this->assertEqual(count($terms), 0, 'No terms loaded when restricted by a non-existing vocabulary.');
   }
+
 }
 
 /**
@@ -1058,7 +1062,7 @@ class TaxonomyRSSTestCase extends TaxonomyWebTestCase {
     $edit = array();
     $langcode = LANGUAGE_NONE;
     $edit["title"] = $this->randomName();
-    $edit[$this->instance['field_name'] . '[' . $langcode .'][]'] = $term1->tid;
+    $edit[$this->instance['field_name'] . '[' . $langcode . '][]'] = $term1->tid;
     $this->drupalPost('node/add/article', $edit, t('Save'));
 
     // Check that the term is displayed when the RSS feed is viewed.
@@ -1072,6 +1076,7 @@ class TaxonomyRSSTestCase extends TaxonomyWebTestCase {
     );
     $this->assertRaw(format_xml_elements(array($test_element)), 'Term is displayed when viewing the rss feed.');
   }
+
 }
 
 /**
@@ -1181,7 +1186,7 @@ class TaxonomyTermIndexTestCase extends TaxonomyWebTestCase {
       ':nid' => $node->nid,
       ':tid' => $term_1->tid,
     ))->fetchField();
-    $this->assertEqual(1, $index_count, t('Term 1 is indexed once.'));
+    $this->assertEqual(1, $index_count, 'Term 1 is indexed once.');
 
     // Update the article to change one term.
     $edit["{$this->field_name_1}[$langcode][]"] = $term_2->tid;
@@ -1192,12 +1197,12 @@ class TaxonomyTermIndexTestCase extends TaxonomyWebTestCase {
       ':nid' => $node->nid,
       ':tid' => $term_1->tid,
     ))->fetchField();
-    $this->assertEqual(1, $index_count, t('Term 1 is indexed.'));
+    $this->assertEqual(1, $index_count, 'Term 1 is indexed.');
     $index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', array(
       ':nid' => $node->nid,
       ':tid' => $term_2->tid,
     ))->fetchField();
-    $this->assertEqual(1, $index_count, t('Term 2 is indexed.'));
+    $this->assertEqual(1, $index_count, 'Term 2 is indexed.');
 
     // Update the article to change another term.
     $edit["{$this->field_name_2}[$langcode][]"] = $term_2->tid;
@@ -1208,12 +1213,12 @@ class TaxonomyTermIndexTestCase extends TaxonomyWebTestCase {
       ':nid' => $node->nid,
       ':tid' => $term_1->tid,
     ))->fetchField();
-    $this->assertEqual(0, $index_count, t('Term 1 is not indexed.'));
+    $this->assertEqual(0, $index_count, 'Term 1 is not indexed.');
     $index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', array(
       ':nid' => $node->nid,
       ':tid' => $term_2->tid,
     ))->fetchField();
-    $this->assertEqual(1, $index_count, t('Term 2 is indexed once.'));
+    $this->assertEqual(1, $index_count, 'Term 2 is indexed once.');
 
     // Redo the above tests without interface.
     $update_node = array(
@@ -1233,12 +1238,12 @@ class TaxonomyTermIndexTestCase extends TaxonomyWebTestCase {
       ':nid' => $node->nid,
       ':tid' => $term_1->tid,
     ))->fetchField();
-    $this->assertEqual(0, $index_count, t('Term 1 is not indexed.'));
+    $this->assertEqual(0, $index_count, 'Term 1 is not indexed.');
     $index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', array(
       ':nid' => $node->nid,
       ':tid' => $term_2->tid,
     ))->fetchField();
-    $this->assertEqual(1, $index_count, t('Term 2 is indexed once.'));
+    $this->assertEqual(1, $index_count, 'Term 2 is indexed once.');
 
     // Update the article to change one term.
     $update_node[$this->field_name_1][$langcode] = array(array('tid' => $term_1->tid));
@@ -1250,12 +1255,12 @@ class TaxonomyTermIndexTestCase extends TaxonomyWebTestCase {
       ':nid' => $node->nid,
       ':tid' => $term_1->tid,
     ))->fetchField();
-    $this->assertEqual(1, $index_count, t('Term 1 is indexed.'));
+    $this->assertEqual(1, $index_count, 'Term 1 is indexed.');
     $index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', array(
       ':nid' => $node->nid,
       ':tid' => $term_2->tid,
     ))->fetchField();
-    $this->assertEqual(1, $index_count, t('Term 2 is indexed.'));
+    $this->assertEqual(1, $index_count, 'Term 2 is indexed.');
 
     // Update the article to change another term.
     $update_node[$this->field_name_2][$langcode] = array(array('tid' => $term_1->tid));
@@ -1267,12 +1272,12 @@ class TaxonomyTermIndexTestCase extends TaxonomyWebTestCase {
       ':nid' => $node->nid,
       ':tid' => $term_1->tid,
     ))->fetchField();
-    $this->assertEqual(1, $index_count, t('Term 1 is indexed once.'));
+    $this->assertEqual(1, $index_count, 'Term 1 is indexed once.');
     $index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', array(
       ':nid' => $node->nid,
       ':tid' => $term_2->tid,
     ))->fetchField();
-    $this->assertEqual(0, $index_count, t('Term 2 is not indexed.'));
+    $this->assertEqual(0, $index_count, 'Term 2 is not indexed.');
   }
 
   /**
@@ -1287,8 +1292,9 @@ class TaxonomyTermIndexTestCase extends TaxonomyWebTestCase {
 
     // Verify that the page breadcrumbs include a link to the parent term.
     $this->drupalGet('taxonomy/term/' . $term1->tid);
-    $this->assertRaw(l($term2->name, 'taxonomy/term/' . $term2->tid), t('Parent term link is displayed when viewing the node.'));
+    $this->assertRaw(l($term2->name, 'taxonomy/term/' . $term2->tid), 'Parent term link is displayed when viewing the node.');
   }
+
 }
 
 /**
@@ -1331,8 +1337,8 @@ class TaxonomyLoadMultipleTestCase extends TaxonomyWebTestCase {
 
     // Load the same terms again by tid.
     $terms2 = taxonomy_term_load_multiple(array_keys($terms));
-    $this->assertEqual($count, count($terms2), 'Five terms were loaded by tid');
-    $this->assertEqual($terms, $terms2, t('Both arrays contain the same terms'));
+    $this->assertEqual($count, count($terms2), 'Five terms were loaded by tid.');
+    $this->assertEqual($terms, $terms2, 'Both arrays contain the same terms.');
 
     // Load the terms by tid, with a condition on vid.
     $terms3 = taxonomy_term_load_multiple(array_keys($terms2), array('vid' => $vocabulary->vid));
@@ -1352,9 +1358,9 @@ class TaxonomyLoadMultipleTestCase extends TaxonomyWebTestCase {
     // Create a single term and load it by name.
     $term = $this->createTerm($vocabulary);
     $loaded_terms = taxonomy_term_load_multiple(array(), array('name' => $term->name));
-    $this->assertEqual(count($loaded_terms), 1, t('One term was loaded'));
+    $this->assertEqual(count($loaded_terms), 1, 'One term was loaded.');
     $loaded_term = reset($loaded_terms);
-    $this->assertEqual($term->tid, $loaded_term->tid, t('Term loaded by name successfully.'));
+    $this->assertEqual($term->tid, $loaded_term->tid, 'Term loaded by name successfully.');
   }
 }
 
@@ -1390,7 +1396,7 @@ class TaxonomyHooksTestCase extends TaxonomyWebTestCase {
     $this->drupalPost('admin/structure/taxonomy/' . $vocabulary->machine_name . '/add', $edit, t('Save'));
     $terms = taxonomy_get_term_by_name($edit['name']);
     $term = reset($terms);
-    $this->assertEqual($term->antonym, $edit['antonym'], t('Antonym was loaded into the term object'));
+    $this->assertEqual($term->antonym, $edit['antonym'], 'Antonym was loaded into the term object.');
 
     // Update the term with a different antonym.
     $edit = array(
@@ -1400,26 +1406,28 @@ class TaxonomyHooksTestCase extends TaxonomyWebTestCase {
     $this->drupalPost('taxonomy/term/' . $term->tid . '/edit', $edit, t('Save'));
     taxonomy_terms_static_reset();
     $term = taxonomy_term_load($term->tid);
-    $this->assertEqual($edit['antonym'], $term->antonym, t('Antonym was successfully edited'));
+    $this->assertEqual($edit['antonym'], $term->antonym, 'Antonym was successfully edited.');
 
     // Delete the term.
     taxonomy_term_delete($term->tid);
     $antonym = db_query('SELECT tid FROM {taxonomy_term_antonym} WHERE tid = :tid', array(':tid' => $term->tid))->fetchField();
-    $this->assertFalse($antonym, t('The antonym were deleted from the database.'));
+    $this->assertFalse($antonym, 'The antonym were deleted from the database.');
   }
+
 }
 
 /**
  * Tests for taxonomy term field and formatter.
  */
 class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase {
+
   protected $instance;
   protected $vocabulary;
 
   public static function getInfo() {
     return array(
-      'name'  => 'Taxonomy term reference field',
-      'description'  => 'Test the creation of term fields.',
+      'name' => 'Taxonomy term reference field',
+      'description' => 'Test the creation of term fields.',
       'group' => 'Taxonomy',
     );
   }
@@ -1473,10 +1481,10 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase {
     $entity->{$this->field_name}[$langcode][0]['tid'] = $term->tid;
     try {
       field_attach_validate('test_entity', $entity);
-      $this->pass(t('Correct term does not cause validation error'));
+      $this->pass('Correct term does not cause validation error.');
     }
     catch (FieldValidationException $e) {
-      $this->fail(t('Correct term does not cause validation error'));
+      $this->fail('Correct term does not cause validation error.');
     }
 
     $entity = field_test_create_stub_entity();
@@ -1484,10 +1492,10 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase {
     $entity->{$this->field_name}[$langcode][0]['tid'] = $bad_term->tid;
     try {
       field_attach_validate('test_entity', $entity);
-      $this->fail(t('Wrong term causes validation error'));
+      $this->fail('Wrong term causes validation error.');
     }
     catch (FieldValidationException $e) {
-      $this->pass(t('Wrong term causes validation error'));
+      $this->pass('Wrong term causes validation error.');
     }
   }
 
@@ -1501,7 +1509,7 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase {
     // Display creation form.
     $langcode = LANGUAGE_NONE;
     $this->drupalGet('test-entity/add/test-bundle');
-    $this->assertFieldByName("{$this->field_name}[$langcode]", '', t('Widget is displayed'));
+    $this->assertFieldByName("{$this->field_name}[$langcode]", '', 'Widget is displayed.');
 
     // Submit with some value.
     $edit = array(
@@ -1510,7 +1518,7 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase {
     $this->drupalPost(NULL, $edit, t('Save'));
     preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
-    $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), t('Entity was created'));
+    $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), 'Entity was created.');
 
     // Display the object.
     $entity = field_test_entity_test_load($id);
@@ -1518,12 +1526,12 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase {
     field_attach_prepare_view('test_entity', $entities, 'full');
     $entity->content = field_attach_view('test_entity', $entity, 'full');
     $this->content = drupal_render($entity->content);
-    $this->assertText($term->name, t('Term name is displayed'));
+    $this->assertText($term->name, 'Term name is displayed.');
 
     // Delete the vocabulary and verify that the widget is gone.
     taxonomy_vocabulary_delete($this->vocabulary->vid);
     $this->drupalGet('test-entity/add/test-bundle');
-    $this->assertNoFieldByName("{$this->field_name}[$langcode]", '', 'Widget is not displayed');
+    $this->assertNoFieldByName("{$this->field_name}[$langcode]", '', 'Widget is not displayed.');
   }
 
   /**
@@ -1555,30 +1563,32 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase {
 
     // Check that entity bundles are properly updated.
     $info = entity_get_info('taxonomy_term');
-    $this->assertFalse(isset($info['bundles'][$old_name]), t('The old bundle name does not appear in entity_get_info().'));
-    $this->assertTrue(isset($info['bundles'][$new_name]), t('The new bundle name appears in entity_get_info().'));
+    $this->assertFalse(isset($info['bundles'][$old_name]), 'The old bundle name does not appear in entity_get_info().');
+    $this->assertTrue(isset($info['bundles'][$new_name]), 'The new bundle name appears in entity_get_info().');
 
     // Check that the field instance is still attached to the vocabulary.
     $field = field_info_field($this->field_name);
     $allowed_values = $field['settings']['allowed_values'];
-    $this->assertEqual($allowed_values[0]['vocabulary'], $new_name, t('Index 0: Machine name was updated correctly.'));
-    $this->assertEqual($allowed_values[1]['vocabulary'], $new_name, t('Index 1: Machine name was updated correctly.'));
-    $this->assertEqual($allowed_values[2]['vocabulary'], 'foo', t('Index 2: Machine name was left untouched.'));
+    $this->assertEqual($allowed_values[0]['vocabulary'], $new_name, 'Index 0: Machine name was updated correctly.');
+    $this->assertEqual($allowed_values[1]['vocabulary'], $new_name, 'Index 1: Machine name was updated correctly.');
+    $this->assertEqual($allowed_values[2]['vocabulary'], 'foo', 'Index 2: Machine name was left untouched.');
   }
+
 }
 
 /**
  * Tests a taxonomy term reference field that allows multiple vocabularies.
  */
 class TaxonomyTermFieldMultipleVocabularyTestCase extends TaxonomyWebTestCase {
+
   protected $instance;
   protected $vocabulary1;
   protected $vocabulary2;
 
   public static function getInfo() {
     return array(
-      'name'  => 'Multiple vocabulary term reference field',
-      'description'  => 'Tests term reference fields that allow multiple vocabularies.',
+      'name' => 'Multiple vocabulary term reference field',
+      'description' => 'Tests term reference fields that allow multiple vocabularies.',
       'group' => 'Taxonomy',
     );
   }
@@ -1638,7 +1648,7 @@ class TaxonomyTermFieldMultipleVocabularyTestCase extends TaxonomyWebTestCase {
     // Submit an entity with both terms.
     $langcode = LANGUAGE_NONE;
     $this->drupalGet('test-entity/add/test-bundle');
-    $this->assertFieldByName("{$this->field_name}[$langcode][]", '', 'Widget is displayed');
+    $this->assertFieldByName("{$this->field_name}[$langcode][]", '', 'Widget is displayed.');
     $edit = array(
       "{$this->field_name}[$langcode][]" => array($term1->tid, $term2->tid),
     );
@@ -1677,7 +1687,7 @@ class TaxonomyTermFieldMultipleVocabularyTestCase extends TaxonomyWebTestCase {
 
     // The widget should still be displayed.
     $this->drupalGet('test-entity/add/test-bundle');
-    $this->assertFieldByName("{$this->field_name}[$langcode][]", '', 'Widget is still displayed');
+    $this->assertFieldByName("{$this->field_name}[$langcode][]", '', 'Widget is still displayed.');
 
     // Term 1 should still pass validation.
     $edit = array(
@@ -1685,13 +1695,14 @@ class TaxonomyTermFieldMultipleVocabularyTestCase extends TaxonomyWebTestCase {
     );
     $this->drupalPost(NULL, $edit, t('Save'));
   }
-}
 
+}
 
 /**
  * Test taxonomy token replacement in strings.
  */
 class TaxonomyTokenReplaceTestCase extends TaxonomyWebTestCase {
+
   public static function getInfo() {
     return array(
       'name' => 'Taxonomy token replacement',
@@ -1772,7 +1783,7 @@ class TaxonomyTokenReplaceTestCase extends TaxonomyWebTestCase {
 
     foreach ($tests as $input => $expected) {
       $output = token_replace($input, array('term' => $term1), array('language' => $language));
-      $this->assertEqual($output, $expected, t('Sanitized taxonomy term token %token replaced.', array('%token' => $input)));
+      $this->assertEqual($output, $expected, format_string('Sanitized taxonomy term token %token replaced.', array('%token' => $input)));
     }
 
     // Generate and test sanitized tokens for term2.
@@ -1788,11 +1799,11 @@ class TaxonomyTokenReplaceTestCase extends TaxonomyWebTestCase {
     $tests['[term:vocabulary:name]'] = check_plain($this->vocabulary->name);
 
     // Test to make sure that we generated something for each token.
-    $this->assertFalse(in_array(0, array_map('strlen', $tests)), t('No empty tokens generated.'));
+    $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
 
     foreach ($tests as $input => $expected) {
       $output = token_replace($input, array('term' => $term2), array('language' => $language));
-      $this->assertEqual($output, $expected, t('Sanitized taxonomy term token %token replaced.', array('%token' => $input)));
+      $this->assertEqual($output, $expected, format_string('Sanitized taxonomy term token %token replaced.', array('%token' => $input)));
     }
 
     // Generate and test unsanitized tokens.
@@ -1803,7 +1814,7 @@ class TaxonomyTokenReplaceTestCase extends TaxonomyWebTestCase {
 
     foreach ($tests as $input => $expected) {
       $output = token_replace($input, array('term' => $term2), array('language' => $language, 'sanitize' => FALSE));
-      $this->assertEqual($output, $expected, t('Unsanitized taxonomy term token %token replaced.', array('%token' => $input)));
+      $this->assertEqual($output, $expected, format_string('Unsanitized taxonomy term token %token replaced.', array('%token' => $input)));
     }
 
     // Generate and test sanitized tokens.
@@ -1815,11 +1826,11 @@ class TaxonomyTokenReplaceTestCase extends TaxonomyWebTestCase {
     $tests['[vocabulary:term-count]'] = 2;
 
     // Test to make sure that we generated something for each token.
-    $this->assertFalse(in_array(0, array_map('strlen', $tests)), t('No empty tokens generated.'));
+    $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
 
     foreach ($tests as $input => $expected) {
       $output = token_replace($input, array('vocabulary' => $this->vocabulary), array('language' => $language));
-      $this->assertEqual($output, $expected, t('Sanitized taxonomy vocabulary token %token replaced.', array('%token' => $input)));
+      $this->assertEqual($output, $expected, format_string('Sanitized taxonomy vocabulary token %token replaced.', array('%token' => $input)));
     }
 
     // Generate and test unsanitized tokens.
@@ -1828,15 +1839,17 @@ class TaxonomyTokenReplaceTestCase extends TaxonomyWebTestCase {
 
     foreach ($tests as $input => $expected) {
       $output = token_replace($input, array('vocabulary' => $this->vocabulary), array('language' => $language, 'sanitize' => FALSE));
-      $this->assertEqual($output, $expected, t('Unsanitized taxonomy vocabulary token %token replaced.', array('%token' => $input)));
+      $this->assertEqual($output, $expected, format_string('Unsanitized taxonomy vocabulary token %token replaced.', array('%token' => $input)));
     }
   }
+
 }
 
 /**
  * Tests for verifying that taxonomy pages use the correct theme.
  */
 class TaxonomyThemeTestCase extends TaxonomyWebTestCase {
+
   public static function getInfo() {
     return array(
       'name' => 'Taxonomy theme switching',
@@ -1867,15 +1880,70 @@ class TaxonomyThemeTestCase extends TaxonomyWebTestCase {
     // should use the administrative theme.
     $vocabulary = $this->createVocabulary();
     $this->drupalGet('admin/structure/taxonomy/' . $vocabulary->machine_name . '/add');
-    $this->assertRaw('seven/style.css', t("The administrative theme's CSS appears on the page for adding a taxonomy term."));
+    $this->assertRaw('seven/style.css', "The administrative theme's CSS appears on the page for adding a taxonomy term.");
 
     // Viewing a taxonomy term should use the default theme.
     $term = $this->createTerm($vocabulary);
     $this->drupalGet('taxonomy/term/' . $term->tid);
-    $this->assertRaw('bartik/css/style.css', t("The default theme's CSS appears on the page for viewing a taxonomy term."));
+    $this->assertRaw('bartik/css/style.css', "The default theme's CSS appears on the page for viewing a taxonomy term.");
 
     // Editing a taxonomy term should use the same theme as adding one.
     $this->drupalGet('taxonomy/term/' . $term->tid . '/edit');
-    $this->assertRaw('seven/style.css', t("The administrative theme's CSS appears on the page for editing a taxonomy term."));
+    $this->assertRaw('seven/style.css', "The administrative theme's CSS appears on the page for editing a taxonomy term.");
+  }
+
+}
+
+/**
+ * Tests the functionality of EntityFieldQuery for taxonomy entities.
+ */
+class TaxonomyEFQTestCase extends TaxonomyWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Taxonomy EntityFieldQuery',
+      'description' => 'Verifies operation of a taxonomy-based EntityFieldQuery.',
+      'group' => 'Taxonomy',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+    $this->admin_user = $this->drupalCreateUser(array('administer taxonomy'));
+    $this->drupalLogin($this->admin_user);
+    $this->vocabulary = $this->createVocabulary();
   }
+
+  /**
+   * Tests that a basic taxonomy EntityFieldQuery works.
+   */
+  function testTaxonomyEFQ() {
+    $terms = array();
+    for ($i = 0; $i < 5; $i++) {
+      $term = $this->createTerm($this->vocabulary);
+      $terms[$term->tid] = $term;
+    }
+    $query = new EntityFieldQuery();
+    $query->entityCondition('entity_type', 'taxonomy_term');
+    $result = $query->execute();
+    $result = $result['taxonomy_term'];
+    asort($result);
+    $this->assertEqual(array_keys($terms), array_keys($result), 'Taxonomy terms were retrieved by EntityFieldQuery.');
+
+    // Create a second vocabulary and five more terms.
+    $vocabulary2 = $this->createVocabulary();
+    $terms2 = array();
+    for ($i = 0; $i < 5; $i++) {
+      $term = $this->createTerm($vocabulary2);
+      $terms2[$term->tid] = $term;
+    }
+
+    $query = new EntityFieldQuery();
+    $query->entityCondition('entity_type', 'taxonomy_term');
+    $query->entityCondition('bundle', $vocabulary2->machine_name);
+    $result = $query->execute();
+    $result = $result['taxonomy_term'];
+    asort($result);
+    $this->assertEqual(array_keys($terms2), array_keys($result), format_string('Taxonomy terms from the %name vocabulary were retrieved by EntityFieldQuery.', array('%name' => $vocabulary2->name)));
+  }
+
 }
diff --git a/modules/toolbar/toolbar.info b/modules/toolbar/toolbar.info
index eaddba5d7..d086d8661 100644
--- a/modules/toolbar/toolbar.info
+++ b/modules/toolbar/toolbar.info
@@ -4,8 +4,8 @@ core = 7.x
 package = Core
 version = VERSION
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/tracker/tracker.info b/modules/tracker/tracker.info
index f6a4069f2..f661a0cde 100644
--- a/modules/tracker/tracker.info
+++ b/modules/tracker/tracker.info
@@ -6,8 +6,8 @@ version = VERSION
 core = 7.x
 files[] = tracker.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/tracker/tracker.install b/modules/tracker/tracker.install
index 84305d822..9967b9db4 100644
--- a/modules/tracker/tracker.install
+++ b/modules/tracker/tracker.install
@@ -221,5 +221,5 @@ function tracker_update_7000() {
 }
 
 /**
- * @} End of "addtogroup updates-6.x-to-7.x"
+ * @} End of "addtogroup updates-6.x-to-7.x".
  */
diff --git a/modules/translation/tests/translation_test.info b/modules/translation/tests/translation_test.info
index 2a08ab218..39b91c1eb 100644
--- a/modules/translation/tests/translation_test.info
+++ b/modules/translation/tests/translation_test.info
@@ -5,8 +5,8 @@ package = Testing
 version = VERSION
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/translation/translation.info b/modules/translation/translation.info
index 6726a857e..dbb0740c6 100644
--- a/modules/translation/translation.info
+++ b/modules/translation/translation.info
@@ -6,8 +6,8 @@ version = VERSION
 core = 7.x
 files[] = translation.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/translation/translation.module b/modules/translation/translation.module
index e61be1d66..331235705 100644
--- a/modules/translation/translation.module
+++ b/modules/translation/translation.module
@@ -84,7 +84,7 @@ function translation_menu() {
  * @see translation_menu()
  */
 function _translation_tab_access($node) {
-  if ($node->language != LANGUAGE_NONE && translation_supported_type($node->type) && node_access('view', $node)) {
+  if (entity_language('node', $node) != LANGUAGE_NONE && translation_supported_type($node->type) && node_access('view', $node)) {
     return user_access('translate content');
   }
   return FALSE;
@@ -233,7 +233,7 @@ function translation_node_view($node, $view_mode) {
     foreach ($translations as $langcode => $translation) {
       // Do not show links to the same node, to unpublished translations or to
       // translations in disabled languages.
-      if ($translation->status && isset($languages[$langcode]) && $langcode != $node->language) {
+      if ($translation->status && isset($languages[$langcode]) && $langcode != entity_language('node', $node)) {
         $language = $languages[$langcode];
         $key = "translation_$langcode";
 
@@ -313,7 +313,7 @@ function translation_node_prepare($node) {
 
     // Add field translations and let other modules module add custom translated
     // fields.
-    field_attach_prepare_translation('node', $node, $node->language, $source_node, $source_node->language);
+    field_attach_prepare_translation('node', $node, $langcode, $source_node, $source_node->language);
   }
 }
 
@@ -358,7 +358,8 @@ function translation_node_insert($node) {
 function translation_node_update($node) {
   // Only act if we are dealing with a content type supporting translations.
   if (translation_supported_type($node->type)) {
-    if (isset($node->translation) && $node->translation && !empty($node->language) && $node->tnid) {
+    $langcode = entity_language('node', $node);
+    if (isset($node->translation) && $node->translation && !empty($langcode) && $node->tnid) {
       // Update translation information.
       db_update('node')
         ->fields(array(
@@ -389,7 +390,8 @@ function translation_node_validate($node, $form) {
   if (translation_supported_type($node->type) && (!empty($node->tnid) || !empty($form['#node']->translation_source->nid))) {
     $tnid = !empty($node->tnid) ? $node->tnid : $form['#node']->translation_source->nid;
     $translations = translation_node_get_translations($tnid);
-    if (isset($translations[$node->language]) && $translations[$node->language]->nid != $node->nid ) {
+    $langcode = entity_language('node', $node);
+    if (isset($translations[$langcode]) && $translations[$langcode]->nid != $node->nid ) {
       form_set_error('language', t('There is already a translation in this language.'));
     }
   }
@@ -469,7 +471,8 @@ function translation_node_get_translations($tnid) {
         ->execute();
 
       foreach ($result as $node) {
-        $translations[$tnid][$node->language] = $node;
+        $langcode = entity_language('node', $node);
+        $translations[$tnid][$langcode] = $node;
       }
     }
     return $translations[$tnid];
@@ -523,10 +526,11 @@ function translation_language_switch_links_alter(array &$links, $type, $path) {
       // have translations it might be a language neutral node, in which case we
       // must leave the language switch links unaltered. This is true also for
       // nodes not having translation support enabled.
-      if (empty($node) || $node->language == LANGUAGE_NONE || !translation_supported_type($node->type)) {
+      if (empty($node) || entity_language('node', $node) == LANGUAGE_NONE || !translation_supported_type($node->type)) {
         return;
       }
-      $translations = array($node->language => $node);
+      $langcode = entity_language('node', $node);
+      $translations = array($langcode => $node);
     }
     else {
       $translations = translation_node_get_translations($node->tnid);
diff --git a/modules/translation/translation.pages.inc b/modules/translation/translation.pages.inc
index fa4070bb8..110fea603 100644
--- a/modules/translation/translation.pages.inc
+++ b/modules/translation/translation.pages.inc
@@ -27,7 +27,7 @@ function translation_node_overview($node) {
   else {
     // We have no translation source nid, this could be a new set, emulate that.
     $tnid = $node->nid;
-    $translations = array($node->language => $node);
+    $translations = array(entity_language('node', $node) => $node);
   }
 
   $type = variable_get('translation_language_type', LANGUAGE_TYPE_INTERFACE);
diff --git a/modules/translation/translation.test b/modules/translation/translation.test
index 09bc9e3b9..e64f9cb86 100644
--- a/modules/translation/translation.test
+++ b/modules/translation/translation.test
@@ -429,7 +429,7 @@ class TranslationTestCase extends DrupalWebTestCase {
 
     $result = TRUE;
     $languages = language_list();
-    $page_language = $languages[$node->language];
+    $page_language = $languages[entity_language('node', $node)];
     $translation_language = $languages[$translation->language];
     $url = url("node/$translation->nid", array('language' => $translation_language));
 
diff --git a/modules/trigger/tests/trigger_test.info b/modules/trigger/tests/trigger_test.info
index e0a3ddbf5..3f9dd05d7 100644
--- a/modules/trigger/tests/trigger_test.info
+++ b/modules/trigger/tests/trigger_test.info
@@ -4,8 +4,8 @@ package = Testing
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/trigger/trigger.admin.inc b/modules/trigger/trigger.admin.inc
index 447d0dc07..5b607c85d 100644
--- a/modules/trigger/trigger.admin.inc
+++ b/modules/trigger/trigger.admin.inc
@@ -53,7 +53,7 @@ function trigger_assign($module_to_display = NULL) {
  * @ingroup forms
  */
 function trigger_unassign($form, $form_state, $module, $hook = NULL, $aid = NULL) {
-  if (!($hook && $aid)) {
+  if (!isset($hook, $aid)) {
     drupal_goto('admin/structure/trigger');
   }
 
diff --git a/modules/trigger/trigger.info b/modules/trigger/trigger.info
index 753711b12..c6e7ee5fe 100644
--- a/modules/trigger/trigger.info
+++ b/modules/trigger/trigger.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = trigger.test
 configure = admin/structure/trigger
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/trigger/trigger.install b/modules/trigger/trigger.install
index 20d5c3a3d..779cd2aad 100644
--- a/modules/trigger/trigger.install
+++ b/modules/trigger/trigger.install
@@ -79,6 +79,11 @@ function trigger_update_7000() {
   db_add_primary_key('trigger_assignments', array('hook', 'aid'));
 }
 
+/**
+ * @addtogroup updates-7.x-extra
+ * @{
+ */
+
 /**
  * Increase the length of the "hook" field to 78 characters.
  *
@@ -105,3 +110,7 @@ function trigger_update_7002() {
       ->execute();
   }
 }
+
+/**
+ * @} End of "addtogroup updates-7.x-extra".
+ */
diff --git a/modules/trigger/trigger.module b/modules/trigger/trigger.module
index 82d117272..aeb1211c9 100644
--- a/modules/trigger/trigger.module
+++ b/modules/trigger/trigger.module
@@ -65,13 +65,35 @@ function trigger_menu() {
     'description' => 'Unassign an action from a trigger.',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('trigger_unassign'),
-    'access arguments' => array('administer actions'),
+    // Only accessible if there are any actions that can be unassigned.
+    'access callback' => 'trigger_menu_unassign_access',
+    // Only output in the breadcrumb, not in menu trees.
+    'type' => MENU_VISIBLE_IN_BREADCRUMB,
     'file' => 'trigger.admin.inc',
   );
 
   return $items;
 }
 
+/**
+ * Access callback: Determines if triggers can be unassigned.
+ *
+ * @return bool
+ *   TRUE if there are triggers that the user can unassign, FALSE otherwise.
+ *
+ * @see trigger_menu()
+ */
+function trigger_menu_unassign_access() {
+  if (!user_access('administer actions')) {
+    return FALSE;
+  }
+  $count = db_select('trigger_assignments')
+    ->countQuery()
+    ->execute()
+    ->fetchField();
+  return $count > 0;
+}
+
 /**
  * Implements hook_trigger_info().
  *
diff --git a/modules/trigger/trigger.test b/modules/trigger/trigger.test
index 138de6281..829e1898b 100644
--- a/modules/trigger/trigger.test
+++ b/modules/trigger/trigger.test
@@ -740,3 +740,32 @@ class TriggerOrphanedActionsTestCase extends DrupalWebTestCase {
     $this->assertRaw(t('!post %title has been updated.', array('!post' => 'Basic page', '%title' => $edit["title"])), t('Make sure the Basic page can be updated with the missing trigger function.'));
   }
 }
+
+/**
+ * Tests the unassigning of triggers.
+ */
+class TriggerUnassignTestCase extends DrupalWebTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Trigger unassigning',
+      'description' => 'Tests the unassigning of triggers.',
+      'group' => 'Trigger',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('trigger', 'trigger_test');
+    $web_user = $this->drupalCreateUser(array('administer actions'));
+    $this->drupalLogin($web_user);
+  }
+
+  /**
+   * Tests an attempt to unassign triggers when none are assigned.
+   */
+  function testUnassignAccessDenied() {
+    $this->drupalGet('admin/structure/trigger/unassign');
+    $this->assertResponse(403, 'If there are no actions available, return access denied.');
+  }
+
+}
diff --git a/modules/update/tests/aaa_update_test.info b/modules/update/tests/aaa_update_test.info
index a2eb6dc3d..9d5f624e7 100644
--- a/modules/update/tests/aaa_update_test.info
+++ b/modules/update/tests/aaa_update_test.info
@@ -4,8 +4,8 @@ package = Testing
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/update/tests/bbb_update_test.info b/modules/update/tests/bbb_update_test.info
index e8f8f856a..bec9aae16 100644
--- a/modules/update/tests/bbb_update_test.info
+++ b/modules/update/tests/bbb_update_test.info
@@ -4,8 +4,8 @@ package = Testing
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/update/tests/ccc_update_test.info b/modules/update/tests/ccc_update_test.info
index aac3a7b63..ad559a307 100644
--- a/modules/update/tests/ccc_update_test.info
+++ b/modules/update/tests/ccc_update_test.info
@@ -4,8 +4,8 @@ package = Testing
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/update/tests/themes/update_test_basetheme/update_test_basetheme.info b/modules/update/tests/themes/update_test_basetheme/update_test_basetheme.info
index eb631e810..81022b26c 100644
--- a/modules/update/tests/themes/update_test_basetheme/update_test_basetheme.info
+++ b/modules/update/tests/themes/update_test_basetheme/update_test_basetheme.info
@@ -3,8 +3,8 @@ description = Test theme which acts as a base theme for other test subthemes.
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/update/tests/themes/update_test_subtheme/update_test_subtheme.info b/modules/update/tests/themes/update_test_subtheme/update_test_subtheme.info
index c097d5bc1..f9663e429 100644
--- a/modules/update/tests/themes/update_test_subtheme/update_test_subtheme.info
+++ b/modules/update/tests/themes/update_test_subtheme/update_test_subtheme.info
@@ -4,8 +4,8 @@ core = 7.x
 base theme = update_test_basetheme
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/update/tests/update_test.info b/modules/update/tests/update_test.info
index ddcc2b5c2..ca1f9be42 100644
--- a/modules/update/tests/update_test.info
+++ b/modules/update/tests/update_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/update/tests/update_test.module b/modules/update/tests/update_test.module
index e7ee43eec..6fe4bddea 100644
--- a/modules/update/tests/update_test.module
+++ b/modules/update/tests/update_test.module
@@ -1,5 +1,10 @@
 <?php
 
+/**
+ * @file
+ * Module for testing Update Manager functionality.
+ */
+
 /**
  * Implements hook_system_theme_info().
  */
@@ -34,13 +39,13 @@ function update_test_menu() {
 /**
  * Implements hook_system_info_alter().
  *
- * This checks the 'update_test_system_info' variable and sees if we need to
- * alter the system info for the given $file based on the setting. The setting
- * is expected to be a nested associative array. If the key '#all' is defined,
- * its subarray will include .info keys and values for all modules and themes
- * on the system. Otherwise, the settings array is keyed by the module or
- * theme short name ($file->name) and the subarrays contain settings just for
- * that module or theme.
+ * Checks the 'update_test_system_info' variable and sees if we need to alter
+ * the system info for the given $file based on the setting. The setting is
+ * expected to be a nested associative array. If the key '#all' is defined, its
+ * subarray will include .info keys and values for all modules and themes on the
+ * system. Otherwise, the settings array is keyed by the module or theme short
+ * name ($file->name) and the subarrays contain settings just for that module or
+ * theme.
  */
 function update_test_system_info_alter(&$info, $file) {
   $setting = variable_get('update_test_system_info', array());
@@ -56,13 +61,12 @@ function update_test_system_info_alter(&$info, $file) {
 /**
  * Implements hook_update_status_alter().
  *
- * This checks the 'update_test_update_status' variable and sees if we need to
- * alter the update status for the given project based on the setting. The
- * setting is expected to be a nested associative array. If the key '#all' is
- * defined, its subarray will include .info keys and values for all modules
- * and themes on the system. Otherwise, the settings array is keyed by the
- * module or theme short name and the subarrays contain settings just for that
- * module or theme.
+ * Checks the 'update_test_update_status' variable and sees if we need to alter
+ * the update status for the given project based on the setting. The setting is
+ * expected to be a nested associative array. If the key '#all' is defined, its
+ * subarray will include .info keys and values for all modules and themes on the
+ * system. Otherwise, the settings array is keyed by the module or theme short
+ * name and the subarrays contain settings just for that module or theme.
  */
 function update_test_update_status_alter(&$projects) {
   $setting = variable_get('update_test_update_status', array());
@@ -80,18 +84,20 @@ function update_test_update_status_alter(&$projects) {
 }
 
 /**
- * Page callback, prints mock XML for the update module.
+ * Page callback: Prints mock XML for the Update Manager module.
  *
  * The specific XML file to print depends on two things: the project we're
  * trying to fetch data for, and the desired "availability scenario" for that
- * project which we're trying to test. Before attempting to fetch this data
- * (by checking for updates on the available updates report), callers need to
- * define the 'update_test_xml_map' variable as an array, keyed by project
- * name, indicating which availability scenario to use for that project.
+ * project which we're trying to test. Before attempting to fetch this data (by
+ * checking for updates on the available updates report), callers need to define
+ * the 'update_test_xml_map' variable as an array, keyed by project name,
+ * indicating which availability scenario to use for that project.
  *
  * @param $project_name
- *   The project short name update.module is trying to fetch data for (the
+ *   The project short name the update manager is trying to fetch data for (the
  *   fetch URLs are of the form: [base_url]/[project_name]/[core_version]).
+ *
+ * @see update_test_menu()
  */
 function update_test_mock_page($project_name) {
   $xml_map = variable_get('update_test_xml_map', FALSE);
@@ -115,7 +121,7 @@ function update_test_mock_page($project_name) {
 }
 
 /**
- * Implement hook_archiver_info().
+ * Implements hook_archiver_info().
  */
 function update_test_archiver_info() {
   return array(
@@ -147,13 +153,23 @@ function update_test_filetransfer_info() {
 }
 
 /**
- * Mock FileTransfer object to test the settings form functionality.
+ * Mocks a FileTransfer object to test the settings form functionality.
  */
 class UpdateTestFileTransfer {
+
+  /**
+   * Returns an UpdateTestFileTransfer object.
+   *
+   * @return
+   *   A new UpdateTestFileTransfer object.
+   */
   public static function factory() {
     return new UpdateTestFileTransfer;
   }
 
+  /**
+   * Returns a settings form with a text field to input a username.
+   */
   public function getSettingsForm() {
     $form = array();
     $form['udpate_test_username'] = array(
@@ -165,7 +181,9 @@ class UpdateTestFileTransfer {
 }
 
 /**
- * Return an Error 503 (Service unavailable) page.
+ * Page callback: Displays an Error 503 (Service unavailable) page.
+ *
+ * @see update_test_menu()
  */
 function update_callback_service_unavailable() {
   drupal_add_http_header('Status', '503 Service unavailable');
diff --git a/modules/update/update-rtl.css b/modules/update/update-rtl.css
index 5fc83d1a6..f181c8454 100644
--- a/modules/update/update-rtl.css
+++ b/modules/update/update-rtl.css
@@ -1,3 +1,7 @@
+/**
+ * @file
+ * RTL styles used by the Update Manager module.
+ */
 
 .update .project {
   padding-right: .25em;
diff --git a/modules/update/update.api.php b/modules/update/update.api.php
index 87f95cac5..cb5669e32 100644
--- a/modules/update/update.api.php
+++ b/modules/update/update.api.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Hooks provided by the Update Status module.
+ * Hooks provided by the Update Manager module.
  */
 
 /**
@@ -14,23 +14,22 @@
  * Alter the list of projects before fetching data and comparing versions.
  *
  * Most modules will never need to implement this hook. It is for advanced
- * interaction with the update status module: mere mortals need not apply.
- * The primary use-case for this hook is to add projects to the list, for
- * example, to provide update status data on disabled modules and themes. A
- * contributed module might want to hide projects from the list, for example,
- * if there is a site-specific module that doesn't have any official releases,
- * that module could remove itself from this list to avoid "No available
- * releases found" warnings on the available updates report. In rare cases, a
- * module might want to alter the data associated with a project already in
- * the list.
+ * interaction with the Update Manager module. The primary use-case for this
+ * hook is to add projects to the list; for example, to provide update status
+ * data on disabled modules and themes. A contributed module might want to hide
+ * projects from the list; for example, if there is a site-specific module that
+ * doesn't have any official releases, that module could remove itself from this
+ * list to avoid "No available releases found" warnings on the available updates
+ * report. In rare cases, a module might want to alter the data associated with
+ * a project already in the list.
  *
  * @param $projects
  *   Reference to an array of the projects installed on the system. This
- *   includes all the metadata documented in the comments below for each
- *   project (either module or theme) that is currently enabled. The array is
- *   initially populated inside update_get_projects() with the help of
- *   _update_process_info_list(), so look there for examples of how to
- *   populate the array with real values.
+ *   includes all the metadata documented in the comments below for each project
+ *   (either module or theme) that is currently enabled. The array is initially
+ *   populated inside update_get_projects() with the help of
+ *   _update_process_info_list(), so look there for examples of how to populate
+ *   the array with real values.
  *
  * @see update_get_projects()
  * @see _update_process_info_list()
@@ -118,6 +117,7 @@ function hook_update_status_alter(&$projects) {
  *   no problems, return an empty array.
  *
  * @see update_manager_archive_verify()
+ * @ingroup update_manager_file
  */
 function hook_verify_update_archive($project, $archive_file, $directory) {
   $errors = array();
diff --git a/modules/update/update.authorize.inc b/modules/update/update.authorize.inc
index c9b76dd30..6ddd2c53a 100644
--- a/modules/update/update.authorize.inc
+++ b/modules/update/update.authorize.inc
@@ -2,15 +2,19 @@
 
 /**
  * @file
- * Callbacks and related functions invoked by authorize.php to update projects
- * on the Drupal site. We use the Batch API to actually update each individual
- * project on the site. All of the code in this file is run at a low bootstrap
- * level (modules are not loaded), so these functions cannot assume access to
- * the rest of the update module code.
+ * Callbacks and related functions invoked by authorize.php to update projects.
+ *
+ * We use the Batch API to actually update each individual project on the site.
+ * All of the code in this file is run at a low bootstrap level (modules are not
+ * loaded), so these functions cannot assume access to the rest of the code of
+ * the Update Manager module.
  */
 
 /**
- * Callback invoked by authorize.php to update existing projects.
+ * Updates existing projects when invoked by authorize.php.
+ *
+ * Callback for system_authorized_init() in
+ * update_manager_update_ready_form_submit().
  *
  * @param $filetransfer
  *   The FileTransfer object created by authorize.php for use during this
@@ -18,9 +22,9 @@
  * @param $projects
  *   A nested array of projects to install into the live webroot, keyed by
  *   project name. Each subarray contains the following keys:
- *   - 'project': The canonical project short name.
- *   - 'updater_name': The name of the Updater class to use for this project.
- *   - 'local_url': The locally installed location of new code to update with.
+ *   - project: The canonical project short name.
+ *   - updater_name: The name of the Updater class to use for this project.
+ *   - local_url: The locally installed location of new code to update with.
  */
 function update_authorize_run_update($filetransfer, $projects) {
   $operations = array();
@@ -50,13 +54,16 @@ function update_authorize_run_update($filetransfer, $projects) {
 }
 
 /**
- * Callback invoked by authorize.php to install a new project.
+ * Installs a new project when invoked by authorize.php.
+ *
+ * Callback for system_authorized_init() in
+ * update_manager_install_form_submit().
  *
  * @param FileTransfer $filetransfer
  *   The FileTransfer object created by authorize.php for use during this
  *   operation.
  * @param string $project
- *   The canonical project short name (e.g. {system}.name).
+ *   The canonical project short name (e.g., {system}.name).
  * @param string $updater_name
  *   The name of the Updater class to use for installing this project.
  * @param string $local_url
@@ -90,7 +97,7 @@ function update_authorize_run_install($filetransfer, $project, $updater_name, $l
 }
 
 /**
- * Copy a project to its proper place when authorized with elevated privileges.
+ * Batch callback: Copies project to its proper place when authorized to do so.
  *
  * @param string $project
  *   The canonical short name of the project being installed.
@@ -102,7 +109,7 @@ function update_authorize_run_install($filetransfer, $project, $updater_name, $l
  * @param FileTransfer $filetransfer
  *   The FileTransfer object to use for performing this operation.
  * @param array $context
- *   Reference to an array used for BatchAPI storage.
+ *   Reference to an array used for Batch API storage.
  */
 function update_authorize_batch_copy_project($project, $updater_name, $local_url, $filetransfer, &$context) {
 
@@ -118,15 +125,13 @@ function update_authorize_batch_copy_project($project, $updater_name, $local_url
     $context['results']['tasks'] = array();
   }
 
-  /**
-   * The batch API uses a session, and since all the arguments are serialized
-   * and unserialized between requests, although the FileTransfer object
-   * itself will be reconstructed, the connection pointer itself will be lost.
-   * However, the FileTransfer object will still have the connection variable,
-   * even though the connection itself is now gone. So, although it's ugly, we
-   * have to unset the connection variable at this point so that the
-   * FileTransfer object will re-initiate the actual connection.
-   */
+  // The batch API uses a session, and since all the arguments are serialized
+  // and unserialized between requests, although the FileTransfer object itself
+  // will be reconstructed, the connection pointer itself will be lost. However,
+  // the FileTransfer object will still have the connection variable, even
+  // though the connection itself is now gone. So, although it's ugly, we have
+  // to unset the connection variable at this point so that the FileTransfer
+  // object will re-initiate the actual connection.
   unset($filetransfer->connection);
 
   if (!empty($context['results']['log'][$project]['#abort'])) {
@@ -163,11 +168,16 @@ function update_authorize_batch_copy_project($project, $updater_name, $local_url
 }
 
 /**
- * Batch callback for when the authorized update batch is finished.
+ * Batch callback: Performs actions when the authorized update batch is done.
  *
  * This processes the results and stashes them into SESSION such that
  * authorize.php will render a report. Also responsible for putting the site
  * back online and clearing the update status cache after a successful update.
+ *
+ * @param $success
+ *   TRUE if the batch operation was successful; FALSE if there were errors.
+ * @param $results
+ *   An associative array of results from the batch operation.
  */
 function update_authorize_update_batch_finished($success, $results) {
   foreach ($results['log'] as $project => $messages) {
@@ -225,11 +235,16 @@ function update_authorize_update_batch_finished($success, $results) {
 }
 
 /**
- * Batch callback for when the authorized install batch is finished.
+ * Batch callback: Performs actions when the authorized install batch is done.
  *
  * This processes the results and stashes them into SESSION such that
  * authorize.php will render a report. Also responsible for putting the site
  * back online after a successful install if necessary.
+ *
+ * @param $success
+ *   TRUE if the batch operation was a success; FALSE if there were errors.
+ * @param $results
+ *   An associative array of results from the batch operation.
  */
 function update_authorize_install_batch_finished($success, $results) {
   foreach ($results['log'] as $project => $messages) {
@@ -279,26 +294,30 @@ function update_authorize_install_batch_finished($success, $results) {
 }
 
 /**
- * Helper function to create a structure of log messages.
+ * Creates a structure of log messages.
  *
  * @param array $project_results
+ *   An associative array of results from the batch operation.
  * @param string $message
+ *   A string containing a log message.
  * @param bool $success
+ *   (optional) TRUE if the operation the message is about was a success, FALSE
+ *   if there were errors. Defaults to TRUE.
  */
 function _update_batch_create_message(&$project_results, $message, $success = TRUE) {
   $project_results[] = array('message' => $message, 'success' => $success);
 }
 
 /**
- * Private helper function to clear cached available update status data.
+ * Clears cached available update status data.
  *
- * Since this function is run at such a low bootstrap level, update.module is
- * not loaded. So, we can't just call _update_cache_clear(). However, the
- * database is bootstrapped, so we can do a query ourselves to clear out what
- * we want to clear.
+ * Since this function is run at such a low bootstrap level, the Update Manager
+ * module is not loaded. So, we can't just call _update_cache_clear(). However,
+ * the database is bootstrapped, so we can do a query ourselves to clear out
+ * what we want to clear.
  *
- * Note that we do not want to just truncate the table, since that would
- * remove items related to currently pending fetch attempts.
+ * Note that we do not want to just truncate the table, since that would remove
+ * items related to currently pending fetch attempts.
  *
  * @see update_authorize_update_batch_finished()
  * @see _update_cache_clear()
diff --git a/modules/update/update.compare.inc b/modules/update/update.compare.inc
index 2ccd97c0e..cd8b762d0 100644
--- a/modules/update/update.compare.inc
+++ b/modules/update/update.compare.inc
@@ -6,7 +6,7 @@
  */
 
 /**
- * Fetch an array of installed and enabled projects.
+ * Fetches an array of installed and enabled projects.
  *
  * This is only responsible for generating an array of projects (taking into
  * account projects that include more than one module or theme). Other
@@ -15,14 +15,39 @@
  * that logic is only required when preparing the status report, not for
  * fetching the available release data.
  *
- * This array is fairly expensive to construct, since it involves a lot of
- * disk I/O, so we cache the results into the {cache_update} table using the
- * 'update_project_projects' cache ID. However, since this is not the data
- * about available updates fetched from the network, it is ok to invalidate it
- * somewhat quickly. If we keep this data for very long, site administrators
- * are more likely to see incorrect results if they upgrade to a newer version
- * of a module or theme but do not visit certain pages that automatically
- * clear this cache.
+ * This array is fairly expensive to construct, since it involves a lot of disk
+ * I/O, so we cache the results into the {cache_update} table using the
+ * 'update_project_projects' cache ID. However, since this is not the data about
+ * available updates fetched from the network, it is acceptable to invalidate it
+ * somewhat quickly. If we keep this data for very long, site administrators are
+ * more likely to see incorrect results if they upgrade to a newer version of a
+ * module or theme but do not visit certain pages that automatically clear this
+ * cache.
+ *
+ * @return
+ *   An associative array of currently enabled projects keyed by the
+ *   machine-readable project short name. Each project contains:
+ *   - name: The machine-readable project short name.
+ *   - info: An array with values from the main .info file for this project.
+ *     - name: The human-readable name of the project.
+ *     - package: The package that the project is grouped under.
+ *     - version: The version of the project.
+ *     - project: The Drupal.org project name.
+ *     - datestamp: The date stamp of the project's main .info file.
+ *     - _info_file_ctime: The maximum file change time for all of the .info
+ *       files included in this project.
+ *   - datestamp: The date stamp when the project was released, if known.
+ *   - includes: An associative array containing all projects included with this
+ *     project, keyed by the machine-readable short name with the human-readable
+ *     name as value.
+ *   - project_type: The type of project. Allowed values are 'module' and
+ *     'theme'.
+ *   - project_status: This indicates if the project is enabled and will always
+ *     be TRUE, as the function only returns enabled projects.
+ *   - sub_themes: If the project is a theme it contains an associative array of
+ *     all sub-themes.
+ *   - base_themes: If the project is a theme it contains an associative array
+ *     of all base-themes.
  *
  * @see update_process_project_info()
  * @see update_calculate_project_data()
@@ -53,25 +78,25 @@ function update_get_projects() {
 }
 
 /**
- * Populate an array of project data.
- *
- * This iterates over a list of the installed modules or themes and groups
- * them by project and status. A few parts of this function assume that
- * enabled modules and themes are always processed first, and if disabled
- * modules or themes are being processed (there is a setting to control if
- * disabled code should be included in the Available updates report or not),
- * those are only processed after $projects has been populated with
- * information about the enabled code. 'Hidden' modules and themes are always
- * ignored. This function also records the latest change time on the .info
- * files for each module or theme, which is important data which is used when
- * deciding if the cached available update data should be invalidated.
+ * Populates an array of project data.
+ *
+ * This iterates over a list of the installed modules or themes and groups them
+ * by project and status. A few parts of this function assume that enabled
+ * modules and themes are always processed first, and if disabled modules or
+ * themes are being processed (there is a setting to control if disabled code
+ * should be included or not in the 'Available updates' report), those are only
+ * processed after $projects has been populated with information about the
+ * enabled code. Modules and themes set as hidden are always ignored. This
+ * function also records the latest change time on the .info files for each
+ * module or theme, which is important data which is used when deciding if the
+ * cached available update data should be invalidated.
  *
  * @param $projects
  *   Reference to the array of project data of what's installed on this site.
  * @param $list
  *   Array of data to process to add the relevant info to the $projects array.
  * @param $project_type
- *   The kind of data in the list (can be 'module' or 'theme').
+ *   The kind of data in the list. Can be 'module' or 'theme'.
  * @param $status
  *   Boolean that controls what status (enabled or disabled) to process out of
  *   the $list and add to the $projects array.
@@ -211,8 +236,13 @@ function _update_process_info_list(&$projects, $list, $project_type, $status) {
 }
 
 /**
- * Given a $file object (as returned by system_get_files_database()), figure
- * out what project it belongs to.
+ * Determines what project a given file object belongs to.
+ *
+ * @param $file
+ *   A file object as returned by system_get_files_database().
+ *
+ * @return
+ *   The canonical project short name.
  *
  * @see system_get_files_database()
  */
@@ -228,7 +258,9 @@ function update_get_project_name($file) {
 }
 
 /**
- * Process the list of projects on the system to figure out the currently
+ * Determines version and type information for currently installed projects.
+ *
+ * Processes the list of projects on the system to figure out the currently
  * installed versions, and other information that is required before we can
  * compare against the available releases to produce the status report.
  *
@@ -277,7 +309,7 @@ function update_process_project_info(&$projects) {
 }
 
 /**
- * Calculate the current update status of all projects on the site.
+ * Calculates the current update status of all projects on the site.
  *
  * The results of this function are expensive to compute, especially on sites
  * with lots of modules or themes, since it involves a lot of comparisons and
@@ -285,13 +317,16 @@ function update_process_project_info(&$projects) {
  * table using the 'update_project_data' cache ID. However, since this is not
  * the data about available updates fetched from the network, it is ok to
  * invalidate it somewhat quickly. If we keep this data for very long, site
- * administrators are more likely to see incorrect results if they upgrade to
- * a newer version of a module or theme but do not visit certain pages that
+ * administrators are more likely to see incorrect results if they upgrade to a
+ * newer version of a module or theme but do not visit certain pages that
  * automatically clear this cache.
  *
  * @param array $available
  *   Data about available project releases.
  *
+ * @return
+ *   An array of installed projects with current update status information.
+ *
  * @see update_get_available()
  * @see update_get_projects()
  * @see update_process_project_info()
@@ -327,52 +362,50 @@ function update_calculate_project_data($available) {
 }
 
 /**
- * Calculate the current update status of a specific project.
+ * Calculates the current update status of a specific project.
  *
- * This function is the heart of the update status feature. For each project
- * it is invoked with, it first checks if the project has been flagged with a
+ * This function is the heart of the update status feature. For each project it
+ * is invoked with, it first checks if the project has been flagged with a
  * special status like "unsupported" or "insecure", or if the project node
  * itself has been unpublished. In any of those cases, the project is marked
  * with an error and the next project is considered.
  *
  * If the project itself is valid, the function decides what major release
  * series to consider. The project defines what the currently supported major
- * versions are for each version of core, so the first step is to make sure
- * the current version is still supported. If so, that's the target version.
- * If the current version is unsupported, the project maintainer's recommended
- * major version is used. There's also a check to make sure that this function
- * never recommends an earlier release than the currently installed major
- * version.
- *
- * Given a target major version, it scans the available releases looking for
+ * versions are for each version of core, so the first step is to make sure the
+ * current version is still supported. If so, that's the target version. If the
+ * current version is unsupported, the project maintainer's recommended major
+ * version is used. There's also a check to make sure that this function never
+ * recommends an earlier release than the currently installed major version.
+ *
+ * Given a target major version, the available releases are scanned looking for
  * the specific release to recommend (avoiding beta releases and development
- * snapshots if possible). This is complicated to describe, but an example
- * will help clarify. For the target major version, find the highest patch
- * level. If there is a release at that patch level with no extra ("beta",
- * etc), then we recommend the release at that patch level with the most
- * recent release date. If every release at that patch level has extra (only
- * betas), then recommend the latest release from the previous patch
- * level. For example:
+ * snapshots if possible). For the target major version, the highest patch level
+ * is found. If there is a release at that patch level with no extra ("beta",
+ * etc.), then the release at that patch level with the most recent release date
+ * is recommended. If every release at that patch level has extra (only betas),
+ * then the latest release from the previous patch level is recommended. For
+ * example:
  *
- * 1.6-bugfix <-- recommended version because 1.6 already exists.
- * 1.6
+ * - 1.6-bugfix <-- recommended version because 1.6 already exists.
+ * - 1.6
  *
  * or
  *
- * 1.6-beta
- * 1.5 <-- recommended version because no 1.6 exists.
- * 1.4
+ * - 1.6-beta
+ * - 1.5 <-- recommended version because no 1.6 exists.
+ * - 1.4
  *
- * It also looks for the latest release from the same major version, even a
- * beta release, to display to the user as the "Latest version" option.
- * Additionally, it finds the latest official release from any higher major
- * versions that have been released to provide a set of "Also available"
+ * Also, the latest release from the same major version is looked for, even beta
+ * releases, to display to the user as the "Latest version" option.
+ * Additionally, the latest official release from any higher major versions that
+ * have been released is searched for to provide a set of "Also available"
  * options.
  *
- * Finally, and most importantly, it keeps scanning the release history until
- * it gets to the currently installed release, searching for anything marked
- * as a security update. If any security updates have been found between the
- * recommended release and the installed version, all of the releases that
+ * Finally, and most importantly, the release history continues to be scanned
+ * until the currently installed release is reached, searching for anything
+ * marked as a security update. If any security updates have been found between
+ * the recommended release and the installed version, all of the releases that
  * included a security fix are recorded so that the site administrator can be
  * warned their site is insecure, and links pointing to the release notes for
  * each security update can be included (which, in turn, will link to the
@@ -381,9 +414,15 @@ function update_calculate_project_data($available) {
  * This function relies on the fact that the .xml release history data comes
  * sorted based on major version and patch level, then finally by release date
  * if there are multiple releases such as betas from the same major.patch
- * version (e.g. 5.x-1.5-beta1, 5.x-1.5-beta2, and 5.x-1.5). Development
+ * version (e.g., 5.x-1.5-beta1, 5.x-1.5-beta2, and 5.x-1.5). Development
  * snapshots for a given major version are always listed last.
  *
+ * @param $project
+ *   An array containing information about a specific project.
+ * @param $project_data
+ *   An array containing information about a specific project.
+ * @param $available
+ *   Data about available project releases of a specific project.
  */
 function update_calculate_project_update_status($project, &$project_data, $available) {
   foreach (array('title', 'link') as $attribute) {
@@ -707,16 +746,16 @@ function update_calculate_project_update_status($project, &$project_data, $avail
 }
 
 /**
- * Retrieve data from {cache_update} or empty the cache when necessary.
+ * Retrieves data from {cache_update} or empties the cache when necessary.
  *
  * Two very expensive arrays computed by this module are the list of all
- * installed modules and themes (and .info data, project associations, etc),
- * and the current status of the site relative to the currently available
- * releases. These two arrays are cached in the {cache_update} table and used
- * whenever possible. The cache is cleared whenever the administrator visits
- * the status report, available updates report, or the module or theme
- * administration pages, since we should always recompute the most current
- * values on any of those pages.
+ * installed modules and themes (and .info data, project associations, etc), and
+ * the current status of the site relative to the currently available releases.
+ * These two arrays are cached in the {cache_update} table and used whenever
+ * possible. The cache is cleared whenever the administrator visits the status
+ * report, available updates report, or the module or theme administration
+ * pages, since we should always recompute the most current values on any of
+ * those pages.
  *
  * Note: while both of these arrays are expensive to compute (in terms of disk
  * I/O and some fairly heavy CPU processing), neither of these is the actual
@@ -726,13 +765,13 @@ function update_calculate_project_update_status($project, &$project_data, $avail
  * hour and never get invalidated just by visiting a page on the site.
  *
  * @param $cid
- *   The cache id of data to return from the cache. Valid options are
+ *   The cache ID of data to return from the cache. Valid options are
  *   'update_project_data' and 'update_project_projects'.
  *
  * @return
  *   The cached value of the $projects array generated by
- *   update_calculate_project_data() or update_get_projects(), or an empty
- *   array when the cache is cleared.
+ *   update_calculate_project_data() or update_get_projects(), or an empty array
+ *   when the cache is cleared.
  */
 function update_project_cache($cid) {
   $projects = array();
@@ -764,13 +803,13 @@ function update_project_cache($cid) {
 }
 
 /**
- * Filter the project .info data to only save attributes we need.
+ * Filters the project .info data to only save attributes we need.
  *
  * @param array $info
  *   Array of .info file data as returned by drupal_parse_info_file().
  *
  * @return
- *   Array of .info file data we need for the Update manager.
+ *   Array of .info file data we need for the update manager.
  *
  * @see _update_process_info_list()
  */
diff --git a/modules/update/update.css b/modules/update/update.css
index d30dfb6e5..ba45fe6b9 100644
--- a/modules/update/update.css
+++ b/modules/update/update.css
@@ -1,3 +1,7 @@
+/**
+ * @file
+ * Styles used by the Update Manager module.
+ */
 
 .update .project {
   font-weight: bold;
diff --git a/modules/update/update.fetch.inc b/modules/update/update.fetch.inc
index ee5d77b16..860a1b975 100644
--- a/modules/update/update.fetch.inc
+++ b/modules/update/update.fetch.inc
@@ -6,7 +6,11 @@
  */
 
 /**
- * Callback to manually check the update status without cron.
+ * Page callback: Checks for updates and displays the update status report.
+ *
+ * Manually checks the update status without the use of cron.
+ *
+ * @see update_menu()
  */
 function update_manual_status() {
   _update_refresh();
@@ -25,7 +29,10 @@ function update_manual_status() {
 }
 
 /**
- * Process a step in the batch for fetching available update data.
+ * Batch callback: Processes a step in batch for fetching available update data.
+ *
+ * @param $context
+ *   Reference to an array used for Batch API storage.
  */
 function update_fetch_data_batch(&$context) {
   $queue = DrupalQueue::get('update_fetch_tasks');
@@ -70,12 +77,12 @@ function update_fetch_data_batch(&$context) {
 }
 
 /**
- * Batch API callback when all fetch tasks have been completed.
+ * Batch callback: Performs actions when all fetch tasks have been completed.
  *
  * @param $success
- *   Boolean indicating the success of the batch.
+ *   TRUE if the batch operation was successful; FALSE if there were errors.
  * @param $results
- *   Associative array holding the results of the batch, including the key
+ *   An associative array of results from the batch operation, including the key
  *   'updated' which holds the total number of projects we fetched available
  *   update data for.
  */
@@ -96,7 +103,7 @@ function update_fetch_data_finished($success, $results) {
 }
 
 /**
- * Attempt to drain the queue of tasks for release history data to fetch.
+ * Attempts to drain the queue of tasks for release history data to fetch.
  */
 function _update_fetch_data() {
   $queue = DrupalQueue::get('update_fetch_tasks');
@@ -108,13 +115,14 @@ function _update_fetch_data() {
 }
 
 /**
- * Process a task to fetch available update data for a single project.
+ * Processes a task to fetch available update data for a single project.
  *
- * Once the release history XML data is downloaded, it is parsed and saved
- * into the {cache_update} table in an entry just for that project.
+ * Once the release history XML data is downloaded, it is parsed and saved into
+ * the {cache_update} table in an entry just for that project.
  *
  * @param $project
  *   Associative array of information about the project to fetch data for.
+ *
  * @return
  *   TRUE if we fetched parsable XML, otherwise FALSE.
  */
@@ -184,7 +192,7 @@ function _update_process_fetch_task($project) {
 }
 
 /**
- * Clear out all the cached available update data and initiate re-fetching.
+ * Clears out all the cached available update data and initiates re-fetching.
  */
 function _update_refresh() {
   module_load_include('inc', 'update', 'update.compare');
@@ -211,7 +219,7 @@ function _update_refresh() {
 }
 
 /**
- * Add a task to the queue for fetching release history data for a project.
+ * Adds a task to the queue for fetching release history data for a project.
  *
  * We only create a new fetch task if there's no task already in the queue for
  * this particular project (based on 'fetch_task::' entries in the
@@ -219,8 +227,8 @@ function _update_refresh() {
  *
  * @param $project
  *   Associative array of information about a project as created by
- *   update_get_projects(), including keys such as 'name' (short name),
- *   and the 'info' array with data from a .info file for the project.
+ *   update_get_projects(), including keys such as 'name' (short name), and the
+ *   'info' array with data from a .info file for the project.
  *
  * @see update_get_projects()
  * @see update_get_available()
@@ -260,14 +268,17 @@ function _update_create_fetch_task($project) {
 /**
  * Generates the URL to fetch information about project updates.
  *
- * This figures out the right URL to use, based on the project's .info file
- * and the global defaults. Appends optional query arguments when the site is
+ * This figures out the right URL to use, based on the project's .info file and
+ * the global defaults. Appends optional query arguments when the site is
  * configured to report usage stats.
  *
  * @param $project
  *   The array of project information from update_get_projects().
  * @param $site_key
- *   The anonymous site key hash (optional).
+ *   (optional) The anonymous site key hash. Defaults to an empty string.
+ *
+ * @return
+ *   The URL for fetching information about updates to the specified project.
  *
  * @see update_fetch_data()
  * @see _update_process_fetch_task()
@@ -293,10 +304,11 @@ function _update_build_fetch_url($project, $site_key = '') {
 }
 
 /**
- * Return the base of the URL to fetch available update data for a project.
+ * Returns the base of the URL to fetch available update data for a project.
  *
  * @param $project
  *   The array of project information from update_get_projects().
+ *
  * @return
  *   The base of the URL used for fetching available update data. This does
  *   not include the path elements to specify a particular project, version,
@@ -309,10 +321,10 @@ function _update_get_fetch_url_base($project) {
 }
 
 /**
- * Perform any notifications that should be done once cron fetches new data.
+ * Performs any notifications that should be done once cron fetches new data.
  *
- * This method checks the status of the site using the new data and depending
- * on the configuration of the site, notifies administrators via email if there
+ * This method checks the status of the site using the new data and, depending
+ * on the configuration of the site, notifies administrators via e-mail if there
  * are new releases or missing security updates.
  *
  * @see update_requirements()
@@ -340,14 +352,19 @@ function _update_cron_notify() {
         else {
           $target_language = $default_language;
         }
-        drupal_mail('update', 'status_notify', $target, $target_language, $params);
+        $message = drupal_mail('update', 'status_notify', $target, $target_language, $params);
+        // Track when the last mail was successfully sent to avoid sending
+        // too many e-mails.
+        if ($message['result']) {
+          variable_set('update_last_email_notification', REQUEST_TIME);
+        }
       }
     }
   }
 }
 
 /**
- * Parse the XML of the Drupal release history info files.
+ * Parses the XML of the Drupal release history info files.
  *
  * @param $raw_xml
  *   A raw XML string of available release data for a given project.
diff --git a/modules/update/update.info b/modules/update/update.info
index c60e62255..2068f46cc 100644
--- a/modules/update/update.info
+++ b/modules/update/update.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = update.test
 configure = admin/reports/updates/settings
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/update/update.install b/modules/update/update.install
index 70fb6c328..baf49538e 100644
--- a/modules/update/update.install
+++ b/modules/update/update.install
@@ -2,26 +2,25 @@
 
 /**
  * @file
- * Install, update and uninstall functions for the update module.
+ * Install, update, and uninstall functions for the Update Manager module.
  */
 
 /**
  * Implements hook_requirements().
  *
  * @return
- *   An array describing the status of the site regarding available updates.
- *   If there is no update data, only one record will be returned, indicating
- *   that the status of core can't be determined. If data is available, there
- *   will be two records: one for core, and another for all of contrib
- *   (assuming there are any contributed modules or themes enabled on the
- *   site). In addition to the fields expected by hook_requirements ('value',
- *   'severity', and optionally 'description'), this array will contain a
- *   'reason' attribute, which is an integer constant to indicate why the
- *   given status is being returned (UPDATE_NOT_SECURE, UPDATE_NOT_CURRENT, or
- *   UPDATE_UNKNOWN). This is used for generating the appropriate e-mail
- *   notification messages during update_cron(), and might be useful for other
- *   modules that invoke update_requirements() to find out if the site is up
- *   to date or not.
+ *   An array describing the status of the site regarding available updates. If
+ *   there is no update data, only one record will be returned, indicating that
+ *   the status of core can't be determined. If data is available, there will be
+ *   two records: one for core, and another for all of contrib (assuming there
+ *   are any contributed modules or themes enabled on the site). In addition to
+ *   the fields expected by hook_requirements ('value', 'severity', and
+ *   optionally 'description'), this array will contain a 'reason' attribute,
+ *   which is an integer constant to indicate why the given status is being
+ *   returned (UPDATE_NOT_SECURE, UPDATE_NOT_CURRENT, or UPDATE_UNKNOWN). This
+ *   is used for generating the appropriate e-mail notification messages during
+ *   update_cron(), and might be useful for other modules that invoke
+ *   update_requirements() to find out if the site is up to date or not.
  *
  * @see _update_message_text()
  * @see _update_cron_notify()
@@ -83,6 +82,7 @@ function update_uninstall() {
     'update_check_frequency',
     'update_fetch_url',
     'update_last_check',
+    'update_last_email_notification',
     'update_notification_threshold',
     'update_notify_emails',
     'update_max_fetch_attempts',
@@ -96,19 +96,19 @@ function update_uninstall() {
 }
 
 /**
- * Private helper method to fill in the requirements array.
+ * Fills in the requirements array.
  *
  * This is shared for both core and contrib to generate the right elements in
  * the array for hook_requirements().
  *
  * @param $project
- *  Array of information about the project we're testing as returned by
- *  update_calculate_project_data().
+ *   Array of information about the project we're testing as returned by
+ *   update_calculate_project_data().
  * @param $type
- *  What kind of project is this ('core' or 'contrib').
+ *   What kind of project this is ('core' or 'contrib').
  *
  * @return
- *  An array to be included in the nested $requirements array.
+ *   An array to be included in the nested $requirements array.
  *
  * @see hook_requirements()
  * @see update_requirements()
@@ -186,5 +186,5 @@ function update_update_7001() {
 }
 
 /**
- * @} End of "addtogroup updates-6.x-to-7.x"
+ * @} End of "addtogroup updates-6.x-to-7.x".
  */
diff --git a/modules/update/update.manager.inc b/modules/update/update.manager.inc
index d9fd86ff2..85b587de2 100644
--- a/modules/update/update.manager.inc
+++ b/modules/update/update.manager.inc
@@ -2,7 +2,8 @@
 
 /**
  * @file
- * Administrative screens and processing functions for the update manager.
+ * Administrative screens and processing functions of the Update Manager module.
+ *
  * This allows site administrators with the 'administer software updates'
  * permission to either upgrade existing projects, or download and install new
  * ones, so long as the killswitch setting ('allow_authorize_operations') is
@@ -11,51 +12,52 @@
  * To install new code, the administrator is prompted for either the URL of an
  * archive file, or to directly upload the archive file. The archive is loaded
  * into a temporary location, extracted, and verified. If everything is
- * successful, the user is redirected to authorize.php to type in their file
- * transfer credentials and authorize the installation to proceed with
- * elevated privileges, such that the extracted files can be copied out of the
- * temporary location and into the live web root.
+ * successful, the user is redirected to authorize.php to type in file transfer
+ * credentials and authorize the installation to proceed with elevated
+ * privileges, such that the extracted files can be copied out of the temporary
+ * location and into the live web root.
  *
  * Updating existing code is a more elaborate process. The first step is a
- * selection form where the user is presented with a table of installed
- * projects that are missing newer releases. The user selects which projects
- * they wish to upgrade, and presses the "Download updates" button to
- * continue. This sets up a batch to fetch all the selected releases, and
- * redirects to admin/update/download to display the batch progress bar as it
- * runs. Each batch operation is responsible for downloading a single file,
- * extracting the archive, and verifying the contents. If there are any
- * errors, the user is redirected back to the first page with the error
- * messages. If all downloads were extacted and verified, the user is instead
- * redirected to admin/update/ready, a landing page which reminds them to
- * backup their database and asks if they want to put the site offline during
- * the upgrade. Once the user presses the "Install updates" button, they are
- * redirected to authorize.php to supply their web root file access
- * credentials. The authorized operation (which lives in update.authorize.inc)
- * sets up a batch to copy each extracted update from the temporary location
- * into the live web root.
+ * selection form where the user is presented with a table of installed projects
+ * that are missing newer releases. The user selects which projects they wish to
+ * update, and presses the "Download updates" button to continue. This sets up a
+ * batch to fetch all the selected releases, and redirects to
+ * admin/update/download to display the batch progress bar as it runs. Each
+ * batch operation is responsible for downloading a single file, extracting the
+ * archive, and verifying the contents. If there are any errors, the user is
+ * redirected back to the first page with the error messages. If all downloads
+ * were extacted and verified, the user is instead redirected to
+ * admin/update/ready, a landing page which reminds them to backup their
+ * database and asks if they want to put the site offline during the update.
+ * Once the user presses the "Install updates" button, they are redirected to
+ * authorize.php to supply their web root file access credentials. The
+ * authorized operation (which lives in update.authorize.inc) sets up a batch to
+ * copy each extracted update from the temporary location into the live web
+ * root.
  */
 
 /**
- * @defgroup update_manager_update Update manager: update
+ * @defgroup update_manager_update Update Manager module: update
  * @{
- * Update manager for updating existing code.
+ * Update Manager module functionality for updating existing code.
  *
  * Provides a user interface to update existing code.
  */
 
 /**
- * Build the form for the update manager page to update existing projects.
+ * Form constructor for the update form of the Update Manager module.
  *
  * This presents a table with all projects that have available updates with
  * checkboxes to select which ones to upgrade.
  *
- * @param $form
- * @param $form_state
  * @param $context
- *   String representing the context from which we're trying to update, can be:
- *   'module', 'theme' or 'report'.
- * @return
- *   The form array for selecting which projects to update.
+ *   String representing the context from which we're trying to update.
+ *   Allowed values are 'module', 'theme', and 'report'.
+ *
+ * @see update_manager_update_form_validate()
+ * @see update_manager_update_form_submit()
+ * @see update_menu()
+ * @ingroup forms
  */
 function update_manager_update_form($form, $form_state = array(), $context) {
   if (!_update_manager_check_backends($form, 'update')) {
@@ -263,7 +265,7 @@ function update_manager_update_form($form, $form_state = array(), $context) {
 }
 
 /**
- * Returns HTML for the first page in the update manager wizard to select projects.
+ * Returns HTML for the first page in the process of updating projects.
  *
  * @param $variables
  *   An associative array containing:
@@ -280,7 +282,11 @@ function theme_update_manager_update_form($variables) {
 }
 
 /**
- * Validation callback to ensure that at least one project is selected.
+ * Form validation handler for update_manager_update_form().
+ *
+ * Ensures that at least one project is selected.
+ *
+ * @see update_manager_update_form_submit()
  */
 function update_manager_update_form_validate($form, &$form_state) {
   if (!empty($form_state['values']['projects'])) {
@@ -295,11 +301,11 @@ function update_manager_update_form_validate($form, &$form_state) {
 }
 
 /**
- * Submit function for the main update form.
+ * Form submission handler for update_manager_update_form().
  *
- * This sets up a batch to download, extract and verify the selected releases
+ * Sets up a batch that downloads, extracts, and verifies the selected releases.
  *
- * @see update_manager_update_form()
+ * @see update_manager_update_form_validate()
  */
 function update_manager_update_form_submit($form, &$form_state) {
   $projects = array();
@@ -329,7 +335,12 @@ function update_manager_update_form_submit($form, &$form_state) {
 }
 
 /**
- * Batch callback invoked when the download batch is completed.
+ * Batch callback: Performs actions when the download batch is completed.
+ *
+ * @param $success
+ *   TRUE if the batch operation was successful, FALSE if there were errors.
+ * @param $results
+ *   An associative array of results from the batch operation.
  */
 function update_manager_download_batch_finished($success, $results) {
   if (!empty($results['errors'])) {
@@ -352,15 +363,21 @@ function update_manager_download_batch_finished($success, $results) {
 }
 
 /**
+ * Form constructor for the update ready form.
+ *
  * Build the form when the site is ready to update (after downloading).
  *
  * This form is an intermediary step in the automated update workflow. It is
- * presented to the site administrator after all the required updates have
- * been downloaded and verified. The point of this page is to encourage the
- * user to backup their site, gives them the opportunity to put the site
- * offline, and then asks them to confirm that the update should continue.
- * After this step, the user is redirected to authorize.php to enter their
- * file transfer credentials and attempt to complete the update.
+ * presented to the site administrator after all the required updates have been
+ * downloaded and verified. The point of this page is to encourage the user to
+ * backup their site, give them the opportunity to put the site offline, and
+ * then ask them to confirm that the update should continue. After this step,
+ * the user is redirected to authorize.php to enter their file transfer
+ * credentials and attempt to complete the update.
+ *
+ * @see update_manager_update_ready_form_submit()
+ * @see update_menu()
+ * @ingroup forms
  */
 function update_manager_update_ready_form($form, &$form_state) {
   if (!_update_manager_check_backends($form, 'update')) {
@@ -389,13 +406,13 @@ function update_manager_update_ready_form($form, &$form_state) {
 }
 
 /**
- * Submit handler for the form to confirm that an update should continue.
+ * Form submission handler for update_manager_update_ready_form().
  *
  * If the site administrator requested that the site is put offline during the
- * update, do so now. Otherwise, pull information about all the required
- * updates out of the SESSION, figure out what Updater class is needed for
- * each one, generate an array of update operations to perform, and hand it
- * all off to system_authorized_init(), then redirect to authorize.php.
+ * update, do so now. Otherwise, pull information about all the required updates
+ * out of the SESSION, figure out what Drupal\Core\Updater\Updater class is
+ * needed for each one, generate an array of update operations to perform, and
+ * hand it all off to system_authorized_init(), then redirect to authorize.php.
  *
  * @see update_authorize_run_update()
  * @see system_authorized_init()
@@ -454,26 +471,27 @@ function update_manager_update_ready_form_submit($form, &$form_state) {
  */
 
 /**
- * @defgroup update_manager_install Update manager: install
+ * @defgroup update_manager_install Update Manager module: install
  * @{
- * Update manager for installing new code.
+ * Update Manager module functionality for installing new code.
  *
  * Provides a user interface to install new code.
  */
 
 /**
- * Build the form for the update manager page to install new projects.
+ * Form constructor for the install form of the Update Manager module.
  *
  * This presents a place to enter a URL or upload an archive file to use to
  * install a new module or theme.
  *
- * @param $form
- * @param $form_state
  * @param $context
- *   String representing the context from which we're trying to install, can
- *   be: 'module', 'theme' or 'report'.
- * @return
- *   The form array for selecting which project to install.
+ *   String representing the context from which we're trying to install.
+ *   Allowed values are 'module', 'theme', and 'report'.
+ *
+ * @see update_manager_install_form_validate()
+ * @see update_manager_install_form_submit()
+ * @see update_menu()
+ * @ingroup forms
  */
 function update_manager_install_form($form, &$form_state, $context) {
   if (!_update_manager_check_backends($form, 'install')) {
@@ -524,11 +542,11 @@ function update_manager_install_form($form, &$form_state, $context) {
  * @param array $form
  *   Reference to the form array we're building.
  * @param string $operation
- *   The Update manager operation we're in the middle of. Can be either
- *   'update' or 'install'. Use to provide operation-specific interface text.
+ *   The update manager operation we're in the middle of. Can be either 'update'
+ *   or 'install'. Use to provide operation-specific interface text.
  *
  * @return
- *   TRUE if the Update manager should continue to the next step in the
+ *   TRUE if the update manager should continue to the next step in the
  *   workflow, or FALSE if we've hit a fatal configuration and must halt the
  *   workflow.
  */
@@ -586,7 +604,9 @@ function _update_manager_check_backends(&$form, $operation) {
 }
 
 /**
- * Validate the form for installing a new project via the update manager.
+ * Form validation handler for update_manager_install_form().
+ *
+ * @see update_manager_install_form_submit()
  */
 function update_manager_install_form_validate($form, &$form_state) {
   if (!($form_state['values']['project_url'] XOR !empty($_FILES['files']['name']['project_upload']))) {
@@ -601,7 +621,7 @@ function update_manager_install_form_validate($form, &$form_state) {
 }
 
 /**
- * Handle form submission when installing new projects via the update manager.
+ * Form submission handler for update_manager_install_form().
  *
  * Either downloads the file specified in the URL to a temporary cache, or
  * uploads the file attached to the form, then attempts to extract the archive
@@ -611,6 +631,7 @@ function update_manager_install_form_validate($form, &$form_state) {
  * via authorize.php which will copy the extracted files from the temporary
  * location into the live site.
  *
+ * @see update_manager_install_form_validate()
  * @see update_authorize_run_install()
  * @see system_authorized_init()
  * @see system_authorized_get_url()
@@ -728,26 +749,26 @@ function update_manager_install_form_submit($form, &$form_state) {
  */
 
 /**
- * @defgroup update_manager_file Update manager: file management
+ * @defgroup update_manager_file Update Manager module: file management
  * @{
- * Update manager file management functions.
+ * Update Manager module file management functions.
  *
- * These functions are used by the update manager to copy, extract
- * and verify archive files.
+ * These functions are used by the update manager to copy, extract, and verify
+ * archive files.
  */
 
 /**
- * Unpack a downloaded archive file.
+ * Unpacks a downloaded archive file.
  *
- * @param string $project
- *   The short name of the project to download.
  * @param string $file
  *   The filename of the archive you wish to extract.
  * @param string $directory
  *   The directory you wish to extract the archive into.
+ *
  * @return Archiver
  *   The Archiver object used to extract the archive.
- * @throws Exception on failure.
+ *
+ * @throws Exception
  */
 function update_manager_archive_extract($file, $directory) {
   $archiver = archiver_get_archiver($file);
@@ -775,7 +796,7 @@ function update_manager_archive_extract($file, $directory) {
 }
 
 /**
- * Verify an archive after it has been downloaded and extracted.
+ * Verifies an archive after it has been downloaded and extracted.
  *
  * This function is responsible for invoking hook_verify_update_archive().
  *
@@ -787,18 +808,17 @@ function update_manager_archive_extract($file, $directory) {
  *   The directory that the archive was extracted into.
  *
  * @return array
- *   An array of error messages to display if the archive was invalid. If
- *   there are no errors, it will be an empty array.
- *
+ *   An array of error messages to display if the archive was invalid. If there
+ *   are no errors, it will be an empty array.
  */
 function update_manager_archive_verify($project, $archive_file, $directory) {
   return module_invoke_all('verify_update_archive', $project, $archive_file, $directory);
 }
 
 /**
- * Copies a file from $url to the temporary directory for updates.
+ * Copies a file from the specified URL to the temporary directory for updates.
  *
- * If the file has already been downloaded, returns the the local path.
+ * Returns the local path if the file has already been downloaded.
  *
  * @param $url
  *   The URL of the file on the server.
@@ -827,18 +847,18 @@ function update_manager_file_get($url) {
 }
 
 /**
- * Batch operation: download, unpack, and verify a project.
+ * Batch callback: Downloads, unpacks, and verifies a project.
  *
- * This function assumes that the provided URL points to a file archive of
- * some sort. The URL can have any scheme that we have a file stream wrapper
- * to support. The file is downloaded to a local cache.
+ * This function assumes that the provided URL points to a file archive of some
+ * sort. The URL can have any scheme that we have a file stream wrapper to
+ * support. The file is downloaded to a local cache.
  *
  * @param string $project
  *   The short name of the project to download.
  * @param string $url
  *   The URL to download a specific project release archive file.
  * @param array $context
- *   Reference to an array used for BatchAPI storage.
+ *   Reference to an array used for Batch API storage.
  *
  * @see update_manager_download_page()
  */
@@ -887,8 +907,8 @@ function update_manager_batch_project_get($project, $url, &$context) {
  * Determines if file transfers will be performed locally.
  *
  * If the server is configured such that webserver-created files have the same
- * owner as the configuration directory (e.g. sites/default) where new code
- * will eventually be installed, the Update manager can transfer files entirely
+ * owner as the configuration directory (e.g., sites/default) where new code
+ * will eventually be installed, the update manager can transfer files entirely
  * locally, without changing their ownership (in other words, without prompting
  * the user for FTP, SSH or other credentials).
  *
diff --git a/modules/update/update.module b/modules/update/update.module
index bf8b06848..85c0968d5 100644
--- a/modules/update/update.module
+++ b/modules/update/update.module
@@ -2,10 +2,13 @@
 
 /**
  * @file
- * The "Update status" module checks for available updates of Drupal core and
- * any installed contributed modules and themes. It warns site administrators
- * if newer releases are available via the system status report
- * (admin/reports/status), the module and theme pages, and optionally via email.
+ * Handles updates of Drupal core and contributed projects.
+ *
+ * The module checks for available updates of Drupal core and any installed
+ * contributed modules and themes. It warns site administrators if newer
+ * releases are available via the system status report (admin/reports/status),
+ * the module and theme pages, and optionally via e-mail. It also provides the
+ * ability to install contributed modules and themes via an user interface.
  */
 
 /**
@@ -246,11 +249,14 @@ function update_menu() {
 }
 
 /**
- * Determine if the current user can access the updater menu items.
+ * Access callback: Resolves if the current user can access updater menu items.
+ *
+ * It both enforces the 'administer software updates' permission and the global
+ * kill switch for the authorize.php script.
  *
- * This is used as a menu system access callback. It both enforces the
- * 'administer software updates' permission and the global killswitch for the
- * authorize.php script.
+ * @return
+ *   TRUE if the current user can access the updater menu items; FALSE
+ *   otherwise.
  *
  * @see update_menu()
  */
@@ -294,13 +300,18 @@ function update_cron() {
     // configured notifications about the new status.
     update_refresh();
     update_fetch_data();
-    _update_cron_notify();
   }
   else {
     // Otherwise, see if any individual projects are now stale or still
     // missing data, and if so, try to fetch the data.
     update_get_available(TRUE);
   }
+  if ((REQUEST_TIME - variable_get('update_last_email_notification', 0)) > $interval) {
+    // If configured time between notifications elapsed, send email about
+    // updates possibly available.
+    module_load_include('inc', 'update', 'update.fetch');
+    _update_cron_notify();
+  }
 
   // Clear garbage from disk.
   update_clear_update_disk_cache();
@@ -327,10 +338,10 @@ function update_themes_disabled($themes) {
 }
 
 /**
- * Implements hook_form_FORM_ID_alter().
+ * Implements hook_form_FORM_ID_alter() for system_modules().
  *
- * Adds a submit handler to the system modules form, so that if a site admin
- * saves the form, we invalidate the cache of available updates.
+ * Adds a form submission handler to the system modules form, so that if a site
+ * admin saves the form, we invalidate the cache of available updates.
  *
  * @see _update_cache_clear()
  */
@@ -339,7 +350,9 @@ function update_form_system_modules_alter(&$form, $form_state) {
 }
 
 /**
- * Helper function for use as a form submit callback.
+ * Form submission handler for system_modules().
+ *
+ * @see update_form_system_modules_alter()
  */
 function update_cache_clear_submit($form, &$form_state) {
   // Clear all update module caches.
@@ -347,7 +360,7 @@ function update_cache_clear_submit($form, &$form_state) {
 }
 
 /**
- * Prints a warning message when there is no data about available updates.
+ * Returns a warning message when there is no data about available updates.
  */
 function _update_no_data() {
   $destination = drupal_get_destination();
@@ -358,20 +371,22 @@ function _update_no_data() {
 }
 
 /**
- * Internal helper to try to get the update information from the cache
- * if possible, and to refresh the cache when necessary.
+ * Tries to get update information from cache and refreshes it when necessary.
  *
  * In addition to checking the cache lifetime, this function also ensures that
  * there are no .info files for enabled modules or themes that have a newer
  * modification timestamp than the last time we checked for available update
- * data. If any .info file was modified, it almost certainly means a new
- * version of something was installed. Without fresh available update data,
- * the logic in update_calculate_project_data() will be wrong and produce
- * confusing, bogus results.
+ * data. If any .info file was modified, it almost certainly means a new version
+ * of something was installed. Without fresh available update data, the logic in
+ * update_calculate_project_data() will be wrong and produce confusing, bogus
+ * results.
  *
  * @param $refresh
- *   Boolean to indicate if this method should refresh the cache automatically
- *   if there's no data.
+ *   (optional) Boolean to indicate if this method should refresh the cache
+ *   automatically if there's no data. Defaults to FALSE.
+ *
+ * @return
+ *   Array of data about available releases, keyed by project shortname.
  *
  * @see update_refresh()
  * @see update_get_projects()
@@ -428,7 +443,11 @@ function update_get_available($refresh = FALSE) {
 }
 
 /**
- * Wrapper to load the include file and then create a new fetch task.
+ * Creates a new fetch task after loading the necessary include file.
+ *
+ * @param $project
+ *   Associative array of information about a project. See update_get_projects()
+ *   for the keys used.
  *
  * @see _update_create_fetch_task()
  */
@@ -438,7 +457,7 @@ function update_create_fetch_task($project) {
 }
 
 /**
- * Wrapper to load the include file and then refresh the release data.
+ * Refreshes the release data after loading the necessary include file.
  *
  * @see _update_refresh()
  */
@@ -448,7 +467,9 @@ function update_refresh() {
 }
 
 /**
- * Wrapper to load the include file and then attempt to fetch update data.
+ * Attempts to fetch update data after loading the necessary include file.
+ *
+ * @see _update_fetch_data()
  */
 function update_fetch_data() {
   module_load_include('inc', 'update', 'update.fetch');
@@ -456,7 +477,7 @@ function update_fetch_data() {
 }
 
 /**
- * Return all currently cached data about available releases for all projects.
+ * Returns all currently cached data about available releases for all projects.
  *
  * @return
  *   Array of data about available releases, keyed by project shortname.
@@ -481,17 +502,17 @@ function _update_get_cached_available_releases() {
 /**
  * Implements hook_mail().
  *
- * Constructs the email notification message when the site is out of date.
+ * Constructs the e-mail notification message when the site is out of date.
  *
  * @param $key
  *   Unique key to indicate what message to build, always 'status_notify'.
  * @param $message
  *   Reference to the message array being built.
  * @param $params
- *   Array of parameters to indicate what kind of text to include in the
- *   message body. This is a keyed array of message type ('core' or 'contrib')
- *   as the keys, and the status reason constant (UPDATE_NOT_SECURE, etc) for
- *   the values.
+ *   Array of parameters to indicate what kind of text to include in the message
+ *   body. This is a keyed array of message type ('core' or 'contrib') as the
+ *   keys, and the status reason constant (UPDATE_NOT_SECURE, etc) for the
+ *   values.
  *
  * @see drupal_mail()
  * @see _update_cron_notify()
@@ -518,22 +539,23 @@ function update_mail($key, &$message, $params) {
 }
 
 /**
- * Helper function to return the appropriate message text when the site is out
- * of date or missing a security update.
+ * Returns the appropriate message text when site is out of date or not secure.
  *
  * These error messages are shared by both update_requirements() for the
  * site-wide status report at admin/reports/status and in the body of the
- * notification emails generated by update_cron().
+ * notification e-mail messages generated by update_cron().
  *
  * @param $msg_type
- *   String to indicate what kind of message to generate. Can be either
- *   'core' or 'contrib'.
+ *   String to indicate what kind of message to generate. Can be either 'core'
+ *   or 'contrib'.
  * @param $msg_reason
  *   Integer constant specifying why message is generated.
  * @param $report_link
- *   Boolean that controls if a link to the updates report should be added.
+ *   (optional) Boolean that controls if a link to the updates report should be
+ *   added. Defaults to FALSE.
  * @param $language
- *   An optional language object to use.
+ *   (optional) A language object to use. Defaults to NULL.
+ *
  * @return
  *   The properly translated error message for the given key.
  */
@@ -603,10 +625,9 @@ function _update_message_text($msg_type, $msg_reason, $report_link = FALSE, $lan
 }
 
 /**
- * Private sort function to order projects based on their status.
+ * Orders projects based on their status.
  *
- * @see update_requirements()
- * @see uasort()
+ * Callback for uasort() within update_requirements().
  */
 function _update_project_status_sort($a, $b) {
   // The status constants are numerically in the right order, so we can
@@ -621,17 +642,16 @@ function _update_project_status_sort($a, $b) {
 /**
  * Returns HTML for the last time we checked for update data.
  *
- * In addition to properly formating the given timestamp, this function also
+ * In addition to properly formatting the given timestamp, this function also
  * provides a "Check manually" link that refreshes the available update and
  * redirects back to the same page.
  *
  * @param $variables
  *   An associative array containing:
- *   - 'last': The timestamp when the site last checked for available updates.
+ *   - last: The timestamp when the site last checked for available updates.
  *
  * @see theme_update_report()
  * @see theme_update_available_updates_form()
- *
  * @ingroup themeable
  */
 function theme_update_last_check($variables) {
@@ -647,7 +667,7 @@ function theme_update_last_check($variables) {
  * Implements hook_verify_update_archive().
  *
  * First, we ensure that the archive isn't a copy of Drupal core, which the
- * Update manager does not yet support. @see http://drupal.org/node/606592
+ * update manager does not yet support. See http://drupal.org/node/606592
  *
  * Then, we make sure that at least one module included in the archive file has
  * an .info file which claims that the code is compatible with the current
@@ -719,19 +739,19 @@ function update_verify_update_archive($project, $archive_file, $directory) {
  * cleared when we're populating it after successfully fetching new available
  * update data. Usage of the core cache API results in all sorts of potential
  * problems that would result in attempting to fetch available update data all
- * the time, including if a site has a "minimum cache lifetime" (which is both
- * a minimum and a maximum) defined, or if a site uses memcache or another
- * plug-able cache system that assumes volatile caches.
- *
- * Update module still uses the {cache_update} table, but instead of using
- * cache_set(), cache_get(), and cache_clear_all(), there are private helper
- * functions that implement these same basic tasks but ensure that the cache
- * is not prematurely cleared, and that the data is always stored in the
+ * the time, including if a site has a "minimum cache lifetime" (which is both a
+ * minimum and a maximum) defined, or if a site uses memcache or another
+ * pluggable cache system that assumes volatile caches.
+ *
+ * The Update Manager module still uses the {cache_update} table, but instead of
+ * using cache_set(), cache_get(), and cache_clear_all(), there are private
+ * helper functions that implement these same basic tasks but ensure that the
+ * cache is not prematurely cleared, and that the data is always stored in the
  * database, even if memcache or another cache backend is in use.
  */
 
 /**
- * Store data in the private update status cache table.
+ * Stores data in the private update status cache table.
  *
  * @param $cid
  *   The cache ID to save the data with.
@@ -743,6 +763,8 @@ function update_verify_update_archive($project, $archive_file, $directory) {
  *     by explicitly using _update_cache_clear().
  *   - A Unix timestamp: Indicates that the item should be kept at least until
  *     the given time, after which it will be invalidated.
+ *
+ * @see _update_cache_get()
  */
 function _update_cache_set($cid, $data, $expire) {
   $fields = array(
@@ -764,12 +786,15 @@ function _update_cache_set($cid, $data, $expire) {
 }
 
 /**
- * Retrieve data from the private update status cache table.
+ * Retrieves data from the private update status cache table.
  *
  * @param $cid
  *   The cache ID to retrieve.
+ *
  * @return
- *   The data for the given cache ID, or NULL if the ID was not found.
+ *   An array of data for the given cache ID, or NULL if the ID was not found.
+ *
+ * @see _update_cache_set()
  */
 function _update_cache_get($cid) {
   $cache = db_query("SELECT data, created, expire, serialized FROM {cache_update} WHERE cid = :cid", array(':cid' => $cid))->fetchObject();
@@ -782,7 +807,10 @@ function _update_cache_get($cid) {
 }
 
 /**
- * Return an array of cache items with a given cache ID prefix.
+ * Returns an array of cache items with a given cache ID prefix.
+ *
+ * @param string $cid_prefix
+ *   The cache ID prefix.
  *
  * @return
  *   Associative array of cache items, keyed by cache ID.
@@ -808,12 +836,12 @@ function _update_get_cache_multiple($cid_prefix) {
  * Invalidates cached data relating to update status.
  *
  * @param $cid
- *   Optional cache ID of the record to clear from the private update module
- *   cache. If empty, all records will be cleared from the table except
- *   fetch tasks.
+ *   (optional) Cache ID of the record to clear from the private update module
+ *   cache. If empty, all records will be cleared from the table except fetch
+ *   tasks. Defaults to NULL.
  * @param $wildcard
- *   If $wildcard is TRUE, cache IDs starting with $cid are deleted in
- *   addition to the exact cache ID specified by $cid.
+ *   (optional) If TRUE, cache IDs starting with $cid are deleted in addition to
+ *   the exact cache ID specified by $cid. Defaults to FALSE.
  */
 function _update_cache_clear($cid = NULL, $wildcard = FALSE) {
   if (empty($cid)) {
@@ -838,18 +866,18 @@ function _update_cache_clear($cid = NULL, $wildcard = FALSE) {
 /**
  * Implements hook_flush_caches().
  *
- * Called from update.php (among others) to flush the caches.
- * Since we're running update.php, we are likely to install a new version of
- * something, in which case, we want to check for available update data again.
- * However, because we have our own caching system, we need to directly clear
- * the database table ourselves at this point and return nothing, for example,
- * on sites that use memcache where cache_clear_all() won't know how to purge
- * this data.
+ * Called from update.php (among others) to flush the caches. Since we're
+ * running update.php, we are likely to install a new version of something, in
+ * which case, we want to check for available update data again. However,
+ * because we have our own caching system, we need to directly clear the
+ * database table ourselves at this point and return nothing, for example, on
+ * sites that use memcache where cache_clear_all() won't know how to purge this
+ * data.
  *
- * However, we only want to do this from update.php, since otherwise, we'd
- * lose all the available update data on every cron run. So, we specifically
- * check if the site is in MAINTENANCE_MODE == 'update' (which indicates
- * update.php is running, not update module... alas for overloaded names).
+ * However, we only want to do this from update.php, since otherwise, we'd lose
+ * all the available update data on every cron run. So, we specifically check if
+ * the site is in MAINTENANCE_MODE == 'update' (which indicates update.php is
+ * running, not update module... alas for overloaded names).
  */
 function update_flush_caches() {
   if (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'update') {
@@ -863,7 +891,7 @@ function update_flush_caches() {
  */
 
 /**
- * Return a short unique identifier for this Drupal installation.
+ * Returns a short unique identifier for this Drupal installation.
  *
  * @return
  *   An eight character string uniquely identifying this Drupal installation.
@@ -877,14 +905,15 @@ function _update_manager_unique_identifier() {
 }
 
 /**
- * Return the directory where update archive files should be extracted.
+ * Returns the directory where update archive files should be extracted.
  *
  * @param $create
- *   If TRUE, attempt to create the directory if it does not already exist.
+ *   (optional) Whether to attempt to create the directory if it does not
+ *   already exist. Defaults to TRUE.
  *
  * @return
- *   The full path to the temporary directory where update file archives
- *   should be extracted.
+ *   The full path to the temporary directory where update file archives should
+ *   be extracted.
  */
 function _update_manager_extract_directory($create = TRUE) {
   $directory = &drupal_static(__FUNCTION__, '');
@@ -898,14 +927,15 @@ function _update_manager_extract_directory($create = TRUE) {
 }
 
 /**
- * Return the directory where update archive files should be cached.
+ * Returns the directory where update archive files should be cached.
  *
  * @param $create
- *   If TRUE, attempt to create the directory if it does not already exist.
+ *   (optional) Whether to attempt to create the directory if it does not
+ *   already exist. Defaults to TRUE.
  *
  * @return
- *   The full path to the temporary directory where update file archives
- *   should be cached.
+ *   The full path to the temporary directory where update file archives should
+ *   be cached.
  */
 function _update_manager_cache_directory($create = TRUE) {
   $directory = &drupal_static(__FUNCTION__, '');
@@ -919,7 +949,7 @@ function _update_manager_cache_directory($create = TRUE) {
 }
 
 /**
- * Clear the temporary files and directories based on file age from disk.
+ * Clears the temporary files and directories based on file age from disk.
  */
 function update_clear_update_disk_cache() {
   // List of update module cache directories. Do not create the directories if
@@ -936,19 +966,19 @@ function update_clear_update_disk_cache() {
 }
 
 /**
- * Delete stale files and directories from the Update manager disk cache.
+ * Deletes stale files and directories from the update manager disk cache.
  *
- * Files and directories older than 6 hours and development snapshots older
- * than 5 minutes are considered stale. We only cache development snapshots
- * for 5 minutes since otherwise updated snapshots might not be downloaded as
+ * Files and directories older than 6 hours and development snapshots older than
+ * 5 minutes are considered stale. We only cache development snapshots for 5
+ * minutes since otherwise updated snapshots might not be downloaded as
  * expected.
  *
  * When checking file ages, we need to use the ctime, not the mtime
- * (modification time) since many (all?) tar implementations go out of their
- * way to set the mtime on the files they create to the timestamps recorded
- * in the tarball. We want to see the last time the file was changed on disk,
- * which is left alone by tar and correctly set to the time the archive file
- * was unpacked.
+ * (modification time) since many (all?) tar implementations go out of their way
+ * to set the mtime on the files they create to the timestamps recorded in the
+ * tarball. We want to see the last time the file was changed on disk, which is
+ * left alone by tar and correctly set to the time the archive file was
+ * unpacked.
  *
  * @param $path
  *   A string containing a file path or (streamwrapper) URI.
diff --git a/modules/update/update.report.inc b/modules/update/update.report.inc
index 3f5933acb..f256575fa 100644
--- a/modules/update/update.report.inc
+++ b/modules/update/update.report.inc
@@ -6,7 +6,9 @@
  */
 
 /**
- * Menu callback. Generate a page about the update status of projects.
+ * Page callback: Generates a page about the update status of projects.
+ *
+ * @see update_menu()
  */
 function update_status() {
   if ($available = update_get_available(TRUE)) {
@@ -257,6 +259,7 @@ function theme_update_report($variables) {
  *   - status: The integer code for a project's current update status.
  *
  * @see update_calculate_project_data()
+ * @ingroup themeable
  */
 function theme_update_status_label($variables) {
   switch ($variables['status']) {
diff --git a/modules/update/update.settings.inc b/modules/update/update.settings.inc
index 60ac3ca8e..5cd241498 100644
--- a/modules/update/update.settings.inc
+++ b/modules/update/update.settings.inc
@@ -6,7 +6,11 @@
  */
 
 /**
- * Form builder for the update settings tab.
+ * Form constructor for the update settings form.
+ *
+ * @see update_settings_validate()
+ * @see update_settings_submit()
+ * @ingroup forms
  */
 function update_settings($form) {
   $form['update_check_frequency'] = array(
@@ -57,9 +61,11 @@ function update_settings($form) {
 }
 
 /**
- * Validation callback for the settings form.
+ * Form validation handler for update_settings().
+ *
+ * Validates the e-mail addresses and ensures the field is formatted correctly.
  *
- * Validates the email addresses and ensures the field is formatted correctly.
+ * @see update_settings_submit()
  */
 function update_settings_validate($form, &$form_state) {
   if (!empty($form_state['values']['update_notify_emails'])) {
@@ -89,13 +95,15 @@ function update_settings_validate($form, &$form_state) {
 }
 
 /**
- * Submit handler for the settings tab.
+ * Form submission handler for update_settings().
+ *
+ * Also invalidates the cache of available updates if the "Check for updates of
+ * disabled modules and themes" setting is being changed. The available updates
+ * report needs to refetch available update data after this setting changes or
+ * it would show misleading things (e.g., listing the disabled projects on the
+ * site with the "No available releases found" warning).
  *
- * Also invalidates the cache of available updates if the "Check for updates
- * of disabled modules and themes" setting is being changed. The available
- * updates report need to refetch available update data after this setting
- * changes or it would show misleading things (e.g. listing the disabled
- * projects on the site with the "No available releases found" warning).
+ * @see update_settings_validate()
  */
 function update_settings_submit($form, $form_state) {
   $op = $form_state['values']['op'];
diff --git a/modules/update/update.test b/modules/update/update.test
index 8daa82155..e297194ae 100644
--- a/modules/update/update.test
+++ b/modules/update/update.test
@@ -2,38 +2,43 @@
 
 /**
  * @file
- * Tests for update.module.
+ * This file contains tests for the Update Manager module.
  *
- * This file contains tests for the update module. The overarching methodology
- * of these tests is we need to compare a given state of installed modules and
- * themes (e.g. version, project grouping, timestamps, etc) vs. a current
- * state of what the release history XML files we fetch say is available.  We
- * have dummy XML files (in the 'tests' subdirectory) that describe various
- * scenarios of what's available for different test projects, and we have
- * dummy .info file data (specified via hook_system_info_alter() in the
- * update_test helper module) describing what's currently installed.  Each
- * test case defines a set of projects to install, their current state (via
- * the 'update_test_system_info' variable) and the desired available update
- * data (via the 'update_test_xml_map' variable), and then performs a series
- * of assertions that the report matches our expectations given the specific
- * initial state and availability scenario.
+ * The overarching methodology of these tests is we need to compare a given
+ * state of installed modules and themes (e.g., version, project grouping,
+ * timestamps, etc) against a current state of what the release history XML
+ * files we fetch say is available. We have dummy XML files (in the
+ * modules/update/tests directory) that describe various scenarios of what's
+ * available for different test projects, and we have dummy .info file data
+ * (specified via hook_system_info_alter() in the update_test helper module)
+ * describing what's currently installed. Each test case defines a set of
+ * projects to install, their current state (via the 'update_test_system_info'
+ * variable) and the desired available update data (via the
+ * 'update_test_xml_map' variable), and then performs a series of assertions
+ * that the report matches our expectations given the specific initial state and
+ * availability scenario.
  */
 
 /**
- * Base class to define some shared functions used by all update tests.
+ * Defines some shared functions used by all update tests.
  */
 class UpdateTestHelper extends DrupalWebTestCase {
+
   /**
-   * Refresh the update status based on the desired available update scenario.
+   * Refreshes the update status based on the desired available update scenario.
    *
    * @param $xml_map
-   *   Array that maps project names to availability scenarios to fetch.
-   *   The key '#all' is used if a project-specific mapping is not defined.
+   *   Array that maps project names to availability scenarios to fetch. The key
+   *   '#all' is used if a project-specific mapping is not defined.
+   * @param $url
+   *   (optional) A string containing the URL to fetch update data from.
+   *   Defaults to 'update-test'.
    *
    * @see update_test_mock_page()
    */
   protected function refreshUpdateStatus($xml_map, $url = 'update-test') {
-    // Tell update module to fetch from the URL provided by update_test module.
+    // Tell the Update Manager module to fetch from the URL provided by
+    // update_test module.
     variable_set('update_fetch_url', url($url, array('absolute' => TRUE)));
     // Save the map for update_test_mock_page() to use.
     variable_set('update_test_xml_map', $xml_map);
@@ -42,7 +47,7 @@ class UpdateTestHelper extends DrupalWebTestCase {
   }
 
   /**
-   * Run a series of assertions that are applicable for all update statuses.
+   * Runs a series of assertions that are applicable to all update statuses.
    */
   protected function standardTests() {
     $this->assertRaw('<h3>' . t('Drupal core') . '</h3>');
@@ -52,12 +57,15 @@ class UpdateTestHelper extends DrupalWebTestCase {
 
 }
 
+/**
+ * Tests behavior related to discovering and listing updates to Drupal core.
+ */
 class UpdateCoreTestCase extends UpdateTestHelper {
 
   public static function getInfo() {
     return array(
       'name' => 'Update core functionality',
-      'description' => 'Tests the update module through a series of functional tests using mock XML data.',
+      'description' => 'Tests the Update Manager module through a series of functional tests using mock XML data.',
       'group' => 'Update',
     );
   }
@@ -69,7 +77,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
   }
 
   /**
-   * Tests the update module when no updates are available.
+   * Tests the Update Manager module when no updates are available.
    */
   function testNoUpdatesAvailable() {
     $this->setSystemInfo7_0();
@@ -81,7 +89,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
   }
 
   /**
-   * Tests the update module when one normal update ("7.1") is available.
+   * Tests the Update Manager module when one normal update is available.
    */
   function testNormalUpdateAvailable() {
     $this->setSystemInfo7_0();
@@ -96,7 +104,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
   }
 
   /**
-   * Tests the update module when a security update ("7.2") is available.
+   * Tests the Update Manager module when a security update is available.
    */
   function testSecurityUpdateAvailable() {
     $this->setSystemInfo7_0();
@@ -111,7 +119,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
   }
 
   /**
-   * Ensure proper results where there are date mismatches among modules.
+   * Ensures proper results where there are date mismatches among modules.
    */
   function testDatestampMismatch() {
     $system_info = array(
@@ -134,7 +142,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
   }
 
   /**
-   * Check that running cron updates the list of available updates.
+   * Checks that running cron updates the list of available updates.
    */
   function testModulePageRunCron() {
     $this->setSystemInfo7_0();
@@ -147,7 +155,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
   }
 
   /**
-   * Check the messages at admin/modules when the site is up to date.
+   * Checks the messages at admin/modules when the site is up to date.
    */
   function testModulePageUpToDate() {
     $this->setSystemInfo7_0();
@@ -164,7 +172,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
   }
 
   /**
-   * Check the messages at admin/modules when missing an update.
+   * Checks the messages at admin/modules when an update is missing.
    */
   function testModulePageRegularUpdate() {
     $this->setSystemInfo7_0();
@@ -181,7 +189,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
   }
 
   /**
-   * Check the messages at admin/modules when missing a security update.
+   * Checks the messages at admin/modules when a security update is missing.
    */
   function testModulePageSecurityUpdate() {
     $this->setSystemInfo7_0();
@@ -216,7 +224,7 @@ class UpdateCoreTestCase extends UpdateTestHelper {
   }
 
   /**
-   * Tests the update module when the update server returns 503 (Service unavailable) errors.
+   * Tests the Update Manager module when the update server returns 503 errors.
    */
   function testServiceUnavailable() {
     $this->refreshUpdateStatus(array(), '503-error');
@@ -252,6 +260,9 @@ class UpdateCoreTestCase extends UpdateTestHelper {
     $this->assertEqual($queue->numberOfItems(), 2, 'Queue contains two items');
   }
 
+  /**
+   * Sets the version to 7.0 when no project-specific mapping is defined.
+   */
   protected function setSystemInfo7_0() {
     $setting = array(
       '#all' => array(
@@ -263,12 +274,15 @@ class UpdateCoreTestCase extends UpdateTestHelper {
 
 }
 
+/**
+ * Tests behavior related to handling updates to contributed modules and themes.
+ */
 class UpdateTestContribCase extends UpdateTestHelper {
 
   public static function getInfo() {
     return array(
       'name' => 'Update contrib functionality',
-      'description' => 'Tests how the update module handles contributed modules and themes in a series of functional tests using mock XML data.',
+      'description' => 'Tests how the Update Manager module handles contributed modules and themes in a series of functional tests using mock XML data.',
       'group' => 'Update',
     );
   }
@@ -308,7 +322,7 @@ class UpdateTestContribCase extends UpdateTestHelper {
   }
 
   /**
-   * Test the basic functionality of a contrib module on the status report.
+   * Tests the basic functionality of a contrib module on the status report.
    */
   function testUpdateContribBasic() {
     $system_info = array(
@@ -336,17 +350,17 @@ class UpdateTestContribCase extends UpdateTestHelper {
   }
 
   /**
-   * Test that contrib projects are ordered by project name.
+   * Tests that contrib projects are ordered by project name.
    *
    * If a project contains multiple modules, we want to make sure that the
-   * available updates report is sorted by the parent project names, not by
-   * the names of the modules included in each project. In this test case, we
-   * have 2 contrib projects, "BBB Update test" and "CCC Update test".
-   * However, we have a module called "aaa_update_test" that's part of the
-   * "CCC Update test" project. We need to make sure that we see the "BBB"
-   * project before the "CCC" project, even though "CCC" includes a module
-   * that's processed first if you sort alphabetically by module name (which
-   * is the order we see things inside system_rebuild_module_data() for example).
+   * available updates report is sorted by the parent project names, not by the
+   * names of the modules included in each project. In this test case, we have
+   * two contrib projects, "BBB Update test" and "CCC Update test". However, we
+   * have a module called "aaa_update_test" that's part of the "CCC Update test"
+   * project. We need to make sure that we see the "BBB" project before the
+   * "CCC" project, even though "CCC" includes a module that's processed first
+   * if you sort alphabetically by module name (which is the order we see things
+   * inside system_rebuild_module_data() for example).
    */
   function testUpdateContribOrder() {
     // We want core to be version 7.0.
@@ -408,7 +422,7 @@ class UpdateTestContribCase extends UpdateTestHelper {
   }
 
   /**
-   * Test that subthemes are notified about security updates for base themes.
+   * Tests that subthemes are notified about security updates for base themes.
    */
   function testUpdateBaseThemeSecurityUpdate() {
     // Only enable the subtheme, not the base theme.
@@ -449,7 +463,7 @@ class UpdateTestContribCase extends UpdateTestHelper {
   }
 
   /**
-   * Test that disabled themes are only shown when desired.
+   * Tests that disabled themes are only shown when desired.
    */
   function testUpdateShowDisabledThemes() {
     // Make sure all the update_test_* themes are disabled.
@@ -510,7 +524,7 @@ class UpdateTestContribCase extends UpdateTestHelper {
   }
 
   /**
-   * Make sure that if we fetch from a broken URL, sane things happen.
+   * Makes sure that if we fetch from a broken URL, sane things happen.
    */
   function testUpdateBrokenFetchURL() {
     $system_info = array(
@@ -566,13 +580,12 @@ class UpdateTestContribCase extends UpdateTestHelper {
   }
 
   /**
-   * Check that hook_update_status_alter() works to change a status.
+   * Checks that hook_update_status_alter() works to change a status.
    *
    * We provide the same external data as if aaa_update_test 7.x-1.0 were
    * installed and that was the latest release. Then we use
    * hook_update_status_alter() to try to mark this as missing a security
-   * update, then assert if we see the appropriate warnings on the right
-   * pages.
+   * update, then assert if we see the appropriate warnings on the right pages.
    */
   function testHookUpdateStatusAlter() {
     variable_set('allow_authorize_operations', TRUE);
@@ -628,11 +641,15 @@ class UpdateTestContribCase extends UpdateTestHelper {
 
 }
 
+/**
+ * Tests project upload and extract functionality.
+ */
 class UpdateTestUploadCase extends UpdateTestHelper {
+
   public static function getInfo() {
     return array(
       'name' => 'Upload and extract module functionality',
-      'description' => 'Tests the update module\'s upload and extraction functionality.',
+      'description' => 'Tests the Update Manager module\'s upload and extraction functionality.',
       'group' => 'Update',
     );
   }
@@ -673,7 +690,7 @@ class UpdateTestUploadCase extends UpdateTestHelper {
   }
 
   /**
-   * Ensure that archiver extensions are properly merged in the UI.
+   * Ensures that archiver extensions are properly merged in the UI.
    */
   function testFileNameExtensionMerging() {
     $this->drupalGet('admin/modules/install');
@@ -684,7 +701,7 @@ class UpdateTestUploadCase extends UpdateTestHelper {
   }
 
   /**
-   * Check the messages on Update manager pages when missing a security update.
+   * Checks the messages on update manager pages when missing a security update.
    */
   function testUpdateManagerCoreSecurityUpdateMessages() {
     $setting = array(
@@ -725,6 +742,9 @@ class UpdateTestUploadCase extends UpdateTestHelper {
 
 }
 
+/**
+ * Tests update functionality unrelated to the database.
+ */
 class UpdateCoreUnitTestCase extends DrupalUnitTestCase {
 
   public static function getInfo() {
@@ -741,7 +761,7 @@ class UpdateCoreUnitTestCase extends DrupalUnitTestCase {
   }
 
   /**
-   * Tests _update_build_fetch_url according to issue 1481156
+   * Tests that _update_build_fetch_url() builds the URL correctly.
    */
   function testUpdateBuildFetchUrl() {
     //first test that we didn't break the trivial case
diff --git a/modules/user/tests/user_form_test.info b/modules/user/tests/user_form_test.info
index 215368355..5db169310 100644
--- a/modules/user/tests/user_form_test.info
+++ b/modules/user/tests/user_form_test.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/user/user.info b/modules/user/user.info
index e1f0df04f..f17ef35e8 100644
--- a/modules/user/user.info
+++ b/modules/user/user.info
@@ -9,8 +9,8 @@ required = TRUE
 configure = admin/config/people
 stylesheets[all][] = user.css
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/modules/user/user.install b/modules/user/user.install
index e46f29d8e..217577de7 100644
--- a/modules/user/user.install
+++ b/modules/user/user.install
@@ -830,6 +830,15 @@ function user_update_7015() {
   ));
 }
 
+/**
+ * @} End of "addtogroup updates-6.x-to-7.x".
+ */
+
+/**
+ * @addtogroup updates-7.x-extra
+ * @{
+ */
+
 /**
  * Update the database to match the schema.
  */
@@ -890,15 +899,6 @@ function user_update_7017() {
   return $message;
 }
 
-/**
- * @} End of "addtogroup updates-6.x-to-7.x"
- */
-
-/**
- * @addtogroup updates-7.x-extra
- * @{
- */
-
 /**
  * Ensure there is an index on {users}.picture.
  */
@@ -909,5 +909,5 @@ function user_update_7018() {
 }
 
 /**
- * @} End of "addtogroup updates-7.x-extra"
+ * @} End of "addtogroup updates-7.x-extra".
  */
diff --git a/modules/user/user.module b/modules/user/user.module
index 94ecaa2df..47ac64273 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -159,6 +159,10 @@ function user_entity_info() {
       'uri callback' => 'user_uri',
       'label callback' => 'format_username',
       'fieldable' => TRUE,
+      // $user->language is only the preferred user language for the user
+      // interface textual elements. As it is not necessarily related to the
+      // language assigned to fields, we do not define it as the entity language
+      // key.
       'entity keys' => array(
         'id' => 'uid',
       ),
@@ -819,7 +823,12 @@ function user_access($string, $account = NULL) {
 /**
  * Checks for usernames blocked by user administration.
  *
- * @return boolean TRUE for blocked users, FALSE for active.
+ * @param $name
+ *   A string containing a name of the user.
+ *
+ * @return
+ *   Object with property 'name' (the user name), if the user is blocked;
+ *   FALSE if the user is not blocked.
  */
 function user_is_blocked($name) {
   return db_select('users')
@@ -3707,7 +3716,8 @@ function user_register_form($form, &$form_state) {
 
   // Attach field widgets, and hide the ones where the 'user_register_form'
   // setting is not on.
-  field_attach_form('user', $form['#user'], $form, $form_state);
+  $langcode = entity_language('user', $form['#user']);
+  field_attach_form('user', $form['#user'], $form, $form_state, $langcode);
   foreach (field_info_instances('user', 'user') as $field_name => $instance) {
     if (empty($instance['settings']['user_register_form'])) {
       $form[$field_name]['#access'] = FALSE;
diff --git a/modules/user/user.pages.inc b/modules/user/user.pages.inc
index 25f4528f0..c4b68b9f6 100644
--- a/modules/user/user.pages.inc
+++ b/modules/user/user.pages.inc
@@ -113,8 +113,9 @@ function user_pass_reset($form, &$form_state, $uid, $timestamp, $hashed_pass, $a
     drupal_goto();
   }
   else {
-    // Time out, in seconds, until login URL expires. 24 hours = 86400 seconds.
-    $timeout = 86400;
+    // Time out, in seconds, until login URL expires. Defaults to 24 hours =
+    // 86400 seconds.
+    $timeout = variable_get('user_password_reset_timeout', 86400);
     $current = REQUEST_TIME;
     // Some redundant checks for extra security ?
     $users = user_load_multiple(array($uid), array('status' => '1'));
@@ -262,7 +263,8 @@ function user_profile_form($form, &$form_state, $account, $category = 'account')
   if ($category == 'account') {
     user_account_form($form, $form_state);
     // Attach field widgets.
-    field_attach_form('user', $account, $form, $form_state);
+    $langcode = entity_language('user', $account);
+    field_attach_form('user', $account, $form, $form_state, $langcode);
   }
 
   $form['actions'] = array('#type' => 'actions');
diff --git a/modules/user/user.test b/modules/user/user.test
index 2efe5b070..b53db0769 100644
--- a/modules/user/user.test
+++ b/modules/user/user.test
@@ -451,6 +451,58 @@ class UserLoginTestCase extends DrupalWebTestCase {
   }
 }
 
+/**
+ * Tests resetting a user password.
+ */
+class UserPasswordResetTestCase extends DrupalWebTestCase {
+  protected $profile = 'standard';
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Reset password',
+      'description' => 'Ensure that password reset methods work as expected.',
+      'group' => 'User',
+    );
+  }
+
+  /**
+   * Tests password reset functionality.
+   */
+  function testUserPasswordReset() {
+    // Create a user.
+    $account = $this->drupalCreateUser();
+    $this->drupalLogin($account);
+    $this->drupalLogout();
+    // Attempt to reset password.
+    $edit = array('name' => $account->name);
+    $this->drupalPost('user/password', $edit, t('E-mail new password'));
+    // Confirm the password reset.
+    $this->assertText(t('Further instructions have been sent to your e-mail address.'), 'Password reset instructions mailed message displayed.');
+  }
+
+  /**
+   * Attempts login using an expired password reset link.
+   */
+  function testUserPasswordResetExpired() {
+    // Set password reset timeout variable to 43200 seconds = 12 hours.
+    $timeout = 43200;
+    variable_set('user_password_reset_timeout', $timeout);
+
+    // Create a user.
+    $account = $this->drupalCreateUser();
+    $this->drupalLogin($account);
+    // Load real user object.
+    $account = user_load($account->uid, TRUE);
+    $this->drupalLogout();
+
+    // To attempt an expired password reset, create a password reset link as if
+    // its request time was 60 seconds older than the allowed limit of timeout.
+    $bogus_timestamp = REQUEST_TIME - variable_get('user_password_reset_timeout', 86400) - 60;
+    $this->drupalGet("user/reset/$account->uid/$bogus_timestamp/" . user_pass_rehash($account->pass, $bogus_timestamp, $account->login));
+    $this->assertText(t('You have tried to use a one-time login link that has expired. Please request a new one using the form below.'), 'Expired password reset request rejected.');
+  }
+}
+
 /**
  * Test cancelling a user.
  */
@@ -2119,9 +2171,13 @@ class UserRolesAssignmentTestCase extends DrupalWebTestCase {
   /**
    * Check role on user object.
    *
-   * @param object $account User.
-   * @param integer $rid Role id.
-   * @param bool $is_assigned True if the role should present on the account.
+   * @param object $account
+   *   The user account to check.
+   * @param string $rid
+   *   The role ID to search for.
+   * @param bool $is_assigned
+   *   (optional) Whether to assert that $rid exists (TRUE) or not (FALSE).
+   *   Defaults to TRUE.
    */
   private function userLoadAndCheckRoleAssigned($account, $rid, $is_assigned = TRUE) {
     $account = user_load($account->uid, TRUE);
diff --git a/profiles/minimal/minimal.info b/profiles/minimal/minimal.info
index 1fd9bddd0..5a9d4c322 100644
--- a/profiles/minimal/minimal.info
+++ b/profiles/minimal/minimal.info
@@ -5,8 +5,8 @@ core = 7.x
 dependencies[] = block
 dependencies[] = dblog
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/profiles/minimal/minimal.install b/profiles/minimal/minimal.install
index 58a0f1277..6099da1ce 100644
--- a/profiles/minimal/minimal.install
+++ b/profiles/minimal/minimal.install
@@ -1,7 +1,7 @@
 <?php
 /**
  * @file
- * Install, update and uninstall functions for the the minimal install profile.
+ * Install, update and uninstall functions for the minimal install profile.
  */
 
 /**
diff --git a/profiles/standard/standard.info b/profiles/standard/standard.info
index 4a1efd44c..5e36db4ed 100644
--- a/profiles/standard/standard.info
+++ b/profiles/standard/standard.info
@@ -24,8 +24,8 @@ dependencies[] = field_ui
 dependencies[] = file
 dependencies[] = rdf
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/profiles/testing/modules/drupal_system_listing_compatible_test/drupal_system_listing_compatible_test.info b/profiles/testing/modules/drupal_system_listing_compatible_test/drupal_system_listing_compatible_test.info
index ac7935ba2..94a9186b6 100644
--- a/profiles/testing/modules/drupal_system_listing_compatible_test/drupal_system_listing_compatible_test.info
+++ b/profiles/testing/modules/drupal_system_listing_compatible_test/drupal_system_listing_compatible_test.info
@@ -6,8 +6,8 @@ core = 7.x
 hidden = TRUE
 files[] = drupal_system_listing_compatible_test.test
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/profiles/testing/modules/drupal_system_listing_incompatible_test/drupal_system_listing_incompatible_test.info b/profiles/testing/modules/drupal_system_listing_incompatible_test/drupal_system_listing_incompatible_test.info
index df5eb4f3c..28ff2b847 100644
--- a/profiles/testing/modules/drupal_system_listing_incompatible_test/drupal_system_listing_incompatible_test.info
+++ b/profiles/testing/modules/drupal_system_listing_incompatible_test/drupal_system_listing_incompatible_test.info
@@ -8,8 +8,8 @@ version = VERSION
 core = 6.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/profiles/testing/testing.info b/profiles/testing/testing.info
index 4920d5708..4791a0d79 100644
--- a/profiles/testing/testing.info
+++ b/profiles/testing/testing.info
@@ -4,8 +4,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index 87eaabbc5..30699a0a2 100644
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -262,7 +262,7 @@ $drupal_hash_salt = '';
  * To see what PHP settings are possible, including whether they can be set at
  * runtime (by using ini_set()), read the PHP documentation:
  * http://www.php.net/manual/en/ini.list.php
- * See drupal_initialize_variables() in includes/bootstrap.inc for required
+ * See drupal_environment_initialize() in includes/bootstrap.inc for required
  * runtime settings and the .htaccess file for non-runtime settings. Settings
  * defined there should not be duplicated here so as to avoid conflict issues.
  */
diff --git a/themes/bartik/bartik.info b/themes/bartik/bartik.info
index f4aed308c..7492f2959 100644
--- a/themes/bartik/bartik.info
+++ b/themes/bartik/bartik.info
@@ -34,8 +34,8 @@ regions[footer] = Footer
 settings[shortcut_module_link] = 0
 
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/themes/bartik/css/style.css b/themes/bartik/css/style.css
index 4fb821025..8e9520210 100644
--- a/themes/bartik/css/style.css
+++ b/themes/bartik/css/style.css
@@ -1488,7 +1488,7 @@ ol.search-results {
 }
 .search-results li:last-child {
   border-bottom: none;
-  padding-bottom: none;
+  padding-bottom: 0;
   margin-bottom: 1em;
 }
 .search-results .search-snippet-info {
diff --git a/themes/bartik/template.php b/themes/bartik/template.php
index bdad570d1..7466e05ce 100644
--- a/themes/bartik/template.php
+++ b/themes/bartik/template.php
@@ -150,7 +150,7 @@ function bartik_field__taxonomy_term_reference($variables) {
   $output .= '</ul>';
 
   // Render the top-level DIV.
-  $output = '<div class="' . $variables['classes'] . (!in_array('clearfix', $variables['classes_array']) ? ' clearfix' : '') . '">' . $output . '</div>';
+  $output = '<div class="' . $variables['classes'] . (!in_array('clearfix', $variables['classes_array']) ? ' clearfix' : '') . '"' . $variables['attributes'] .'>' . $output . '</div>';
 
   return $output;
 }
diff --git a/themes/garland/garland.info b/themes/garland/garland.info
index 7dfbf5302..0b8016c7f 100644
--- a/themes/garland/garland.info
+++ b/themes/garland/garland.info
@@ -7,8 +7,8 @@ stylesheets[all][] = style.css
 stylesheets[print][] = print.css
 settings[garland_width] = fluid
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/themes/seven/seven.info b/themes/seven/seven.info
index a59f0f274..c51d58ec3 100644
--- a/themes/seven/seven.info
+++ b/themes/seven/seven.info
@@ -13,8 +13,8 @@ regions[page_bottom] = Page bottom
 regions[sidebar_first] = First sidebar
 regions_hidden[] = sidebar_first
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
diff --git a/themes/stark/stark.info b/themes/stark/stark.info
index fd7aa87e1..0d35fc3c6 100644
--- a/themes/stark/stark.info
+++ b/themes/stark/stark.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 stylesheets[all][] = layout.css
 
-; Information added by drupal.org packaging script on 2012-05-02
-version = "7.14"
+; Information added by drupal.org packaging script on 2012-08-01
+version = "7.15"
 project = "drupal"
-datestamp = "1335997555"
+datestamp = "1343839327"
 
-- 
GitLab