-
Notifications
You must be signed in to change notification settings - Fork 16
Create your own shortcodes using the base class.
In addition to providing ready shortcakes, this plug-in is also amazing because it includes a base class that can help you implement new shortcodes to follow a consistent pattern.
The base class Shortcode
is under namespace Shortcake_Bakery\Shortcodes
. Nevertheless, your plugin is not part of shortcake-bakery. We therefore recommend that you do not enter this namespace in your code. Instead, do the following when you want to extend the base class:
class Your_Shortcode extends Shortcake_Bakery\Shortcodes\Shortcode {
# code
}
Create the public static function get_shortcode_ui_args()
. This function
should return an array()
that may contain the following indexes:
- label: Display label. String. Required.
- listItemImage: Icon/attachment for shortcode. Optional. src or dashicons-$icon. Defaults to carrot.
-
attrs: Available shortcode attributes. Required. Array. Attribute model expects
attr
,type
andlabel
indexes. - label: The attribute display label. String. Required.
- attr: The attribute unique name. String. Required.
-
type: Supported field types. String. Required. Types include
text
,checkbox
,textarea
,radio
,select
,email
,url
,number
,date
,attachment
andpost_select
. - Additional attributes can be found in the Shortcake/dev.php sample file.
This is an example of the implementation of the shortcode for posts and videos from @Facebook:
class Facebook extends Shortcake_Bakery\Shortcodes\Shortcode {
public static function get_shortcode_ui_args() {
return array(
'label' => esc_html__( 'Facebook', 'your-plugin-textdomain' ),
'listItemImage' => 'dashicons-facebook',
'attrs' => array(
array(
'label' => esc_html__( 'URL', 'your-plugin-textdomain' ),
'attr' => 'url',
'type' => 'text',
'description' => esc_html__( 'Full URL to the Facebook Post or Video', 'your-plugin-textdomain' ),
),
),
);
}
# ...
}
Note that labels and descriptions can't be hardcoded. Always use the esc_html__
function of WordPress and create a .po language file for your plugin with the respective translations.
The public static function callback
will be the responsible for generating the output of your shortcode. This function must receive two arguments. $attrs
receives an array
with the values entered by the user when inserting a shortcode on Edit Post screen. The same goes for $content
, that receives any inner content for the shortcode, but it is optional.
Basically, this function must do the following:
- Test whether the mandatory arguments were informed. If not, return an empty string;
- Use regular expressions and other techniques to detect whether the arguments are valid and suitable to generate the output code; ** Optionally generate some visual feedback for users with ability to edit posts if some argument is invalid or inappropriate.
- If necessary, enqueue scripts or styles that ensure proper rendering code. Obviously, these scripts and/or styles need to be registered on the
'init'
action, which show through. - Finally, return the code.
Take this example of Facebook shortcode callback function and try to identify each of the steps above:
class Facebook extends Shortcake_Bakery\Shortcodes\Shortcode {
public static function get_shortcode_ui_args() {
# we have done this before...
}
public static function callback( $attrs, $content = '' ) {
if ( empty( $attrs['url'] ) ) {
return '';
}
if ( ! preg_match( '#https?://(www)?\.facebook\.com/[^/]+/posts/[\d]+#', $attrs['url'] ) && ! preg_match( '#https?://(www)?\.facebook\.com\/video\.php\?v=[\d]+#', $attrs['url'] ) ) {
if ( current_user_can( 'edit_posts' ) ) {
return '<div class="shortcake-bakery-error"><p>' . sprintf( esc_html__( 'Invalid Facebook URL: %s', 'shortcake-bakery' ), esc_url( $attrs['url'] ) ) . '</p></div>';
} else {
return '';
}
}
wp_enqueue_script( 'facebook-api' );
$out = '<div id="fb-root"></div>';
$out .= '<div class="fb-post" data-href="' . esc_url( $attrs['url'] ) . '" data-width="350px" data-true-height="550px" data-true-width="350px"><div class="fb-xfbml-parse-ignore"></div></div>';
return $out;
}
}
Remember: in callback functions, you have to always return, not echo.
In your theme or plugin, add a filter called 'shortcake_bakery_shortcode_classes'
with a callback function that takes an array
of $classes
, add the desired class names and then return it. Example:
add_filter( 'shortcake_bakery_shortcode_classes', 'foo_filter_shortcode_classes' );
function foo_filter_shortcode_classes( $classes ) {
$classes[] = 'Shortcake_Bakery\Shortcodes\Foo';
return $classes;
}
The plugin shortcode classes are autoloaded by the autoload_shortcode_classes
function.
In scenarios where your shortcode generates an embed code, or even when you want to avoid using HTML tags in the content while editing it, you can use public static function reversal
to turn embed code or some HTML tags into a proper shortcode.
For this, you probably need to use regular expressions and substitutions, in functions such as preg_match_all
, str_replace
, array_keys
, array_values
and, as it should return a string in shortcode format, you need to know what is the current tag shortcode. For this you must use self::get_shortcode_tag();
.
The function, which necessarily takes a string with the entire contents of the post, should return a string with the substitutions made. See the implementation of reversal taking as an example - again - the Facebook shortcode:
class Facebook extends Shortcake_Bakery\Shortcodes\Shortcode {
public static function get_shortcode_ui_args() {
# we have done this before...
}
public static function callback( $attrs, $content = '' ) {
# and we did that too, remember?
}
public static function reversal( $content ) {
if ( preg_match_all( '#<div id="fb-root"></div><script>[^<]+</script><div[^>]+href=[\'\"]([^\'\"]+)[\'\"].+</div>(</div>)?#', $content, $matches ) ) {
$replacements = array();
$shortcode_tag = self::get_shortcode_tag();
foreach ( $matches[0] as $key => $value ) {
$replacements[ $value ] = '[' . $shortcode_tag . ' url="' . esc_url( $matches[1][ $key ] ) . '"]';
}
$content = str_replace( array_keys( $replacements ), array_values( $replacements ), $content );
}
return $content;
}
}
Remember that implementing this function is not something obligatory, and often is not necessary but, when appropriate, makes that shortcode the most amazing shortcode yet :)
In some situations, your shortcode may need to perform some additional actions. Most of the time, enqueuing some essential script or style so that shortcode is displayed properly.
For this, you can create the public static function setup_actions()
. This function allows the class to register its own actions. It fires after the shortcode has been registered on init
.
There's no need to receive any parameters or return anything. But you can use add_action
and any other convenient functions. See the example and - yes - it's Facebook again.
class Facebook extends Shortcake_Bakery\Shortcodes\Shortcode {
public static function get_shortcode_ui_args() {
# we have done this before...
}
public static function callback( $attrs, $content = '' ) {
# and we did that too, remember?
}
public static function setup_actions() {
add_action( 'init', 'Shortcake_Bakery\Shortcodes\Facebook::foo' );
}
public static function foo() {
wp_register_script( 'facebook-api', '//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.0' );
}
}
You may have noticed that, in addition to the setup_actions()
function we mentioned, there is a public static function foo()
. That's because there was a need to create a callback function for the 'init'
hook.
You can create static functions as well you want to serve as hooks for setup_actions()
. But do not forget to use self-explanatory names and document the new function
. And... of course, do not use "foo" as a function name! 😁
Would you like to see as was the entire code of this shortcode? Read the code of class-facebook.php. Note that, there, namespace
is in the beginning of the file because - uhm - this shortcode is already built into the plug-in.
You can also use the code from the base class as a reference to create your own shortcodes. Good job!