$conf, $runtime; function_exists('chdir') AND chdir(APP_PATH); $r = 'mysql' == $conf['cache']['type'] ? website_set('runtime', $runtime) : cache_set('runtime', $runtime); } function runtime_truncate() { global $conf; 'mysql' == $conf['cache']['type'] ? website_set('runtime', '') : cache_delete('runtime'); } register_shutdown_function('runtime_save'); ?>regex - Extract attribute values from every shortcode in post|Programmer puzzle solving
最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

regex - Extract attribute values from every shortcode in post

matteradmin9PV0评论

I have multiple shortcodes in the post:

[section title="first"]
[section title="second"]
[section title="third"]

I want to extract all title values (i.e first, second, third) from external function, that's how I'm trying to do:

$pattern = get_shortcode_regex();
preg_match('/'.$pattern.'/s', $post->post_content, $matches);
    if (is_array($matches) && $matches[2] == 'section') {
        $attribureStr = str_replace (" ", "&", trim ($matches[3]));
        $attribureStr = str_replace ('"', '', $attributeStr);
        $attributes = wp_parse_args ($attributeStr);
        echo $attributes["title"];
    }

The problem is that code extracts value only from first shortcode. How to get it working for every shortcode in the post?

I have multiple shortcodes in the post:

[section title="first"]
[section title="second"]
[section title="third"]

I want to extract all title values (i.e first, second, third) from external function, that's how I'm trying to do:

$pattern = get_shortcode_regex();
preg_match('/'.$pattern.'/s', $post->post_content, $matches);
    if (is_array($matches) && $matches[2] == 'section') {
        $attribureStr = str_replace (" ", "&", trim ($matches[3]));
        $attribureStr = str_replace ('"', '', $attributeStr);
        $attributes = wp_parse_args ($attributeStr);
        echo $attributes["title"];
    }

The problem is that code extracts value only from first shortcode. How to get it working for every shortcode in the post?

Share Improve this question asked Dec 14, 2014 at 19:57 LionheartLionheart 431 silver badge3 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 10

Method #1

If available, I would use the:

shortcode_atts_{$shortcode}

filter to collect the attributes of a given shortcode.

Example:

$text = '
    [gallery]
    [gallery ids="1,2" link="file"]
    [gallery ids="3"]
    [caption id="attachment_6" align="alignright" width="300"]
';

if( class_exists( 'WPSE_CollectShortcodeAttributes' ) )
{
    $o = new WPSE_CollectShortcodeAttributes;
    $out = $o->init( $shortcode = 'gallery', $text )->get_attributes();
    print_r( $out );
}

where our helper class is defined as:

class WPSE_CollectShortcodeAttributes
{
    private $text      = '';
    private $shortcode = '';
    private $atts      = array();

    public function init( $shortcode = '', $text = '' )
    {
        $this->shortcode = esc_attr( $shortcode );
        if( shortcode_exists( $this->shortcode ) 
            && has_shortcode( $text, $this->shortcode ) 
        )
        {
            add_filter( "shortcode_atts_{$this->shortcode}", 
                array( $this, 'collect' ), 10, 3 );
            $this->text = do_shortcode( $text );
            remove_filter( "shortcode_atts_{$this->shortcode}", 
                array( $this, 'collect' ), 10 );
        }
        return $this;
    }

    public function collect( $out, $pair, $atts )
    {
        $this->atts[] = $atts;
        return $out;
    }

    public function get_attributes()
    {
        return $this->atts;
    }
}

The output of our example is:

Array
(
    [0] => Array
        (
            [0] => 
        )

    [1] => Array
        (
            [ids] => 1,2
            [link] => file
            [orderby] => post__in
            [include] => 1,2
        )

    [2] => Array
        (
            [ids] => 3
            [orderby] => post__in
            [include] => 3
        )

)

so for the gallery shortcode, we get some extra attributes as well.

Method #2

But not all shortcodes support the above filter. In that case you could try the following:

/**
 * Grab all attributes for a given shortcode in a text
 *
 * @uses get_shortcode_regex()
 * @uses shortcode_parse_atts()
 * @param  string $tag   Shortcode tag
 * @param  string $text  Text containing shortcodes
 * @return array  $out   Array of attributes
 */

function wpse172275_get_all_attributes( $tag, $text )
{
    preg_match_all( '/' . get_shortcode_regex() . '/s', $text, $matches );
    $out = array();
    if( isset( $matches[2] ) )
    {
        foreach( (array) $matches[2] as $key => $value )
        {
            if( $tag === $value )
                $out[] = shortcode_parse_atts( $matches[3][$key] );  
        }
    }
    return $out;
}

Example:

$text = '
    [gallery]
    [gallery ids="1,2" link="file"]
    [gallery ids="3"]
    [caption id="attachment_6" align="alignright" width="300"][/caption]
';
$out = wpse172275_get_all_attributes( 'gallery', $text );
print_r( $out );

with the output:

Array
(
    [0] => 
    [1] => Array
        (
            [ids] => 1,2
            [link] => file
        )

    [2] => Array
        (
            [ids] => 3
        )

)

I hope you can modify this to your needs.

Post a comment

comment list (0)

  1. No comments so far