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.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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;
}
Method 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.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0