Config-driven WordPress shortcodes.
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
includes
src
.gitignore
CHANGELOG.md
LICENSE
README.md
composer.json
composer.lock
phpcs.xml
phpunit.xml

README.md

Bright Nucleus Shortcodes Component

Config-driven WordPress shortcodes.

Scrutinizer Code Quality Code Coverage Build Status Codacy Badge Code Climate

Latest Stable Version Total Downloads Latest Unstable Version License

This is a WordPress shortcodes component that lets you define shortcodes through a config file, complete with dependencies, localization and Shortcake UI.

Table Of Contents

Installation

The best way to use this component is through Composer:

composer require brightnucleus/shortcodes

Basic Usage

To use this component, you'll need to:

  1. instantiate the ShortcodeManager class;
  2. inject an object implementing the BrightNucleus\Config\ConfigInterface through its constructor;
  3. call its register() method.
use BrightNucleus\Config\ConfigFactory;
use BrightNucleus\Shortcode\ShortcodeManager;

$config = ConfigFactory::create( __DIR__ . '/../config/example_config.php');
$shortcode_manager = new ShortcodeManager(
	$config->getSubConfig( 'ShortcodeManager' )
);
$shortcode_manager->register();

Configuration Schema

$shortcodes_config = [

	/* For each shortcode you wish to define, you'll need one separate entry at
	 * the root config entry passed in to ShortcodeManager. The name of that
	 * entry is used as the shortcode tag.
	 */
	'shortcode_tag' => [

		/* Path to a template that is used to render the shortcode.
		 * The path is relative to the configuration file.
		 */
		'view' => __DIR__ . '/../views/shortcodes/view_file.php',

		/* Customised ShortcodeInterface implementation. (optional)
		 * You can use this to completely customize the standard shortcode
		 * class behavior.
		 * Omit to use default `Shortcode` class.
		 * This can be either a fully qualified class name or a callable.
		 */
		'custom_class' => '\BrightNucleus\Shortcodes\Shortcode',

		/* Customised ShortcodeAttsParserInterface implementation. (optional)
		 * You can use this to completely customize the way shortcode attributes
		 * are parsed.
		 * Omit to use default `ShortcodeAttsParser` class.
		 * This can be either a fully qualified class name or a callable.
		 */
		'custom_atts_parser' => '\BrightNucleus\Shortcodes\ShortcodeAttsParser',

		/* Collection of attributes that can be used with the shortcode.
		 * These attributes will be processed by the
		 * `ShortcodeAttsParserInterface` implementation that is being used.
		 */
		'atts' => [

			/* Shortcode attribute name.
			 * These are the optional attributes that you can append to your
			 * shortcode within the WP editor: [shortcode att_name='value'].
			 * NB: lower-cased by WP, so no camelCase or UPPER_CASE.
			 */
			'attribute_name'    => [

				/* Provided that you use the default `ShortcodeAttsParser`
				 * implementation, you can define a `default` value for each
				 * attribute, as well as an optional `validate` callable that
				 * gets evaluated to a boolean.
				 */
				'default'  => 'default_value',
				'validate' => function ( $att ) {
					return some_validation_function( $att );
				},
			],
		],

		/* Customised ShortcodeUIInterface implementation. (optional)
		 * You can use this to completely customize the standard shortcode
		 * user interface class behavior.
		 * Omit to use default `ShortcodeUI` class.
		 * This can be either a fully qualified class name or a callable.
		 */
		'custom_ui' => '\BrightNucleus\Shortcodes\ShortcodeUI',

		/* Besides one additional keys that ShortcodeManager recognizes, the
		 * 'ui' subkey gets passed as is to the Shortcake UI plugin.
		 * Refer to the Shortcake documentation for details about the syntax:
		 * https://github.com/wp-shortcake/shortcake/wiki/Registering-Shortcode-UI
		 */
		'ui'   => [

			/* Whether the shortcode UI (along with its dependencies) is needed
			 * within the current context or not. If this is a callable, it gets
			 * executed and its result evaluated to boolean.
			 */
			'is_needed' => function ( $context ) {
				return true;
			},

			// [ Shortcake configuration keys. ]

		],
	]
];

Registering a basic shortcode

For the following example, we'll register a new shortcode that provides a simple [button] shortcode. We want the shortcode to be configurable through Shortcake.

Configuration File

First, we need to define the shortcode through a configuration file.

<?php namespace Example\Plugin;

/* ShortcodeManager configuration.
 */
$shortcodes = [
	// Let's define a new button.
	'button'          => [
		'view' => __DIR__ . '/../views/shortcodes/button.php',
		'atts' => [
			// It will accept a caption...
			'caption' => [
				'validate' => function ( $att ) {
					return ( null !== $att )
						? esc_attr( $att )
						: null;
				},
				'default'  => 'Straight to Google!',
			],
			// ...and a URL.
			'url'     => [
				'validate' => function ( $att ) {
					return ( null !== $att )
						? esc_attr( $att )
						: null;
				},
				'default'  => 'https://www.google.com/',
			],
		],
		// We also want a user interface for that button.
		'ui'   => [
			// Let's call it "Example Button".
			'label'         => esc_html__(
				'Example Button',
				'example-plugin'
			),
			'listItemImage' => 'dashicons-search',
			// We only want to make it available when editing a "page".
			'post_type'     => [ 'page' ],
			// It is always needed, so no extra checks to load it conditionally.
			'is_needed'     => function ( $context ) { return true; },
			// We also need to configure the Shortcake input fields.
			'attrs'         => [
				[
					'label'       => esc_html__(
						'Caption',
						'example-plugin'
					),
					'description' => esc_html__(
						'The caption that is shown on the button.',
						'example-plugin'
					),
					'attr'        => 'caption',
					'type'        => 'text',
					'value'       => 'Straight to Google!',
				],
				[
					'label'       => esc_html__(
						'URL',
						'example-plugin'
					),
					'description' => esc_html__(
						'Target URL where the button will lead to when pressed.',
						'example-plugin'
					),
					'attr'        => 'url',
					'type'        => 'url',
					'value'       => 'https://www.google.com/',
				],
			],
		],
	],
];

/* Plugin settings.
 */
$plugin_settings = [
	'ShortcodeManager'  => $shortcodes,
];

/* Return with Vendor/Package prefix.
 */
return [
	'Example' => [
		'Plugin' => $plugin_settings,
	],
];

Template file

Then, we'll need to write a template that can be rendered by the shortcode.

<?php namespace Example\Plugin;

/**
 * Button Shortcode Template
 */

// The `$atts` array (as well as the inner `$content` variable) will be
// available from within this template.

?>
<div class="example button class">
	<a class="button radius"
	href="<?php echo esc_url( $atts['url'] ); ?>"><?php echo esc_html( $atts['caption'] ); ?></a>
</div>

Initialization

Finally, we'll need to initialize the ShortcodeManager with the configuration file, and let it register() its shortcodes.

<?php namespace Example\Plugin;

use BrightNucleus\Config\ConfigFactory;
use BrightNucleus\Shortcode\ShortcodeManager;

const PLUGIN_PREFIX            = 'Example\Plugin';
const SHORTCODE_MANAGER_PREFIX = 'ShortcodeManager';

// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
	die;
}

// Load Composer autoloader.
if ( file_exists( __DIR__ . '/vendor/autoload.php' ) ) {
	require_once __DIR__ . '/vendor/autoload.php';
}

// Load configuration file.
$config = ConfigFactory::create( __DIR__ . '/config/example.php' );

// Initialize Shortcode Manager.
$shortcode_manager = new ShortcodeManager(
	$config->getSubConfig( PLUGIN_PREFIX, SHORTCODE_MANAGER_PREFIX )
);

// Hook Shortcode Manager up to WordPress action.
\add_action( 'init', [ $shortcode_manager, 'register' ] );

Using Custom Classes

The actual implementations to be used for the following interfaces can be changed through the Config files:

  • BrightNucleus\Shortcode\ShortcodeInterface
  • BrightNucleus\Shortcode\ShortcodeAttsParserInterface
  • BrightNucleus\Shortcode\ShortcodeUIInterface

The Config files accepts a key for overriding each of these. You can pass either a fully qualified class name or a callable that acts as a factory.

When using a callable, the arguments that are passed to that callable are the same as the constructor gets for the default implementation of each of these.

Contributing

All feedback / bug reports / pull requests are welcome.

License

Copyright (c) 2016 Alain Schlesser, Bright Nucleus

This code is licensed under the MIT License.