Skip to content

Commit 083d66b

Browse files
author
jorbin
committed
Bootstrap/Load: Load plugin.php earlier in wp-settings.php
In order to allow non-web initializations of WordPress (such as through wp-cli) to modify things like the check for maintenance mode, plugins.php and the associated functions must be available much earlier. The use of these functions earlier than the loading of plugins is not recommended in most use cases. Fixes #36819. See #34936. Props jorbin, danielbachhuber for documentation. git-svn-id: https://develop.svn.wordpress.org/trunk@37588 602fd350-edb4-49c9-b593-d223f7449a82
1 parent d5b571d commit 083d66b

File tree

3 files changed

+130
-2
lines changed

3 files changed

+130
-2
lines changed

src/wp-includes/plugin.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,3 +946,65 @@ function _wp_filter_build_unique_id($tag, $function, $priority) {
946946
return $function[0] . '::' . $function[1];
947947
}
948948
}
949+
950+
/**
951+
* Back up global variables used for actions and filters.
952+
*
953+
* Prevents redefinition of these globals in advanced-cache.php from accidentally
954+
* destroying existing data.
955+
*
956+
* @since 4.6.0
957+
* @access private
958+
*
959+
* @global array $wp_filter Stores all filters and actions.
960+
* @global array $wp_actions Stores the amount of times an action was triggered.
961+
* @global array $merged_filters Merges the filter hooks using this function.
962+
* @global array $wp_current_filter Stores the list of current filters with the current one last.
963+
* @staticvar array $backup_globals Backed up globals.
964+
* @return array the staticvar from the first time it is set.
965+
*/
966+
function _backup_plugin_globals(){
967+
global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
968+
static $backup_globals = array();
969+
if ( empty( $backup_globals ) ) {
970+
$backup_globals = array(
971+
'backup_wp_filter' => $wp_filter,
972+
'backup_wp_actions' => $wp_actions,
973+
'backup_merged_filters' => $merged_filters,
974+
'backup_wp_current_filter' => $wp_current_filter,
975+
);
976+
};
977+
return $backup_globals;
978+
}
979+
980+
/**
981+
* Safely restore backed up global variables used for actions and filters.
982+
*
983+
* @since 4.6.0
984+
* @access private
985+
*
986+
* @global array $wp_filter Stores all filters and actions.
987+
* @global array $wp_actions Stores the amount of times an action was triggered.
988+
* @global array $merged_filters Merges the filter hooks using this function.
989+
* @global array $wp_current_filter Stores the list of current filters with the current one last.
990+
* @staticvar array $backup_globals Backed up globals.
991+
*/
992+
function _restore_plugin_globals(){
993+
global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
994+
$backup_globals = _backup_plugin_globals();
995+
if ( $wp_filter !== $backup_globals['backup_wp_filter'] ){
996+
$wp_filter = array_merge_recursive( $wp_filter, $backup_globals['backup_wp_filter'] );
997+
}
998+
999+
if ( $wp_actions !== $backup_globals['backup_wp_actions'] ){
1000+
$wp_actions = array_merge_recursive( $wp_actions, $backup_globals['backup_wp_actions'] );
1001+
}
1002+
1003+
if ( $merged_filters !== $backup_globals['backup_merged_filters'] ){
1004+
$merged_filters = array_merge_recursive( $merged_filters, $backup_globals['backup_merged_filters'] );
1005+
}
1006+
1007+
if ( $wp_current_filter !== $backup_globals['backup_wp_current_filter'] ){
1008+
$wp_current_filter = array_merge_recursive( $wp_current_filter, $backup_globals['backup_wp_current_filter'] );
1009+
}
1010+
}

src/wp-settings.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
// Include files required for initialization.
2121
require( ABSPATH . WPINC . '/load.php' );
2222
require( ABSPATH . WPINC . '/default-constants.php' );
23+
require( ABSPATH . WPINC . '/plugin.php' );
2324

2425
/*
2526
* These can't be directly globalized in version.php. When updating,
@@ -70,8 +71,11 @@
7071
wp_debug_mode();
7172

7273
// For an advanced caching plugin to use. Uses a static drop-in because you would only want one.
73-
if ( WP_CACHE )
74+
if ( WP_CACHE ) {
75+
_backup_plugin_globals();
7476
WP_DEBUG ? include( WP_CONTENT_DIR . '/advanced-cache.php' ) : @include( WP_CONTENT_DIR . '/advanced-cache.php' );
77+
_restore_plugin_globals();
78+
}
7579

7680
// Define WP_LANG_DIR if not set.
7781
wp_set_lang_dir();
@@ -81,7 +85,6 @@
8185
require( ABSPATH . WPINC . '/functions.php' );
8286
require( ABSPATH . WPINC . '/class-wp.php' );
8387
require( ABSPATH . WPINC . '/class-wp-error.php' );
84-
require( ABSPATH . WPINC . '/plugin.php' );
8588
require( ABSPATH . WPINC . '/pomo/mo.php' );
8689

8790
// Include the wpdb class and, if present, a db.php database drop-in.

tests/phpunit/tests/actions.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,69 @@ function test_doing_filter_real() {
328328
$this->assertFalse( doing_filter( 'testing' ) ); // No longer doing this filter
329329
}
330330

331+
/**
332+
* @ticket 36819
333+
*/
334+
function test_backup_plugin_globals_returns_filters() {
335+
$backup = _backup_plugin_globals();
336+
$this->assertArrayHasKey( 'backup_wp_filter', $backup );
337+
$this->assertArrayHasKey( 'backup_wp_actions', $backup );
338+
$this->assertArrayHasKey( 'backup_wp_current_filter', $backup );
339+
$this->assertArrayHasKey( 'backup_merged_filters', $backup );
340+
}
341+
342+
/**
343+
* @ticket 36819
344+
*/
345+
function test_backup_plugin_globals_returns_filters_from_first_time_called() {
346+
$backup = _backup_plugin_globals();
347+
348+
$a = new MockAction();
349+
$tag = rand_str();
350+
351+
add_action($tag, array(&$a, 'action'));
352+
353+
$new_backup = _backup_plugin_globals();
354+
$this->assertEquals( $backup, $new_backup );
355+
}
356+
357+
/**
358+
* @ticket 36819
359+
*/
360+
function test_restore_plugin_globals_from_stomp() {
361+
global $wp_actions;
362+
$original_actions = $wp_actions;
363+
364+
_backup_plugin_globals();
365+
366+
$wp_actions = array();
367+
368+
$this->assertEmpty( $wp_actions );
369+
_restore_plugin_globals();
370+
371+
$this->assertEquals( $GLOBALS['wp_actions'], $original_actions );
372+
}
373+
374+
/**
375+
* @ticket 36819
376+
*/
377+
function test_restore_plugin_globals_includes_additions() {
378+
global $wp_filter;
379+
$original_filter = $wp_filter;
380+
381+
$backup = _backup_plugin_globals();
382+
383+
$a = new MockAction();
384+
$tag = rand_str();
385+
add_action($tag, array(&$a, 'action'));
386+
387+
$this->assertNotEquals( $GLOBALS['wp_filter'], $original_filter );
388+
389+
_restore_plugin_globals();
390+
391+
$this->assertNotEquals( $GLOBALS['wp_filter'], $original_filter );
392+
}
393+
331394
function apply_testing_filter() {
332395
$this->apply_testing_filter = true;
333396

0 commit comments

Comments
 (0)