I need to generate a list of sidebars on a given page. I know how to list all sidebars that have been registered, and all sidebars that have been registered that have active widgets, but I do not know how to filter them down to the sidebars that were displayed on an individual page using PHP.
To try to get around this I took $wp_registered_sidebars
and swapped it out for a class that implemented ArrayAccess
, which gets 90% of the way there in that it intercepts the calls and stores the requested sidebars, only the sidebars then never show because somewhere is an is_array
or other check fails.
I can also intercept dynamic_sidebar_params
and check the id field in the first array item, but this only tells me which dynamic sidebars are called with active widgets, it doesn’t tell me when an empty sidebar is tried.
Here is my interception class:
class sidebar_counter implements ArrayAccess {
private $container;
private $offsets = array();
function __construct( $container ) {
$this->container = $container;
}
public function addOffset( $offset ) {
if ( !in_array( $offset, $this->offsets ) ) {
$this->offsets[] = $offset;
}
}
public function getOffsets() {
return $this->offsets;
}
public function offsetExists( $offset ) {
$this->addOffset( $offset );
return isset($this->container[$offset]);
}
public function offsetGet( $offset ) {
$this->addOffset( $offset );
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
public function offsetSet( $offset, $value ) {
if ( is_null( $offset ) ) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
$this->addOffset( $offset );
}
}
public function offsetUnset( $offset ) {
if ( ( $key = array_search( $offset, $this->offsets ) ) !== false ) {
unset( $this->offsets[$key] );
}
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
}
It’s intended usage:
// early on:
global $wp_registered_sidebars;
$this->counter = new sidebar_counter( $wp_registered_sidebars );
$wp_registered_sidebars = $this->counter;
then after the footer:
$sidebar_ids = $counter->getOffsets();
There actually are filters coming with WP 3.9+:
do_action( 'dynamic_sidebar_before', $index, false );
do_action( 'dynamic_sidebar_after', $index, false );
apply_filters( 'dynamic_sidebar_has_widgets', false, $index );
The 2nd argument indicates if the sidebar has widgets.
Current workaround: Hook into
sanitize_title()
as this will hold the current sidebarname/ID
. Then hook intowp_get_sidebars_widgets()
as this is where you already got the name and know if there are widgets or not.