2

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();
3

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 sidebar name/ID. Then hook into wp_get_sidebars_widgets() as this is where you already got the name and know if there are widgets or not.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.