Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

In a plugin class I want to provide simple fields for public data: email, phone number, Twitter etc. The list can be extended.

See the plugin Public Contact Data on GitHub for details.

To keep the usage simple, I also want to offer shortcodes which are easy to type:

  • [public_email]
  • [public_phone]
  • [public_something]

The only difference is the second part. I don’t want further arguments for the shortcodes because they are error prone. So I register one shortcode handler for all fields in my plugin class:

foreach ( $this->fields as $key => $value )
{
    add_shortcode( 'public_' . $key, array( $this, 'shortcode_handler' ) );
}

Now shortcode_handler() has to know which shortcode has been called. My question is: How do I do this?

My current workaround is another function:

protected function current_shortcode()
{
    $backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS );
    return $backtrace[3]['args'][0][2];
}

This … works for the_content(). But it is neither elegant nor robust.
I have read wp-includes/shortcodes.php, but I cannot see right now how to do it better.

share|improve this question
1  
You have me all curious now. I'll look into this shortly. I know shortcodes.php is just a bunch of functions, if it were written correctly using OOP it would no doubt have had a current_shortcode class variable and made everything easier. To my knowledge Wordpress only stores all of the shortcodes and callbacks in an array, I wonder if there is a way to make it store each shortcode into a variable as it's processed and without hacking core files? –  DigitalSea Feb 20 '12 at 7:47
    
@toscho Agreed, I think that's really a problem, a remodeling in the way that shortcodes are done, (embracing more OOP like Widgets) should be in mind. I would love to help on that, and later on send this as a update to the Core. –  Webord Feb 20 '12 at 9:33
    
@brasofilo Right, I did that just now. –  toscho Jul 4 '13 at 23:00

2 Answers 2

up vote 1 down vote accepted

This is untested, but the callback function is provided with an array of arguments, $args which give (if any) the paramters provided with the shortocode. The zeroth entry sometimes contains the name of the shortcode used (e.g. public_email). By sometimes I mean...

The zeroeth entry of the attributes array ($atts[0]) will contain the string that matched the shortcode regex, but ONLY if that differs from the callback name, which otherwise appears as the third argument to the callback function.

(See the Codex). For your purposes then $atts[0] will contain either public_email, public_phone etc.

function shortcode_handler($atts,$content=NULL){
     if(!isset($atts[0]))
         return; //error?

     switch($atts[0]):
         case 'public_email':
              //deal with this case
              break;
         case 'public_phone':
              //deal with this case
              break;
         case 'public_something':
              //deal with this case
              break;
     endswitch;   
}
share|improve this answer
    
Ah, I remember, I’ve run into something similar a long time ago. In my case it is the third argument for the shortcode handler. The first is $args, the second $content and the last one the shortcode! –  toscho Feb 20 '12 at 11:15
    
Really? The shortcode differs from the callback name 'shortcode_handler'... I would have thought it would have been given in the $args. But if that works for you... :D. –  Stephen Harris Feb 20 '12 at 11:44

Based on Stephen Harris answer I made my catch all handler accept a third argument, which is the shortcode name:

/**
 * Handler for all shortcodes.
 *
 * @param  array  $args
 * @param  NULL   $content Not used.
 * @param  string $shortcode Name of the current shortcode.
 * @return string
 */
public function shortcode_handler(  $args = array (), $content = NULL, $shortcode = '' )
{
    $key = $this->current_shortcode_key( $shortcode );
    $args['print'] = FALSE;
    return $this->action_handler( $key, $args );
}

/**
 * Returns the currently used shortcode. Sometimes.
 *
 * @return string
 */
protected function current_shortcode_key( $shortcode )
{
    return substr( $shortcode, 7 );
}

See it in action in the plugin linked in my question.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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