1

I've created a custom shortcode to add pop-up definitions to selected vocabulary terms. The shortcode looks like this:

[glossary term="data breach"]data breaches[/glossary]

The function searches posts in a custom post type called 'glossary-term' for the term's definition, prints it in a div, and turns the enclosed text into a link to that div:

function glossary_shortcode( $atts = array(), $shortcode_content = null ) {
    
    // parameters
    extract(shortcode_atts(array(
        'term' => null
    ), $atts));
    
    $glossary_term_object = get_page_by_title($term, 'OBJECT', 'glossary-term');

   // print definition in popup div
    echo '<div id="glossary-popup-' . $glossary_term_object->post_name . '" class="glossary_popup"><h4>' . $glossary_term_object->post_title . '</h4>' . wpautop( $glossary_term_object->post_content ) . '<div class="ctas"><a href="">Visit Glossary</a><a href="#">Close</a></div></div>';

    // return link to definition popup
    return '<a href="#glossary-popup-' . $glossary_term_object->post_name . '">' . $shortcode_content . '</a>';
    
}

add_shortcode('glossary', 'glossary_shortcode');

Rather than echo the definition pop-up, I'd like to have all the definitions created by this shortcode (which may be used several times on a page) collected into their own div at the end of the main page content.

Any ideas how to accomplish this?

2 Answers 2

0

I think, I would simply store all the definitions during the glossary_shortcode() execution in a global variable and serve them at the end of some hook like the_content.

function glossary_shortcode( $atts = array(), $shortcode_content = null ) {
    // Your code can be kept identical, just store the $glossary_term_object somewhere.

    global $glossaries;
    $glossaries = $glossaries ?? [];
    $glossaries[] = glossary_term_object;
}

add_filter( 'the_content', function ( $content ) {
 
    global $glossaries;
    if ( !empty( $glossaries ) ) {
        echo '<ul class="glossary">';

        foreach ( $glossaries as $glossary ) {
                printf( '<li><a href="%s" target="_blank">%s : %s</a></li>',
                        get_the_permalink( $glossary ),
                        $glossary->post_title,
                        $glossary->post_content
                );
        }

        echo '</ul>';
    }
 
    return $content;
}
1
  • 1
    This works, so long as we add a later priority (11+) to add_filter(). Thanks so much.
    – BoyKenan
    Commented Jan 26, 2022 at 17:53
0

Here's the solution, h/t to Tim who got me 95% of the way there.

// Shortcode function
function glossary_shortcode( $atts = array(), $shortcode_content = null ) {
    
    // Parameters: determine what post we're looking for
    extract(shortcode_atts(array(
        'term' => null
    ), $atts));
    
    // Get requested post
    $glossary_term_object = get_page_by_title($term, 'OBJECT', 'glossary-term');
   
    // Add post to global variable
    global $glossaries;
    $glossaries = $glossaries ?? [];
    $glossaries[] = $glossary_term_object;
    
    // Link to the list item we'll build below.
    return '<a class="glossary-link toggle" href="#glossary-popup-' . $glossary_term_object->post_name . '">' . $shortcode_content . '</a>';
    
}

// Register shortcode
add_shortcode('glossary', 'glossary_shortcode');


// Build our list of definitions. Set priority at 11+ or global variable will be empty.
add_filter( 'the_content', function ( $content ) {
 
    // Retrieve posts assembled above
    global $glossaries;
    if ( !empty( $glossaries ) ) {
        
        $page_glossary = '';
        
        // Format our posts content as a list of definitions
        foreach ($glossaries as $glossary) {
            
            $page_glossary .= '<li id="glossary-popup-' . $glossary->post_name . '" class="glossary_popup"><h4>' . $glossary->post_title . '</h4>' . wpautop( $glossary->post_content ) . '<div class="ctas"><a href="">Visit Glossary</a><a class="close" href="#glossary-popup-' . $glossary->post_name . '">Close</a></div></li>';
            
        }
        
        // Add the list to the end of the current post's content
        $content .= '<section id="page-glossary"><ul>' . $page_glossary . '</ul></section>';
    }
 
    return $content;
    
}, 11 );
1
  • Glad I could help. Indeed, the weight of 11 will add the filter after other filters that would have been registered later in the execution.
    – Tim
    Commented Jan 26, 2022 at 21:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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