2

I've searched many places and tried many ways for this but no success.

I have a shortcode in my WP Theme like;

[recent_posts layout="thumbnails-on-side" columns="4" number_posts="4" offset="" cat_slug="" exclude_cats="" thumbnail="yes" title="no" meta="no" excerpt="no" excerpt_length="35" strip_html="yes" animation_type="0" animation_direction="down" animation_speed="0.1" class="" id=""][/recent_posts]

(It is Avada theme's recent posts shortcode). In the core, this shortcode executes

WP_Query( $args )

function to get posts. But this shortcode cannot be used with Custom Post Types because coders didn't put 'post_type' attribute to shortcode $args (so because of default value is 'posts', shortcode only fetches standard posts).

As a result, i would like to extend/define new extended version of this shortcode for adding 'post_type' attribute as a variable (because i would like to use it for many custom post types). How can i do that? Thanks.

  • 1
    I think there is no way. You have to ask theme developers to add post_type option or make possible to add custom arguments to the shortcode. – cybmeta May 2 '15 at 23:39
  • 1
    Maybe you could add code examples to your question and make it independent of your paid theme (third party plugins/themes are off topic)? – birgire May 3 '15 at 1:52
  • 1
    @birgire Actually you're right but i don't know is this breaks the license because code seems to be coded by theme authors in custom way so i decided to try Pieter's second advise. But additionally, I'll ask to authors for code sharing, if they said no problem, I'll update question. – Alper May 3 '15 at 11:07
4

Without seeing your code it is difficult to give you an exact answer. There is the shortcode_atts_{$shortcode} filter that was introduced in Wordpress 3.6. All attributes is run through this filter. It has to be noted that the $shortcode parameter needs to be set in shortcode_atts. I haven't seen shortcodes yet that has this parameter set though.

Your problem here is actually bigger that just the attributes as you will need to add the attribute and the post_type parameter to your query arguments. If the author did not supply a custom filter for the query arguments, then you are at a dead end street.

IMO, you have two choices here

  • Contact the theme author and ask him to at the relevant code to the shortcode in his next update. I don't think that he/she will have an issue as this adds value to the shortcode

  • Create a child theme and copy the shortcode to the child theme. Modify the shortcode as needed, and remember to change the function name and shortcode name accordingly. This way you will have a shortcode that fits your needs

| improve this answer | |
  • second way seems to be easier for now because i don't know when next version will be released. Thanks for help. – Alper May 3 '15 at 11:00
  • My pleasure. Enjoy :-) – Pieter Goosen May 3 '15 at 11:18
4

Here's just an addition to the answer by @PieterGoosen.

There are few methods how one could modify the post type of WP_Query, that's inside a shortcode. Let's assume it's [recent_posts].

Method A) If the shortcode uses the third parameter of the shortcode_atts() (as @PieterGoosen mentioned) for example wpse, then:

/**
 * Method A: Using the shortcode_atts_$shortcode filter + pre_get_posts action
 */

add_filter( 'shortcode_atts_wpse', function ( $out, $pairs, $atts )
{
    if( isset( $atts['post_type'] ) && $post_type = $atts['post_type'] )
    {
        add_action( 'pre_get_posts', function ( $q ) use ( $post_type )
        {
            static $activated = false;
            if( ! $activated )
            {
                $q->set( 'post_type', santize_key( $post_type ) );
                $activated = true;
            }
        }
    }       
    return $out;
} );

Here you can see my other answer on how to use this filter.

Method B) Else, we can re-register the shortcode with a new callback.

Change it from old_recent_posts to new_recent_posts:

/**
 * Method B: Re-register the shortcode
 */

add_action( 'after_setup_theme', function()
{
    if( function_exists( 'old_recent_posts' ) )
    {
        remove_shortcode( 'recent_posts', 'old_recent_posts' );
        add_shortcode(    'recent_posts', 'new_recent_posts' );
    }

} );

function new_recent_posts( $atts = [], $content = '' )
{
    if( isset( $atts['post_type'] ) && $post_type = $atts['post_type'] )
    {
        add_action( 'pre_get_posts', function ( $q ) use ( $post_type )
        {
            static $activated = false;
            if( ! $activated )
            {
                $q->set( 'post_type', santize_key( $post_type ) );
                $activated = true;
            }
        }
    }       
    return old_recent_posts( $atts = [], $content = '' );
}

Here you can see how @toscho replaces the shortcode callback, in the same question as my linked answer above.

Note that I didn't test this, but hopefully you can adjust this to your needs.

| improve this answer | |
  • Nice extention :-) – Pieter Goosen May 3 '15 at 11:27
  • Thanks @PieterGoosen. I think you're right about few themes using the third parameter of the shortcode_atts() function. Many of them also use the extract method and I'm afraid that some even don't bother to sanitize the user input ;-) – birgire May 3 '15 at 12:13
  • Let me try second one, because I've tried your first way ( wordpress.stackexchange.com/a/95971/26350 ) but no success and i didn't see any shortcode_atts support in code. Thanks.. – Alper May 3 '15 at 12:21
  • Hmmm, another problem is this shortcode is coded by OOP technique so i couldn't access via function name. You can find logic here : 'class FusionSC_RecentPosts' wraps the shortcode and construction starts with 'public function __construct() {' After than, 'add_shortcode( "recent_posts", array( $this, "render" ) );' so render function executing to show the result/execute the WPQuery function. How can i access this function from 'functions.php' to extend it? Thanks again. – Alper May 3 '15 at 16:24
  • How is FusionSC_RecentPosts instantiated? Is the instance globally accessable? You might also try do_shortcode( '[recent_posts ...]' ) instead of using the old shortcode callback. @Alper – birgire May 3 '15 at 16:36

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.