Creating Shortcodes

A shortcode is self-contained functionality that fits well into the context of reusable content with configurable options typically coupled with uploaded content. A shortcode could be an image, a Flash object, a map, a video, etc. Shortcodes qualify as content but are not text or layout classes. Shortcodes are part of the default Content widget that comes with Barebones CMS. The Image (bb_image) Shortcode is included with the default Barebones CMS installation. Additional Shortcodes are available for further enhancing the Content Editor.

Each shortcode consists of three parts: Visual icons, a configuration dialog, and a way to display the content to the user. This documentation covers each aspect in-depth. If you are reading this, it is assumed that you want to create your own shortcode.

Your First Shortcode

Unlike Widgets, there is no way to automatically create a Shortcode. The best approach is to download a few and look at the source code of the official Image Shortcode to get a feel for what this entails. It helps to have written header and footer widgets prior to authoring a Shortcode.

The first thing to note is that Shortcodes are part of the Content widget. All Shortcodes in the system are loaded when the Content widget loads, regardless of whether or not they are used. This should emphasize the importance of keeping Shortcodes as small and lightweight as possible. The Image Shortcode, for example, is about 8KB in size. Obviously, most Shortcodes will need to be more advanced.

It is recommended that Shortcodes be developed locally until they are ready for a production environment. The use of an external text editor is highly recommended while creating the Shortcode.

Creating the Icons

Toolbar and Content Editor icons.
Toolbar and Content Editor icons.

Every Shortcode has two icons: A tiny 24x24 pixel PNG icon for the WYMEditor (Content Editor) toolbar and a 128 pixel wide PNG icon for the main editing area and for display in the preview area (height of the large icon doesn't matter). Both icons should preferably be 8-bit, semi-transparent PNGs and have a modern, clean look-and-feel.

The general naming scheme for Shortcode icons is '[shortcodename]_small.png' for the small icon and '[shortcodename]_large.png' for the large icon. While the naming scheme doesn't really matter, it should not conflict with other files in the 'widgets/bb_content/shortcodes/' directory.

Setting Up The Shortcode

The next step in creating a Shortcode is to register it with the Content widget. There are two ways to do this. The preferred method is to create a single PHP file in 'widgets/bb_content/shortcodes/'. The 'bb_' prefix for filenames and internal Shortcode names is reserved for official Barebones CMS Shortcodes. Other than that, the filename doesn't really matter. If you want to use a prefix, use 'sc_'.

In the event you need multiple PHP files for a single Shortcode, create a subdirectory within 'widgets/bb_content/shortcodes/' and put the main Shortcode into 'index.php' along with all supporting files (e.g. the icons). An example path could therefore be, 'widgets/bb_content/shortcodes/sc_mine/index.php'.

Many Shortcodes will require using multiple support files, typically of the third-party Javascript variety. These files should go into a subdirectory off the root 'support' subdirectory.

Once the base file is created, it is time to register the Shortcode with the Content widget. Here is how the default Image Shortcode that comes with the default Content widget does this:

<?php
	// Barebones CMS Content Widget Shortcode Handler for Images
	// (C) 2010 CubicleSoft.  All Rights Reserved.
	// Icons are licensed from the IconShock library.

	if (!defined("BB_FILE"))  exit();

	$g_bb_content_shortcodes["bb_image"] = array(
		"name" => "Image",
		"toolbaricon" => $g_fullurl . "/bb_image_small.png",
		"mainicon" => $g_fullurl . "/bb_image_large.png",
		"cache" => true,
		"security" => array(
			"" => array("Images", "Defines who can add and edit images."),
			"local" => array("Local Images", "Defines who can preview images on the local server."),
			"remote" => array("Remote Images", "Defines who can preview images on remote servers.")
		)
	);

	class bb_content_shortcode_bb_image extends BB_ContentShortcodeBase
	{
		...
	}
?>

The global $g_bb_content_shortcodes is an array that tracks all active Shortcodes. Each PHP file that gets included gets a chance to modify this array. Each Shortcode should only add one item to the array. Note that the base name in the array above is specified as "bb_image". This name is used to locate the class name of the same name prefixed with 'bb_content_shortcode_'. The base name must be capable of being used in a PHP class name.

There are a number of required options in the array:

Before the Shortcode is included, $g_fullurl is calculated as the URL to use when displaying the icons. This global allows both 'toolbaricon' and 'mainicon' to easily point at the desired URLs for correct display.

The 'cache' option is used to tell the Content widget that the output can be cached until the Shortcode content is changed within the editor. Most Shortcodes should be able to use a value of true. If all Shortcodes in a Content widget instance are cached, then the Content widget caches the entire content that gets generated. This results in even faster performance when the page has to be generated.

Configuring shortcode security.
Configuring shortcode security.

The 'security' option is what gets displayed in the 'Configure Security' dialog of the Content widget. These options are site-wide. In the image above, you can see how the Image Shortcode options appear. Compare these to the $g_bb_content_shortcodes 'security' options to see how to set these up correctly. At a minimum, every Shortcode must have at least the unnamed (empty string - "") option to define who can use the Shortcode.

Creating the Configuration Dialog

After setting up the overall structure and registering the basic Shortcode options with the Content widget, it is time to get to work on the dialogs the user will interact with. To do this, define two functions inside your class:

<?php
	...
	class bb_content_shortcode_bb_image extends BB_ContentShortcodeBase
	{
		private function GetInfo($sid)
		{
			global $bb_widget;

			$info = $bb_widget->shortcodes[$sid];
			if (!isset($info["src"]))  $info["src"] = "";
			if (!isset($info["alt"]))  $info["alt"] = "";
			if (!isset($info["opt-caption"]))  $info["opt-caption"] = 0;
			if (!isset($info["opt-caption-width"]))  $info["opt-caption-width"] = 0;

			return $info;
		}

		...

		public function ProcessShortcodeBBAction($parent)
		{
			global $bb_dir, $bb_pref_lang, $bb_revision_num;

			$info = $this->GetInfo($parent->GetSID());

			...

			if ($_REQUEST["sc_action"] == "bb_image_configure_submit")
			{
				...
				if (!$parent->SaveShortcode($info))  BB_PropertyFormError("Unable to save the shortcode.");

?>
<div class="success">Options saved.</div>
<script type="text/javascript">
CloseProperties();
ReloadIFrame();
</script>
<?php
				...
			}
			else if ($_REQUEST["sc_action"] == "bb_image_configure")
			{
				BB_RunPluginAction("pre_bb_content_shortcode_bb_image_configure");

				$desc = "<br />";
				$desc .= $parent->CreateShortcodePropertiesLink("Upload/Transfer Image", "bb_image_upload");

				$options = array(
					"title" => "Configure Image",
					"desc" => "Configure the image or upload/transfer a new image.",
					"htmldesc" => $desc,
					"bb_action" => $_REQUEST["bb_action"],
					"hidden" => array(
						"sid" => $parent->GetSID(),
						"sc_action" => "bb_image_configure_submit"
					),
					"fields" => array(
						array(
							"title" => "Image URL",
							"type" => "text",
							"name" => "src",
							"value" => $info["src"],
							"desc" => "The URL of this image."
						),
						...
					),
					"submit" => "Save",
					"focus" => true
				);

				BB_RunPluginActionInfo("bb_content_shortcode_bb_image_configure_options", $options);

				BB_PropertyForm($options);

				BB_RunPluginAction("post_bb_content_shortcode_bb_image_configure");
			}
		}
	}
?>

The first function, called GetInfo(), is not required but highly recommended. It is extremely useful to preload default settings into a Shortcode when they aren't defined. The other function, ProcessShortcodeBBAction() is required. $parent is the $this pointer of the caller. There are several very useful functions within the Content widget and the $parent variable makes it convenient to access those functions.

When the user first double-clicks on the placeholder icon (the big icon) in the editor, ProcessShortcodeBBAction() is called after setting $_REQUEST["sc_action"] to $g_bb_content_shortcodes["base_name"] . "_configure". So, in the case of "bb_image", 'sc_action' gets set to "bb_image_configure".

Note that 'sc_action' is the entry point into the Shortcode, not 'bb_action'. 'bb_action' is reserved for the main editor and widgets. Shortcodes operate inside the Content widget.

At this point, a Shortcode can pretty much do whatever it needs to do. The typical approach is to have an upload link created with $parent->CreateShortcodePropertiesLink() and a dialog created with BB_PropertyForm(). If you are familiar with widgets, you probably already know how to use CreateWidgetPropertiesLink() and CreateWidgetPropertiesJS(). The Shortcode link and Javascript object creation calls are similar.

When creating a dialog, the highlighted lines above MUST exist. BB_PropertyForm()'s default 'bb_action' target must be overridden with the current $_REQUEST["bb_action"]. Then, to target the correct Shortcode, a 'sid' of $parent->GetSID() must be passed. Finally, a target 'sc_action' must be specified. This combination targets the specific Content widget instance, a specific Shortcode instance within the Content widget instance, and a specific command within the Shortcode.

When the user clicks "Save" in the configuration dialog, it is usually a good idea to save the configuration. This is accomplished with the $parent->SaveShortcode() function where you pass in a modified array of information - usually an array from the GetInfo() function that gets modified. Do NOT create a new array as the data stored in $bb_widget->shortcodes has private data that identifies the Shortcode (private data has an underscore '_' prefix). Modifying or eliminating Shortcode private data will cause the Shortcode to break.

Once again, the best source code reference to follow is the Image Shortcode that comes with the default Content widget.

Generating Content

Once you have created a basic configuration dialog and that piece of the puzzle is put together, it is time to start working on generating the content for both the preview pane in the main Barebones CMS editor and the frontend (what users see). To do this, add the GenerateShortcode() function to your class:

<?php
	class bb_content_shortcode_bb_image extends BB_ContentShortcodeBase
	{
		...

		public function GenerateShortcode($parent, $sid, $depth)
		{
			global $g_bb_content_shortcodes;

			$info = $this->GetInfo($sid);
			if ($info["src"] == "")  return "";

			if ($parent !== false && !$parent->IsShortcodeAllowed("bb_image", BB_IsLocalURL($info["src"]) ? "local" : "remote"))  $info["src"] = $g_bb_content_shortcodes["bb_image"]["mainicon"];

			$data = "";
			if ($info["opt-caption"])  $data .= '<div class="image-caption-wrap"' . ($info["opt-caption-width"] ? ' style="width: ' . $info["opt-caption-width"] . 'px;"' : '') . '><div class="image-caption-image">';
			$data .= '<img src="' . htmlspecialchars($info["src"]) . '"' . ($info["alt"] != "" ? ' alt="' . htmlspecialchars($info["alt"]) . '"' : '') . ' />';
			if ($info["opt-caption"])  $data .= '</div><div class="image-caption-text">' . htmlspecialchars($info["alt"]) . '</div></div>';

			return $data;
		}

		...
	}
?>

This function takes three parameters and requires a string to be returned containing the content to output. This function runs in the context of a BB_HTMLTransformForWYMEditor() callback, so there are a few limitations on what can be accomplished within the function. Basically, the configuration should be completely set up in advance so that this function has minimal work to do.

When this function is also called in the context of the main Barebones CMS editor preview frame, $parent will not be a boolean of false. When inside the editor, this offers the opportunity to check against the site-wide Shortcode security settings for the Shortcode and do something different if the user is not allowed to view the Shortcode in all its impressiveness. This check is done with a call to $parent->IsShortcodeAllowed().

This concludes the basic Shortcode documentation. The rest of this page consists of dull technical documentation on the various aspects of Shortcode development.

Content Widget Functions

The Content widget provides a number of useful functions that Shortcodes can and should utilize wherever possible. Several of these functions were mentioned already in the documentation above. These functions are accessible by using the $parent variable that is passed into the Shortcode handlers. $parent is typically only available/relevant in the context of the main Barebones CMS editor.

$parent->GetSID()

Parameters: None.

Returns: An integer containing the current Shortcode identifier.

This function retrieves the current Shortcode identifier. This can be used to retrieve the Shortcode configuration from the $bb_widget->shortcodes array or as part of a BB_PropertyForm() $options array.

$parent->CreateShortcodeUploader(...)

Parameters:

Returns: Nothing.

Example:

<?php
	...
	else if ($_REQUEST["sc_action"] == "bb_image_upload")
	{
		$parent->CreateShortcodeUploader("", array(), "Configure Image", "Image", "image", "*.png;*.jpg;*.gif", "Web Image Files");
	}
	...
?>

This function generates a standard file upload/transfer dialog for a Shortcode. By using this function, about 60 lines of common, dense, error-prone code are eliminated.

$parent->CreateShortcodePropertiesLink($title, $sc_action, ...)

Parameters:

Returns: A string containing a valid hyperlink targeting a Shortcode 'sc_action' handler. Includes surrounding 'a' tags.

This function is nearly identical to BB_CreateWidgetPropertiesLink() but adds the active Shortcode identifier. Creates a valid link that loads a property form (dialog) via AJAX.

$parent->CreateShortcodePropertiesJS($sc_action, ...)

Parameters:

Returns: A string containing a Javascript object.

This function is nearly identical to BB_CreateWidgetPropertiesJS() but adds the active Shortcode identifier. Creates a Javascript object suitable for LoadProperties() calls. Can also be used to generate load/save callback objects for the reusable components (Code Editor, Content Editor, etc.), which are typically generated using $full set to true.

$parent->IsShortcodeAllowed($sname, $key)

Parameters:

Returns: A boolean of true if the user has the permission specified by $key, false otherwise.

This function checks $g_bb_content_shortcodes[$sname]["security"][$key] against an internally managed array ('widgets/bb_content/security.php') and the currently logged in user type to determine if the user has the specified permission.

$parent->RegenerateContent($forcesave)

Parameters:

Returns: A boolean of true if the content was successfully generated, false otherwise.

This function calls BB_HTMLTransformForWYMEditor() to prepare output to the end-user. If it is able to be cached or $forcesave is true, BB_SaveLangPage() is called. Shortcodes should call $parent->SaveShortcode() instead of this function.

$parent->SaveShortcode($info)

Parameters:

Returns: A boolean of true if the information was successfully saved and the content generated, false otherwise.

This function saves the state of Shortcode information and regenerates the content.

BB_ContentShortcodeBase

All Shortcodes should extend the base class BB_ContentShortcodeBase. This provides the necessary framework for proper operation of the Shortcode and communication with the Content widget.

What follows is the list of functions that you may derive from inside your Shortcode. GenerateShortcode() and ProcessShortcodeBBAction() are the two functions that are most commonly used.

Class names must be named 'bb_content_shortcode_' . [basename] where '[basename]' is the string used in the $g_bb_content_shortcodes["basename"] definition for the Shortcode.

GenerateShortcode($parent, $sid, $depth)

Parameters:

Returns: A string to output to the browser.

This function is called by the Content widget when processing content for output to the browser and a Shortcode image placeholder is encountered. The image placeholder is replaced with the data returned from this function.

ProcessShortcodeAction($parent)

Parameters:

Returns: Nothing.

This function is called when there is an 'action' parameter passed into the script targeting a Shortcode. Useful for Shortcodes that output interactive forms and need to process the result.

Since this does not operate in the context of the main Barebones CMS editor, not all $parent->...() functions are valid. Anything that displays output in the editor won't work.

ProcessShortcodeBBAction($parent)

Parameters:

Returns: Nothing.

This function manages all of the main Barebones CMS editor interactions. It is initially called when the user double-clicks on the placeholder icon (the large icon) in the Content Editor and assigns the string [basename] . "_configure" to $_REQUEST["sc_action"] (e.g. "bb_image_configure"). The intended purpose of the initial call is to create a dialog with BB_PropertyForm() but literally anything is possible.

When using BB_PropertyForm() in this function, Shortcodes need to specify several additional parameters. See the section "Creating the Configuration Dialog" on this page for details.

© CubicleSoft