Pergunta

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.

Foi útil?

Solução

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;   
}

Outras dicas

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a wordpress.stackexchange
scroll top