[wp-trac] [WordPress Trac] #37958: Improve looping through sites and restoring
WordPress Trac
noreply at wordpress.org
Tue Sep 6 17:58:27 UTC 2016
#37958: Improve looping through sites and restoring
------------------------------------+-----------------------------
Reporter: tfrommen | Owner:
Type: enhancement | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Networks and Sites | Version:
Severity: normal | Keywords:
Focuses: multisite, performance |
------------------------------------+-----------------------------
[https://wordpress.slack.com/archives/core-multisite/p1473179575000111 As
discussed] in the recent multisite ~~hours~~ minutes, I would like to
propose (and discuss) a better means to looping through a number of (or
even all) sites and finally restoring to the state before the loop.
The naive approach looks like the following:
{{{#!php
<?php
foreach ( $some_or_all_site_ids as $site_id ) {
switch_to_blog( $site_id );
// Do some (maybe expensive) things on the site.
restore_current_blog();
}
}}}
This is not ideal as in all but the last case we don't really want to
restore, but just switch to the next site.
An ''improved'' version then would look like this:
{{{#!php
<?php
$__site_id = get_current_blog_id();
$__stack = $GLOBALS['_wp_switched_stack'];
$__switched = $GLOBALS['switched'];
foreach ( $some_or_all_site_ids as $site_id ) {
switch_to_blog( $site_id );
// Do some (maybe expensive) things on the site.
}
switch_to_blog( $__site_id );
$GLOBALS['_wp_switched_stack'] = $__stack;
$GLOBALS['switched'] = $__switched;
}}}
This, however, doesn't look nice. Moreover, you would have to do this for
every loop again and again.
So, why not abstract out the logic into a statically creatable
''snapshot'' of the current network state?
[https://gist.github.com/tfrommen/51d80f6d327d4d254ad9ace09b8d3fdc My
suggestion] for such a class looks like the following (which is already in
use in the wild):
{{{#!php
<?php
/**
* Save and restore the current network state.
*
* By using this class, you can avoid unnecessary
* switch_to_blog()-restore_current_blog()-switch_to_blog()-... excesses.
*/
class NetworkState {
/**
* @var int
*/
private $site_id;
/**
* @var int[]
*/
private $stack;
/**
* @var bool
*/
private $switched;
/**
* Constructor. Sets up the properties.
*/
public function __construct() {
global $_wp_switched_stack, $switched;
$this->site_id = get_current_blog_id();
$this->stack = $_wp_switched_stack;
$this->switched = $switched;
}
/**
* Returns a new instance representing the current network state.
*
* @return static Network state object.
*/
public static function create() {
return new static();
}
/**
* Restores the saved network state.
*
* @return void
*/
public function restore() {
switch_to_blog( $this->site_id );
$GLOBALS['_wp_switched_stack'] = $this->stack;
$GLOBALS['switched'] = $this->switched;
}
}
}}}
With this class, the `foreach`-loop code from before can become this:
{{{#!php
<?php
$network_state = NetworkState:create();
foreach ( $some_or_all_site_ids as $site_id ) {
switch_to_blog( $site_id );
// Do some (maybe expensive) things on the site.
}
$network_state->restore();
}}}
No matter what happens in the loop (and thus in any called function or
method), we restore to the exact same state the network was in before the
loop.
The above implementation works with the (currently available and used)
globals. As soon as there is some other way (see #37699), this can easily
be adapted as it's internals only.
The naming is just a suggestion, and we can, of course, baptize all the
things differently.
Core could make use of it, too. For example in the
[https://core.trac.wordpress.org/browser/trunk/src/wp-
admin/includes/ms.php?rev=38334#L221 `wpmu_delete_user()] function, during
[https://core.trac.wordpress.org/browser/trunk/src/wp-
admin/network/upgrade.php?rev=38229#L64 Network upgrade], or in the
[https://core.trac.wordpress.org/browser/trunk/src/wp-includes/admin-
bar.php?rev=38470#L461 wp_admin_bar_my_sites_menu()] function (!), which
means: On. Every. Single. Page. Load.
I'd be happy to provide a full patch against trunk. I just wanted to
propose this first and give opportunity to discuss this.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/37958>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list