4

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?

1 Answer 1

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.

1
  • Yes, just instead of print_r($out) I used foreach ($out as $attribute) { echo $attribute['title']; } Thank you a lot!
    – Lionheart
    Commented Dec 15, 2014 at 6:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.