Creating Widgets

A widget is usually self-contained, custom functionality on a page that falls outside the scope of a shortcode and can be reused. Barebones CMS comes with three default widgets: Code, Layout, and Content. Each of these three widgets offer unique, self-contained functionality but integrate tightly into the CMS infrastructure.

The most common reason to create a widget is to create header and footer widgets. This documentation covers every key aspect of creating a widget.

Your First Widget

A widget consists of at least frontend (what users see) and, optionally, editor (backend) components. Widgets are written in PHP and usually leverage the Barebones CMS library (functions, global variables, etc). Widgets are usually built using an external editor but can be built using the Code Editor.

Creating the Widget

'Create New Widget' menu item.
'Create New Widget' menu item.

Creating a new widget is best done with the built-in widget creation tool. This tool speeds up the widget development process by generating correct code. To use this tool, go into the editor on any page and click the 'Create New Widget' link located under 'Site Options'.

A dialog will appear with two fields to fill in.

The first field is the base name of the widget. This name will be used for the class name and various other aspects of the widget. End-users will never see this name as it is always internal. An example of an appropriate base name could be 'site_header' (without the quotes).

The other field to fill in is the display name to use throughout the editor. Only those who have access to the main editor will see this name. An example of a display name could be 'Site Header' (again without the quotes).

The 'Create New Widget' dialog.
The 'Create New Widget' dialog.

Upon clicking 'Create', the widget will be created and placed into the 'widgets' subdirectory of your Barebones CMS installation. This process consists of creating a new directory based on the base name of the widget and a 'index.php' file. Open up 'index.php' in your favorite text editor and let's see what your new widget looks like:

<?php
	if (!defined("BB_FILE"))  exit();

	$bb_widget->_s = "site_header";
	$bb_widget->_n = "Site Header";
	$bb_widget->_key = "";
	$bb_widget->_ver = "";

	class site_header extends BB_WidgetBase
	{
		public function Init()
		{
			global $bb_widget;
		}

		public function PreWidget()
		{
			global $bb_widget, $bb_account;

			if ($bb_account["type"] == "dev" || $bb_account["type"] == "design")
			{
				echo BB_CreateWidgetPropertiesLink("Configure", "site_header_configure_widget");
			}
		}

		public function Process()
		{
			global $bb_mode, $bb_widget, $bb_css, $bb_js;

			if ($bb_mode == "head")
			{
			}
			else if ($bb_mode == "body")
			{
			}
		}

		public function ProcessAction()
		{
			global $bb_widget;
		}

		public function ProcessBBAction()
		{
			global $bb_widget, $bb_account, $bb_revision_num;

			if (($bb_account["type"] == "dev" || $bb_account["type"] == "design") && $_REQUEST["bb_action"] == "site_header_configure_widget")
			{
				BB_RunPluginAction("pre_site_header_configure_widget");

				$options = array(
					"title" => "Configure " . $bb_widget->_f,
					"desc" => "Configuration options.",
					"fields" => array(
					),
					"submit" => "Save",
					"focus" => true
				);

				BB_RunPluginActionInfo("site_header_configure_widget_options", $options);

				BB_PropertyForm($options);

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

Did you have a nice heart attack?

Simplifying The Widget

A very simple site header (or footer) generally does not need all of the functionality of the baseline widget that gets generated. You can keep the various functions around if you think you might need them later on, but, for your first widget, trim it down to the bare essentials and add a little content:

<?php
	if (!defined("BB_FILE"))  exit();

	$bb_widget->_s = "site_header";
	$bb_widget->_n = "Site Header";
	$bb_widget->_key = "";
	$bb_widget->_ver = "";

	class site_header extends BB_WidgetBase
	{
		public function Process()
		{
			global $bb_mode, $bb_widget, $bb_page, $bb_langpage, $bb_css, $bb_js;

			if ($bb_mode == "head")
			{
?>
<link rel="/header.css" type="text/css" />
<?php
			}
			else if ($bb_mode == "body")
			{
?>
<div class="slogan">We are the best company EVAR!</div>
<?php
			}
		}
	}
?>

That should be a lot easier to read and comprehend. While parts of this widget aren't considered to be the "best practice" approach, it is a pretty good start. After all, you've got to start somewhere.

The Process() function of a widget is called multiple times by BB_ProcessPage() (located in proc.php) to generate content for each portion of a page. The most common modes ($bb_mode) that are handled by Process() are "head" and "body" for the 'head' and 'body' HTML tags respectively. For most widgets, Process() is used to output content to the correct areas of the page.

This concludes the basic widget documentation. The rest of this page consists of boring technical details of every aspect of developing widgets.

BB_WidgetBase

The BB_WidgetBase object provides baseline functions for a widget to operate properly. By deriving a class from this object, the derived class can use any, all, or none of the functions. If a function does not exist in the derived class, the base class function is called instead. The base class functions do nothing except stop PHP from complaining about a non-existent function.

You can, of course, create other functions that you call internally. It is fairly unlikely that the widget infrastructure will change, so there should never be function name conflicts.

Init()

This function is called immediately after the class instance is created. This provides an opportunity to initialize the class (e.g. load private class variables).

PreWidget()

This function is called within the editor to display a gray box with hyperlinks before Process() is called. This offers an opportunity to provide configuration options for the widget.

This function is not called on the frontend.

Process()

This function is called a number of times while generating page content. The $bb_mode variable can be used to distinguish which mode that BB_ProcessPage() (proc.php) is currently processing.

The define()'d constant 'BB_MODE_EDIT' can be used to differentiate between frontend and editor execution. If it is defined, then BB_ProcessPage() is running in the context of the editor. If it isn't defined, then BB_ProcessPage() is executing in the context of the frontend. The default widgets have examples of how to use this define().

ProcessAction()

This function is called by 'proc.php' when $_REQUEST contains a variable called 'action' (without the quotes). The typical use for this function is to bypass the caching system to process a form. This can also be used to process AJAX requests on the frontend.

By default, this does not output anything. If you wish to output the page's content, you will have to call BB_ProcessPage() yourself.

ProcessBBAction()

This function is called by 'edit.php' when $_REQUEST contains variables called 'bb_action' and 'wid' (without the quotes). The 'wid' variable is the unique widget ID issued to each widget on a page. The process of defining a correct set of variables is error-prone, so it is usually obscured by using the function BB_CreateWidgetPropertiesLink() for URLs and the function BB_CreateWidgetPropertiesJS() for Javascript (typically AJAX) within the current widget.

This function is primarily used for displaying and processing the standard dialog (internally known as the "property form") via the BB_PropertyForm() function.

This function is not called on the frontend.

$bb_widget

During widget development, most widgets will need a place to store configuration data for the widget. This is where $bb_widget comes in. $bb_widget is a wrapper class for managing the configuration of an active widget.

The underscore ('_') prefix is reserved for private Barebones CMS variables inside the widget configuration. You may treat these as read-only access. The only variable you should ever read from the private variables is '_f'.

Creating new configuration options is easy: $bb_widget->option_name_goes_here = "value";

Example configuration:

object(bb_widget_internal)#1 (10) {
  ["_f"]=>
  string(4) "Code"
  ["_m"]=>
  bool(false)
  ["_a"]=>
  string(4) "root"
  ["_id"]=>
  string(14) "bb_code_code"
  ["_file"]=>
  string(17) "bb_code/index.php"
  ["_s"]=>
  string(7) "bb_code"
  ["_n"]=>
  string(4) "Code"
  ["_key"]=>
  string(0) ""
  ["_ver"]=>
  string(0) ""
  ["body"]=>
  string(0) ""
}

What follows is a breakdown of each of the above private Barebones CMS variables.

$bb_widget->_f

Type: String

Example: "My Layout"

This is the display name for the widget instance that should only be displayed to users inside the editor. This is different from widget display name ($bb_widget->_n).

$bb_widget->_m

Type: Boolean

Example: false

This declares if this widget is a master widget. This will always be 'false' for widgets.

$bb_widget->_a

Type: String

Example: "root"

The unique identifier of the parent. For widgets, this will be a master widget. Used primarily to identify orphaned widgets (allows for detaching and attaching).

$bb_widget->_id

Type: String

Example: "bb_code_code"

The unique identifier of this widget. Use the global variable $bb_widget_id instead of this.

$bb_widget->_file

Type: String

Example: "bb_code/index.php"

The relative path and filename of the current widget. Use BB_GetRealPath(ExtractPathname()) to get the path. The full path and filename can be determined with:

<?php
	$fullpath = ROOT_PATH . "/" . WIDGET_PATH . "/" . BB_GetRealPath($bb_widget->_file);
?>

$bb_widget->_s

Type: String

Example: "bb_code"

This is the base (internal) name for the widget.

Should be defined at the start of the widget source code.

$bb_widget->_n

Type: String

Example: "Code"

This is the display name for the widget that should only be displayed to users inside the editor. This is different from widget instance display name ($bb_widget->_f).

Should be defined at the start of the widget source code.

$bb_widget->_key

Type: String

Defines a unique identifier for this widget. Used to determine if an upgrade exists for the widget.

Should be defined at the start of the widget source code.

$bb_widget->_ver

Type: String

Defines the version of this widget. Used to determine if an upgrade exists for the widget.

Should be defined at the start of the widget source code.

Making Configuration Changes

Usually configuration options are presented to the user via BB_PropertyForm(). Once the form is submitted, $bb_widget is modified with the user's desired settings.

Example:

<?php
	$bb_widget->myvar = array("stuff" => array("more", "stuff"));
?>

Once you have modified $bb_widget, it is typically saved by calling BB_SaveLangPage($bb_revision_num). Well-written widgets always check the return value of the global functions.

What's Next

Learn about Global and Reserved Variables and Global Functions you have access to from within a widget.

© CubicleSoft