How to detect if a function has been fired on any page so scripts/styles can be loaded conditionally

I’m building a small gallery plugin and I’d like to only load scripts/styles onto the page IF the gallery has been loaded via the template tag. The template tag can take a post ID parameter when used to call a post’s gallery from wherever you need within the theme.

I know how to do this on singular pages (I can just lookup the meta_key and match it against the currently viewed post) but detecting if there’s a gallery present on say the homepage (or any other page) is proving more difficult.

Read More

So let’s assume the template tag looks something like this:

if ( function_exists( 'my_gallery' ) )
    echo my_gallery( '100' ); // gallery of image from post 100 will be shown

And the gallery function looks like this (simplified):

function my_gallery( $post_id = '' ) {
    // whole bunch of stuff in here which is returned
}

The scripts and styles for the gallery would look like this (simplified):

function my_gallery_scripts() {

   wp_register_script( 'my-gallery-js', MY_GALLERY_URL . 'js/my-gallery.js', array( 'jquery' ), '1.0', true );
   wp_register_style( 'my-gallery-css', MY_GALLERY_URL . 'css/my-gallery.css', '', '1.0', 'screen' );

    // need to load these conditionally, but how?
    wp_enqueue_style( 'my-gallery-js' );
    wp_enqueue_script( 'my-gallery-css' );

}
add_action( 'wp_enqueue_scripts', 'my_gallery_scripts' );

I’ve tried using set_query_var inside my_gallery() like this to kind of set a global variable inside $wp_query.

 function my_gallery( $post_id = '' ) {

    set_query_var( 'has_gallery', true );

    // whole bunch of stuff in here which is returned
}    

The problem though is that I can’t use get_query_var inside the wp_enqueue_scripts action.

So the following would be ideal for me I believe, loading has_gallery into the $wp_query object which would be available to me on every page (except it doesn’t work).

 function my_gallery_scripts() {

   wp_register_script( 'my-gallery-js', MY_GALLERY_URL . 'js/my-gallery.js', array( 'jquery' ), '1.0', true );
   wp_register_style( 'my-gallery-css', MY_GALLERY_URL . 'css/my-gallery.css', '', '1.0', 'screen' );

    // does not work
    $has_gallery = get_query_var( 'has_gallery' );

    if ( $has_gallery ) {
        wp_enqueue_style( 'my-gallery-js' );
        wp_enqueue_script( 'my-gallery-css' );
    }
}
add_action( 'wp_enqueue_scripts', 'my_gallery_scripts' );

Is there another way to set a global option similar to set_query_var but will work in my scenario? I’d like to obviously avoid the use of a global variable. I’ve also tried setting a constant to no avail.

Related posts

3 comments

  1. For scripts this is no-brainer – just enqueue inside my_gallery() function and they will be output in footer (since header already passed).

    However stylesheets are a challenge, they are only supposed to work in head section and enqueueing for footer is not supported.

    Essentially you need to know if function was called before it was called. This has no simple solution for conditions given.

    I would probably try to load stylesheet from JS code to achieve this in form you are describing.

  2. The best way that I could imagine (and with best I mean “working”, not “fast”), is to check the post contents for the existence of that shortcode. Using the core Regex function makes that quite easy.

    Step 1: Register

    /**
     * Register the needed assets
     */
    add_action( 'wp_enqueue_scripts', 'wpse_105537_register_assets', 0 );
    function wpse_105537_register_assests()
    {
        wp_register_script(
            'wpse_105537_script',
            // ETC.
        );
        wp_register_style(
            'wpse_105537_style',
            // ETC.
        );
    }
    

    Step 2: Enqueue

    /**
     * Enqueue the needed assets if the shortcode is present anywhere
     */
    add_action( 'wp_enqueue_scripts', 'wpse_105537_register_assets' );
    function wpse_105537_enqueue_assets()
    {
        if ( ! wpse_105537_check_content() )
            return;
    
        wp_enqueue_script( 'wpse_105537_script' );
        wp_enqueue_style( 'wpse_105537_style' );
    }
    

    Helper: Search the shortcode inside the post contents

    This helper function aborts after the first match.

    /**
     * Check if any of the posts has the shortcode in its post_content
     * @return bool
     */
    function wpse_105537_check_content()
    {
        global $wp_query;
    
        foreach ( $GLOBALS['wp_query']->posts as $post )
        {
            $pattern = get_shortcode_regex();
            if (
                preg_match_all( '/'. $pattern .'/s', $post->post_content, $matches )
                AND array_key_exists( 2, $matches )
                AND in_array( 'gallery', $matches[2] )
            )
                return true;
        }
    
        return false;
    }
    
  3. I know how to do this on singular pages (I can just lookup the meta_key and match it against the currently viewed post) but detecting if there’s a gallery present on say the homepage (or any other page) is proving more difficult.

    So if there’s a meta key, it would be even more simple: Just grab it early. The first two functions can be taken from the other answer. Just the check itself would be replaced with the following function:

    /**
     * Check if any of the posts has the needed gallery meta data attached
     * @return bool
     */
    function wpse_105537_check_meta()
    {
        global $wp_query;
    
        foreach ( $GLOBALS['wp_query']->posts as $post )
        {
            if ( '' !== get_post_meta( $post->ID, 'your_meta_key', true ) )
                return true;
        }
    
        return false;
    }
    

Comments are closed.