wordpress shortcode within get_the_content() and infinite nested loop

225 views Asked by At

First of all, sorry for this long subject, but I didn't find a way to explain the issue otherwise...

I'm facing an issue with shortcode executed within get_the_content() and with the management of infinite nested loop that can occur.

My plugin is used as a shortcode to display posts of a specific list of categories passed as argument. The shortcode can be used as well on a page, on a post or on a widget. It can be summarized like this:

Root Post/Page/Widget body with [shortcode category_slug_list="category_slug1"]
  =>  post 1 of category with slug1 is displayed
      post 2 of category with slug1 is displayed
      ...
      ...
      post n of category with slug1 is displayed

Each post is displayed in the loop with:

$content = get_the_content();  
$content = apply_filters('the_content', $content);

If it's used on a post, the main problem here is that the post MUST NOT belong to one of the categories specified by the shortcode to avoid infinite nested loop.

When the post that belong to one of the categories is at first level of depth, the management of this is done with:

if (is_single()) {
    if (in_category($category_slug_array)) {
        // The function must not proceed with this post !!!
        $out = '<div>To proceed inside a post, the post MUST not belong to one of the categories asked by "category_slug_list" option, to avoid infinite nested loop...</div>';
        return $out;
    }
}

It works because (is_single) is related to the first level of depth and here the first level is a post.

But, for example, when the first level of depth is a page, when one of the posts displayed has its own shortcode there is a problem. As the content of the post is retrieved with get_the_content(), when the shortcode in it is executed, I can't find a way to retrieve the context, as is_single() returns false because it's related to the root page, and not the current post from which we got the value of get_the_content().

Example:

Root Page body with [shortcode category_slug_list="category_slug2"]
  =>  post 1 of category with slug2 displayed
      post 2 of category with slug2 displayed
             post 2 body with [shortcode category_slug_list="category_slug2"]
      ...
      ...
      post n of category with slug2 displayed

From this example, is there a way to get the "post 2" context, I mean verify that it's a post, and then check the in_category function on it? Any clue, Idea, Advice will be welcomed...

1

There are 1 answers

0
BenDev On BEST ANSWER

So, I've finally found a solution to this:

The only way I've found was to be able to pass the post id as attribute to the nested shortcode.

In the shortcode function, in the posts loop, I use str_ireplace in the post content to add attribute if the shortcode is found:

$content = str_ireplace("[shortcode-function-name",'[shortcode-function-name post_id="'.$post->ID.'"',$content);

So, at the beginning of the shortcode function, I retreive the post_id attribute:

extract(shortcode_atts(array(
        "post_id" => '',
        "other_attribute" => 'default_value',
        ...
        ...
        "last_attribute" => 'default_value'
    ), $atts));

And then, in addition to the first check in the case of root post, I can now check with the post ID:

if ($post_id) {
    if (in_category($category_slug_array,$post_id)) {
        // The function must not proceed with this post !!!
        $out = '<div>To proceed inside a post, the post MUST not belong to one of the categories asked by "category_slug_list" option, to avoid infinite nested loop...</div>';
        return $out;
    }
}

In case it can help someone who try to work with a shortcode function inside a nested loop depending on post specificities...