Count the number of times a WordPress shortcode is used in a post

I have the following WordPress shortcode function:

function wp_shortcode() {
 static $i=1;
 $return = '['.$i.']';
 $i++;
 return $return;
}
add_shortcode('shortcode', 'wp_shortcode');

This works fine. The $i variable gets incremented each time the function is called in the article. So for

Read More
[shortcode][shortcode][shortcode][shortcode]

the output is as expected

[1][2][3][4]

but

if the article has more than one page, than the counter resets on the next article page. So for:

[shortcode][shortcode][shortcode][shortcode]
<!--nextpage-->
[shortcode][shortcode][shortcode][shortcode]

the output is

[1][2][3][4]
<!--nextpage-->
[1][2][3][4]

instead of the wanted output of:

[1][2][3][4]
<!--nextpage-->
[5][6][7][8]

Anyway to change this?

Related posts

Leave a Reply

4 comments

  1. So after researching a bit more @diggy’s idea with pre processing the_content and adding the $atts to the shorcodes before the shortcodes are rendered, I came up with this:

    function my_shortcode_content( $content ) {
     //check to see if the post has your shortcode, skip do nothing if not found
     if( has_shortcode( $content, 'shortcode' ) ):
    
      //replace any shortcodes to the basic form ([shortcode 1] back to [shortcode])
      //usefull when the post is edited and more shortcodes are added
      $content = preg_replace('/shortcode .]/', 'shortcode]', $content);
    
      //loop the content and replace the basic shortcodes with the incremented value
      $content = preg_replace_callback('/shortocode]/', 'rep_count', $content);
    
     endif;
    
    return $content;
    }
    add_filter( 'content_save_pre' , 'my_shortcode_content' , 10, 1);
    
    function rep_count($matches) {
     static $i = 1;
    return 'shortcode ' . $i++ .']';
    }
    
  2. Nice question. A possible solution below, however not exactly elegant because it requires you to have a fixed number of shortcodes on each page, e.g. 4:

    add_shortcode( 'shortcode', 'wp_shortcode' );
    function wp_shortcode() {
        global $page;
        $spp = 4;
        static $i = 1;
        $ii = $i + ( ( $page - 1 ) * $spp );
        $return = '<a href="#f'.$ii.'" name="r'.$ii.'">['.$ii.']</a>';
        $i++;
        return $return;
    }
    
  3. If you need to just count the total tags in a page/post you can use this:

    function count_shortcodes( $content, $tag ) {
        if ( false === strpos( $content, '[' ) ) {
            return 0;
        }
    
        if ( shortcode_exists( $tag ) ) {
            preg_match_all( '/' . get_shortcode_regex() . '/', $content, $matches, PREG_SET_ORDER );
            if ( empty( $matches ) )
                return 0;
    
            $count = 0;
            foreach ( $matches as $shortcode ) {
                if ( $tag === $shortcode[2] ) {
                    $count++;
                } elseif ( ! empty( $shortcode[5] ) && has_shortcode( $shortcode[5], $tag ) ) {
                    $count++;
                }
            }
    
            return $count;
        }
        return 0;
    }
    
  4. It is happens, because on every page load you redefined your function, so static $i=1; will executed always.

    Maybe you want to use a $_SESSION variable. But do not forget the session_start() somewhere in init callback.

    function wp_shortcode() {
        if (empty($_SESSION["myCounter"])) {
            $_SESSION["myCounter"] = 1;
        }
        $return = '<a href="#f' . $_SESSION["myCounter"] . '" name="r' 
            . $_SESSION["myCounter"] . '">[' 
            . $_SESSION["myCounter"] . ']</a>';
        $_SESSION["myCounter"]++;
        return $return;
    }
    add_shortcode('shortcode', 'wp_shortcode');
    

    Setting the session, put it into the functions.php

    add_action('init', 'my_init');
    function my_init() {
        if (!session_id()) {
            session_start();
        }
        //Other init here
    }