11

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.

3
  • 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? Commented Feb 20, 2012 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
    Commented Feb 20, 2012 at 9:33
  • @brasofilo Right, I did that just now.
    – fuxia
    Commented Jul 4, 2013 at 23:00

2 Answers 2

3

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;   
}
2
  • 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!
    – fuxia
    Commented Feb 20, 2012 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. Commented Feb 20, 2012 at 11:44
2

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.

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.