A Widgets Bundle widget is a folder with a PHP file that declares the widget, a template that outputs it and an optional LESS stylesheet. The Widgets Bundle builds the widget's form from the fields you declare, then saves and renders the widget for you.
The siteorigin_widgets_widget_folders filter registers a folder of your own widgets, so you can keep them apart from the SiteOrigin widgets:
<?php
function add_my_awesome_widgets_collection( $folders ) {
$folders[] = plugin_dir_path( __FILE__ ) . 'widgets/'; // An absolute path. The slash at the end is required.
return $folders;
}
add_filter( 'siteorigin_widgets_widget_folders', 'add_my_awesome_widgets_collection' );The Widgets Bundle looks for PHP files in each subfolder of a registered folder. It lists every file whose metadata header has a Widget Name field as a widget that users can activate and use in widget areas, Page Builder and the Block Editor.
The extend-widgets-bundle plugin in our so-dev-examples repository is a standard WordPress plugin that uses this filter to add its extra-widgets folder.
Create a folder for your widget, and a PHP file inside it with the same name. Follow the WordPress naming best practices for the file and folder names.
Start the PHP file with a metadata header. The Widgets Bundle uses the header to find files that contain a widget, and it skips any file without a Widget Name field. The other fields are optional, and they give users more information about the widget and its author:
<?php
/*
Widget Name: Hello world widget
Description: An example widget which displays 'Hello world!'.
Author: Me
Author URI: http://example.com
Documentation: http://example.com/hello-world-widget-docs
*/Your widget class extends the SiteOrigin_Widget base class. SiteOrigin_Widget builds on the WordPress Widgets API, so the class needs a constructor that describes the widget. Declare the form fields in a get_widget_form() method, as the example does. Passing $form_options to the constructor also works.
Register the class with siteorigin_widget_register(), passing the widget ID, the path of the widget file and the class name:
class Hello_World_Widget extends SiteOrigin_Widget {
function __construct() {
// Here you can do any preparation required before calling the parent constructor, such as including additional files or initializing variables.
// Call the parent constructor with the required arguments.
parent::__construct(
// The unique id for your widget.
'hello-world-widget',
// The name of the widget for display purposes.
__( 'Hello World Widget', 'hello-world-widget-text-domain' ),
// The $widget_options array, which is passed through to WP_Widget.
// It has a couple of extras like the optional help URL, which should link to your sites help or support page.
array(
'description' => __( 'A hello world widget.', 'hello-world-widget-text-domain' ),
'help' => 'http://example.com/hello-world-widget-docs',
),
// The $control_options array, which is passed through to WP_Widget
array(),
// We set $form_options using the get_widget_form method below.
false,
// The $base_folder path string.
plugin_dir_path( __FILE__ )
);
}
public function get_widget_form() {
return array(
'text' => array(
'type' => 'text',
'label' => __( 'Hello world! goes here.', 'hello-world-widget-text-domain' ),
'default' => 'Hello world!',
),
);
}
}
siteorigin_widget_register( 'hello-world-widget', __FILE__, 'Hello_World_Widget' );The widget now appears in the list at Plugins > SiteOrigin Widgets. New widgets start inactive, so activate the Hello World Widget there before you use it. Its form has a text field with the default text "Hello world!", which users can edit and save. The widget shows nothing on the front end until it has a template.
The template outputs the widget. The Widgets Bundle looks for tpl/default.php in your widget folder. Override get_template_name() to use another template, and return the template's file name without .php. Override get_template_dir() to use another folder, and return the folder's path relative to the widget class file, without leading or trailing slashes:
function get_template_name( $instance ) {
return 'hello-world-template';
}
function get_template_dir( $instance ) {
return 'hw-templates';
}The Hello World Widget's files are laid out like this:
hello-world-widget/
├── assets/
│ └── banner.svg
├── styles/
│ └── hello-world-widget-style.less
├── tpl/
│ └── hello-world-widget-template.php
└── hello-world-widget.php
The Hello World Widget's template outputs the widget's text:
<div>
<?php echo wp_kses_post( $instance['text'] ); ?>
</div>The widget now shows its text on the front end.
The Widgets Bundle loads styles/default.less from your widget folder. Override get_style_name() to use another LESS stylesheet in the styles folder, and return the stylesheet's file name without .less. LESS Stylesheets explains how the Widgets Bundle uses LESS.
function get_style_name( $instance ) {
return 'my-widget-styles';
}Each widget has a banner in the list at Plugins > SiteOrigin Widgets. Save your banner as assets/banner.svg in your widget folder, or set its URL with the siteorigin_widgets_widget_banner filter. This example sits in my-awesome-widget.php, outside the class. If you put the code in another file, change the image path to match:
function my_awesome_widget_banner_img_src( $banner_url, $widget_meta ) {
if ( $widget_meta['ID'] == 'my-awesome-widget' ) {
$banner_url = plugin_dir_url( __FILE__ ) . 'images/awesome_widget_banner.svg';
}
return $banner_url;
}
add_filter( 'siteorigin_widgets_widget_banner', 'my_awesome_widget_banner_img_src', 10, 2 );