最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

plugins - How to modify shortcode attributes with data from current post

programmeradmin1浏览0评论

I apologize in advance for my lack of PHP/WP knowledge, and my wordiness in explaining what I'm looking for, but I've been trying to work out a solution for a couple of days now, and I'm just starting to wrap my head around filters and the loop.

Here's what I'd like to accomplish:

A shortcode for a plugin I'm using has an attribute tag "sched" that I would like to make essentially dynamic, changed to the current (custom)post's (custom)category slug. Here's an example of an existing shortcode that works well with the MSTW Schedules and Scoreboards plugin:

[mstw_schedule_table sched="v-football"]

My plan was to set the "sched" attribute's value to "sport" (on all posts) as a placeholder that would be replaced with the current post's "sport" custom category slug. I've set up all "sport" category slugs to correspond with the "sched" values used in the plugin, to ensure that the schedule table displayed on the current post is correct.

Note: All of these custom posts (set up as "team") should only have one "sport" category applied to them: I have set up "sport" categories as a dropdown meta box in admin, like this.

Also Note: I'd like the editable shortcode to be available within the custom post's content, so I can edit other attributes as needed for each post.

Here is what I've tried:

This is the closest I've gotten, but I know that I'm using the wrong filter, or otherwise calling the function at the wrong time. Note that I ran this code in the "single-team.php" file I created for my custom post type, before the loop. I'm aware it should probably be in functions.php or a separate plugin (please advise).

My inspiration:
do_shortcode_tag / get_the_terms

    add_filter( 'do_shortcode_tag', 'wpse_106269_do_shortcode_tag', 10, 4);
    function wpse_106269_do_shortcode_tag( $output, $tag, $attr, $m ) {

        if( $tag === 'mstw_schedule_table' ) {
            //* Do something useful
            if ($attr['sched'] === 'sport-slug') {
                print_r($attr);

                // Get a list of tags and extract their names
                $sport = get_the_terms( get_the_ID(), 'sport' );
                if ( ! empty( $sport ) && ! is_wp_error( $sport ) ) {
                    $sport_slug = wp_list_pluck( $sport, 'slug' );

                    $attr['sched'] = $sport_slug[0];
                }

                echo "<br>";
                print_r($attr);
            }

        }
        return $output;
    }

This outputs:

Array ( [sched] => sport-slug ) 
Array ( [sched] => v-football )

So I know I can change the value of the shortcode's $attr, but I don't know how to replace the original shortcode with the modified one, before it's parsed by the plugin.

I tried using the_content:

// Modify Content of a Post
add_filter('the_content', 'se24265_my_function');
function se24265_my_function( $content )
{
    $write = 'hello world'; 
    $new_content = $write . $content;

        $sport = get_the_terms( get_the_ID(), 'sport' );
        if ( ! empty( $sport ) && ! is_wp_error( $sport ) ) {
            $sport_slug = wp_list_pluck( $sport, 'slug' );

            str_replace("sport-slug", $sport_slug[0], $new_content);
        }
        return $new_content; 
        // outputs hello world
        // outputs inital shortcode without modifications
}

I also thought about running the plugin's shortcode handler function (like this) with a modified argument, but I don't know how to access/modify that argument before it's interpreted out by the plugin.

I've also seen this example where the shortcode is generated within the custom post template...

// Making your custom string parses shortcode
$string = do_shortcode( $string );
// If your string has a custom filter, add its tag name in an applicable add_filter function
add_filter( 'my_string_filter_hook_tag_name', 'do_shortcode' );

... but I'd like to maintain the ability to edit / place the shortcode in different places within each custom post as needed, and I still don't know which filter hook to use (content_edit_pre ?)

Any help would be appreciated. Thanks.

I apologize in advance for my lack of PHP/WP knowledge, and my wordiness in explaining what I'm looking for, but I've been trying to work out a solution for a couple of days now, and I'm just starting to wrap my head around filters and the loop.

Here's what I'd like to accomplish:

A shortcode for a plugin I'm using has an attribute tag "sched" that I would like to make essentially dynamic, changed to the current (custom)post's (custom)category slug. Here's an example of an existing shortcode that works well with the MSTW Schedules and Scoreboards plugin:

[mstw_schedule_table sched="v-football"]

My plan was to set the "sched" attribute's value to "sport" (on all posts) as a placeholder that would be replaced with the current post's "sport" custom category slug. I've set up all "sport" category slugs to correspond with the "sched" values used in the plugin, to ensure that the schedule table displayed on the current post is correct.

Note: All of these custom posts (set up as "team") should only have one "sport" category applied to them: I have set up "sport" categories as a dropdown meta box in admin, like this.

Also Note: I'd like the editable shortcode to be available within the custom post's content, so I can edit other attributes as needed for each post.

Here is what I've tried:

This is the closest I've gotten, but I know that I'm using the wrong filter, or otherwise calling the function at the wrong time. Note that I ran this code in the "single-team.php" file I created for my custom post type, before the loop. I'm aware it should probably be in functions.php or a separate plugin (please advise).

My inspiration:
do_shortcode_tag / get_the_terms

    add_filter( 'do_shortcode_tag', 'wpse_106269_do_shortcode_tag', 10, 4);
    function wpse_106269_do_shortcode_tag( $output, $tag, $attr, $m ) {

        if( $tag === 'mstw_schedule_table' ) {
            //* Do something useful
            if ($attr['sched'] === 'sport-slug') {
                print_r($attr);

                // Get a list of tags and extract their names
                $sport = get_the_terms( get_the_ID(), 'sport' );
                if ( ! empty( $sport ) && ! is_wp_error( $sport ) ) {
                    $sport_slug = wp_list_pluck( $sport, 'slug' );

                    $attr['sched'] = $sport_slug[0];
                }

                echo "<br>";
                print_r($attr);
            }

        }
        return $output;
    }

This outputs:

Array ( [sched] => sport-slug ) 
Array ( [sched] => v-football )

So I know I can change the value of the shortcode's $attr, but I don't know how to replace the original shortcode with the modified one, before it's parsed by the plugin.

I tried using the_content:

// Modify Content of a Post
add_filter('the_content', 'se24265_my_function');
function se24265_my_function( $content )
{
    $write = 'hello world'; 
    $new_content = $write . $content;

        $sport = get_the_terms( get_the_ID(), 'sport' );
        if ( ! empty( $sport ) && ! is_wp_error( $sport ) ) {
            $sport_slug = wp_list_pluck( $sport, 'slug' );

            str_replace("sport-slug", $sport_slug[0], $new_content);
        }
        return $new_content; 
        // outputs hello world
        // outputs inital shortcode without modifications
}

I also thought about running the plugin's shortcode handler function (like this) with a modified argument, but I don't know how to access/modify that argument before it's interpreted out by the plugin.

I've also seen this example where the shortcode is generated within the custom post template...

// Making your custom string parses shortcode
$string = do_shortcode( $string );
// If your string has a custom filter, add its tag name in an applicable add_filter function
add_filter( 'my_string_filter_hook_tag_name', 'do_shortcode' );

... but I'd like to maintain the ability to edit / place the shortcode in different places within each custom post as needed, and I still don't know which filter hook to use (content_edit_pre ?)

Any help would be appreciated. Thanks.

Share Improve this question edited Sep 13, 2017 at 18:01 Peter Arthur asked Sep 13, 2017 at 17:17 Peter ArthurPeter Arthur 581 silver badge10 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 2

Yes, you can filter and modify any 3rd party plugin's shortcode attributes and change the shortcode output according the updated shortcodes

Case Study
For example we have an 3rd party plugin's shortcode usermeta and its required a attribute user_id and we want to modify the user_id attribute value.

The following solution is tested and working 100%.

// hook the custom callback function on the do_shortcode_tag action hook 
add_action( 'do_shortcode_tag', 'update_shortcode_attr_and_output', 1, 4 );


//callback function to filter and modify the usermeta shortcode attr & output
function update_shortcode_attr_and_output( $output, $tag, $attr, $m ) {

         //Filter the shortcode tag
        if (  'usermeta' == $tag && ! isset( $attr['user_id'] ) ) {

            // Update ShortCode Attribute user_id value
            $attr['user_id'] = $this->user_id;

            /**
             * update outup according updated attr
             * Refrence: https://core.trac.wordpress/browser/trunk/src/wp-includes/shortcodes.php?rev=38713#L342
             */
            global $shortcode_tags;
            $content = isset( $m[5] ) ? $m[5] : null;
            $output  = $m[1] . call_user_func( $shortcode_tags[ $tag ], $attr, $content, $tag ) . $m[6];

        }

        return $output;
}

For anyone who might stumble upon this, I've found a solution:

In my particular case, I'm using a single-[taxonomy].php template file, and was able to add the shortcode manually via the WordPress function do_shortcode() instead of modifying a shortcode within the post content.

Here's how I wrote it:

<?php echo do_shortcode( '[mstw_schedule_table sched="'.$sports_slug.'" ]' ); ?>

And here's how I got the $sports_slug to work for me. Previously in the file (outside the loop) :

// Get this post's sport taxonomy - https://wordpress.stackexchange/a/168862/127459
           $sports = get_the_terms($post->ID, 'sport');
           $sports_slug = '';
           if ($sports) { 

                foreach ($sports as $sport) {   
                    $sports_slug = $sport->slug;    
                }
           }

This code is slightly less complicated than what I used ( I needed to select only non-parent sport taxonomies ) but this simplified version may help someone else. These links helped me along the way:

Get custom category name from ID (Answer)

get_the_terms()

发布评论

评论列表(0)

  1. 暂无评论