summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.txt3
-rw-r--r--includes/common.inc5
-rw-r--r--includes/module.inc5
-rw-r--r--modules/simpletest/simpletest.info1
-rw-r--r--modules/simpletest/tests/boot.test38
-rw-r--r--modules/simpletest/tests/boot_test_1.info6
-rw-r--r--modules/simpletest/tests/boot_test_1.module21
-rw-r--r--modules/simpletest/tests/boot_test_2.info6
-rw-r--r--modules/simpletest/tests/boot_test_2.module13
9 files changed, 98 insertions, 0 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 069595046..4e9e4f0da 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,6 +1,9 @@
Drupal 7.40, xxxx-xx-xx (development version)
-----------------------
+- Fixed various bugs that occurred after hooks were invoked early in the Drupal
+ bootstrap and that caused module_implements() and drupal_alter() to cache an
+ incomplete set of hook implementations for later use.
- Set the X-Content-Type-Options header to "nosniff" when possible, to prevent
certain web browsers from picking an unsafe MIME type.
- Prevented the database API from executing multiple queries at once on MySQL,
diff --git a/includes/common.inc b/includes/common.inc
index ceac115a5..ef71ee8b6 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -5212,6 +5212,11 @@ function _drupal_bootstrap_full() {
fix_gpc_magic();
// Load all enabled modules
module_load_all();
+ // Reset drupal_alter() and module_implements() static caches as these
+ // include implementations for vital modules only when called early on
+ // in the bootstrap.
+ drupal_static_reset('drupal_alter');
+ drupal_static_reset('module_implements');
// Make sure all stream wrappers are registered.
file_get_stream_wrappers();
// Ensure mt_rand is reseeded, to prevent random values from one page load
diff --git a/includes/module.inc b/includes/module.inc
index 076992ca9..7bf619b47 100644
--- a/includes/module.inc
+++ b/includes/module.inc
@@ -867,6 +867,11 @@ function module_hook_info() {
* @see module_implements()
*/
function module_implements_write_cache() {
+ // The list of implementations includes vital modules only before full
+ // bootstrap, so do not write cache if we are not fully bootstrapped yet.
+ if (drupal_get_bootstrap_phase() != DRUPAL_BOOTSTRAP_FULL) {
+ return;
+ }
$implementations = &drupal_static('module_implements');
if (isset($implementations['#write_cache'])) {
unset($implementations['#write_cache']);
diff --git a/modules/simpletest/simpletest.info b/modules/simpletest/simpletest.info
index 7b139ba3d..1aec619f5 100644
--- a/modules/simpletest/simpletest.info
+++ b/modules/simpletest/simpletest.info
@@ -11,6 +11,7 @@ configure = admin/config/development/testing/settings
files[] = tests/actions.test
files[] = tests/ajax.test
files[] = tests/batch.test
+files[] = tests/boot.test
files[] = tests/bootstrap.test
files[] = tests/cache.test
files[] = tests/common.test
diff --git a/modules/simpletest/tests/boot.test b/modules/simpletest/tests/boot.test
new file mode 100644
index 000000000..562b082e8
--- /dev/null
+++ b/modules/simpletest/tests/boot.test
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * Perform early bootstrap tests.
+ */
+class EarlyBootstrapTestCase extends DrupalWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Early bootstrap test',
+ 'description' => 'Confirm that calling module_implements() during early bootstrap does not pollute the module_implements() cache.',
+ 'group' => 'System',
+ );
+ }
+
+ function setUp() {
+ parent::setUp('boot_test_1', 'boot_test_2');
+ }
+
+ /**
+ * Test hook_boot() on both regular and "early exit" pages.
+ */
+ public function testHookBoot() {
+ $paths = array('', 'early_exit');
+ foreach ($paths as $path) {
+ // Empty the module_implements() caches.
+ module_implements(NULL, FALSE, TRUE);
+ // Do a request to the front page, which will call module_implements()
+ // during hook_boot().
+ $this->drupalGet($path);
+ // Reset the static cache so we get implementation data from the persistent
+ // cache.
+ drupal_static_reset();
+ // Make sure we get a full list of all modules implementing hook_help().
+ $modules = module_implements('help');
+ $this->assertTrue(in_array('boot_test_2', $modules));
+ }
+ }
+}
diff --git a/modules/simpletest/tests/boot_test_1.info b/modules/simpletest/tests/boot_test_1.info
new file mode 100644
index 000000000..a6f2ffb60
--- /dev/null
+++ b/modules/simpletest/tests/boot_test_1.info
@@ -0,0 +1,6 @@
+name = Early bootstrap tests
+description = A support module for hook_boot testing.
+core = 7.x
+package = Testing
+version = VERSION
+hidden = TRUE
diff --git a/modules/simpletest/tests/boot_test_1.module b/modules/simpletest/tests/boot_test_1.module
new file mode 100644
index 000000000..a452e2897
--- /dev/null
+++ b/modules/simpletest/tests/boot_test_1.module
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * @file
+ * Tests calling module_implements() during hook_boot() invocation.
+ */
+
+/**
+ * Implements hook_boot().
+ */
+function boot_test_1_boot() {
+ // Calling module_implements during hook_boot() will return "vital" modules
+ // only, and this list of modules will be statically cached.
+ module_implements('help');
+ // Define a special path to test that the static cache isn't written away
+ // if we exit before having completed the bootstrap.
+ if ($_GET['q'] == 'early_exit') {
+ module_implements_write_cache();
+ exit();
+ }
+}
diff --git a/modules/simpletest/tests/boot_test_2.info b/modules/simpletest/tests/boot_test_2.info
new file mode 100644
index 000000000..f421997d4
--- /dev/null
+++ b/modules/simpletest/tests/boot_test_2.info
@@ -0,0 +1,6 @@
+name = Early bootstrap tests
+description = A support module for hook_boot hook testing.
+core = 7.x
+package = Testing
+version = VERSION
+hidden = TRUE
diff --git a/modules/simpletest/tests/boot_test_2.module b/modules/simpletest/tests/boot_test_2.module
new file mode 100644
index 000000000..c3ab8d61d
--- /dev/null
+++ b/modules/simpletest/tests/boot_test_2.module
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @file
+ * Defines a hook_help() implementation in a non-"bootstrap" module.
+ */
+
+/**
+ * Implements hook_help().
+ */
+function boot_test_2_help($path, $arg) {
+ // Empty hook.
+}