Shortcodes
Topics
Introduction
The Events Calendar and Event Tickets plugins provide a robust Shortcode API that allows both internal and third-party developers to create and manage shortcodes within the ecosystem. This API is designed to standardize shortcode creation, argument handling, validation, and rendering while providing hooks for customization at every step.
The Shortcode API is part of the Common module in The Events Calendar, making it available to all plugins that include this common functionality. This documentation will explore how to leverage this API to create custom shortcodes that integrate seamlessly with The Events Calendar and Event Tickets.
Core API Architecture
The Shortcode API is built around four primary components in the Common module:
Interface
The Shortcode_Interface (\Tribe\Shortcode\Shortcode_Interface) defines the contract that all shortcodes must follow. This interface ensures that shortcodes implement consistent methods for:
- Registration
- Argument handling
- Content parsing
- HTML rendering
Key methods defined in the interface include:
get_registration_slug()– Returns the shortcode tag used for registrationsetup()– Configures the shortcode with arguments and contentparse_arguments()– Processes and validates shortcode attributesget_html()– Renders the shortcode’s HTML output
Abstract Class
The Shortcode_Abstract (\Tribe\Shortcode\Shortcode_Abstract) implements the interface and provides common functionality that all shortcodes can inherit. The abstract class handles:
- Argument parsing and validation
- Default argument management
- Aliased argument support (allowing alternative attribute names)
- Content storage
- Filter hooks for customization
Key properties you’ll need to define when extending this class:
protected $slug = 'your_shortcode_tag';
protected $default_arguments = [
'arg1' => 'default_value',
'arg2' => 123,
];
The abstract class includes built-in support for argument aliasing, allowing users to provide alternative argument names in their shortcodes:
protected $aliased_arguments = [
'alt_name' => 'canonical_name',
'from' => 'to',
];
Manager
The Manager (\Tribe\Shortcode\Manager) class is responsible for:
- Registering shortcodes with WordPress
- Handling shortcode rendering through the appropriate classes
- Tracking which shortcodes are currently being processed
- Providing utility methods for checking shortcode status
The Manager implements a filter tribe_shortcodes that allows plugins to register their shortcodes:
add_filter( 'tribe_shortcodes', function( $shortcodes ) {
$shortcodes['my_shortcode'] = 'My\Namespace\My_Shortcode';
return $shortcodes;
} );
Utils
The Utils (\Tribe\Shortcode\Utils) class provides helper methods for shortcode-related operations, particularly converting widget settings to shortcode attributes:
$attributes_string = Utils::get_attributes_string( $settings, $allowed );
Creating Custom Shortcodes
Basic Implementation
To create a custom shortcode using The Events Calendar’s Shortcode API:
- Create a class that extends
\Tribe\Shortcode\Shortcode_Abstract - Set the
$slugproperty to your shortcode tag - Implement the
get_html()method to render your shortcode output - Register your shortcode with the manager
Here’s a minimal example:
<?php
namespace My\Plugin\Shortcodes;
use Tribe\Shortcode\Shortcode_Abstract;
class My_Custom_Shortcode extends Shortcode_Abstract {
/**
* {@inheritDoc}
*/
protected $slug = 'my_custom_shortcode';
/**
* {@inheritDoc}
*/
protected $default_arguments = [
'title' => '',
'limit' => 5,
];
/**
* {@inheritDoc}
*/
public function get_html() {
$title = $this->get_argument( 'title', 'Default Title' );
$limit = $this->get_argument( 'limit', 5 );
// Your shortcode logic here
return '<div class="my-shortcode">' .
'<h3>' . esc_html( $title ) . '</h3>' .
// Additional HTML
'</div>';
}
}
Handling Arguments
The Shortcode API provides robust argument handling:
Default Arguments
Set default values for your shortcode arguments:
protected $default_arguments = [
'title' => 'Default Title',
'limit' => 10,
'category' => '',
];
Argument Aliasing
Allow users to use alternative attribute names:
protected $aliased_arguments = [
'count' => 'limit', // [my_shortcode count="5"] works the same as [my_shortcode limit="5"]
'heading' => 'title', // [my_shortcode heading="Events"] works the same as [my_shortcode title="Events"]
];
Argument Validation
Implement validation callbacks for your arguments:
protected $validate_arguments_map = [
'limit' => [ $this, 'validate_limit' ],
'category' => [ $this, 'validate_category' ],
];
protected function validate_limit( $limit ) {
$limit = absint( $limit );
return $limit > 0 ? $limit : 5;
}
protected function validate_category( $category ) {
return sanitize_text_field( $category );
}
Retrieving Arguments
Access processed arguments in your shortcode:
public function get_html() {
// Get a single argument with optional default
$limit = $this->get_argument( 'limit', 10 );
// Get all arguments
$args = $this->get_arguments();
// Build your shortcode output using these arguments
// ...
}
Rendering HTML
The get_html() method is where you generate the shortcode output:
public function get_html() {
// Check if we're in an admin context and not doing AJAX
if ( is_admin() && ! tribe_context()->doing_ajax() ) {
return '';
}
// Get your template engine
$template = tribe( 'your.template.engine' );
// Prepare data for the template
$data = [
'title' => $this->get_argument( 'title' ),
'items' => $this->get_items(),
];
// Add the data to template context
$template->add_template_globals( $data );
// Enqueue any necessary assets
tribe_asset_enqueue_group( 'your-asset-group' );
// Render and return the template
return $template->template( 'path/to/template', $data, false );
}
Registration Process
To register your shortcode with The Events Calendar’s Shortcode API:
- Create a function or class method that hooks into the
tribe_shortcodesfilter - Add your shortcode to the array with the shortcode slug as the key and the class name as the value
- Ensure your class autoloading is set up correctly
Example in a plugin:
<?php
/**
* Plugin Name: My TEC Extension
* Description: Adds custom shortcodes to The Events Calendar
*/
// Register shortcodes with TEC
add_filter( 'tribe_shortcodes', function( $shortcodes ) {
$shortcodes['my_custom_shortcode'] = 'My\Plugin\Shortcodes\My_Custom_Shortcode';
return $shortcodes;
} );
// Include your shortcode class
require_once plugin_dir_path( __FILE__ ) . 'classes/Shortcodes/My_Custom_Shortcode.php';
Available Hooks
The Shortcode API provides numerous filter hooks for customization:
Global Shortcode Filters
tribe_shortcodes– Register shortcode classestribe_shortcode_validate_arguments_map– Modify argument validation callbackstribe_shortcode_arguments– Filter processed shortcode argumentstribe_shortcode_argument– Filter an individual argument valuetribe_shortcode_default_arguments– Modify default arguments
Shortcode-Specific Filters
tribe_shortcode_{$slug}_validate_arguments_map– Modify validation callbacks for a specific shortcodetribe_shortcode_{$slug}_arguments– Filter arguments for a specific shortcodetribe_shortcode_{$slug}_argument– Filter an individual argument for a specific shortcodetribe_shortcode_{$slug}_default_arguments– Modify default arguments for a specific shortcodetec_shortcode_{$slug}_aliased_arguments– Modify aliased arguments for a specific shortcode
Best Practices
When developing shortcodes with The Events Calendar’s API:
- Always extend the Shortcode_Abstract class – This ensures your shortcode follows the same standards and behaves consistently with other TEC shortcodes.
- Validate user input – Use the
validate_arguments_mapto ensure all user-provided attributes are properly sanitized. - Support aliased arguments – Improve user experience by allowing alternative attribute names that may be more intuitive.
- Separate logic from presentation – Use templates for rendering HTML rather than building it directly in the
get_html()method. - Enqueue required assets – Make sure to enqueue any CSS/JS your shortcode needs.
- Check context before rendering – Avoid rendering in admin contexts where it might not make sense.
- Use filter hooks – Implement filter hooks to allow other developers to customize your shortcode’s behavior.
- Document your shortcode – Provide clear documentation on what attributes are available and how they modify the output.
- Handle errors gracefully – Return informative messages when something goes wrong, rather than breaking the page.
- Keep performance in mind – Optimize database queries and cache results when possible.
Troubleshooting
Common issues when working with the Shortcode API:
Shortcode Not Registered
If your shortcode isn’t working:
- Verify your hook into
tribe_shortcodesis running - Check that the class name in the registry matches your actual class name and namespace
- Ensure your class is properly autoloaded or included
Arguments Not Processing Correctly
If shortcode attributes aren’t working as expected:
- Check if you’re properly defining
$default_arguments - Verify your validation callbacks are returning the expected values
- Use
var_dump( $this->get_arguments() )in yourget_html()method to debug
HTML Output Issues
If your shortcode isn’t rendering correctly:
- Check for any PHP errors in your logs
- Ensure templates exist at the specified paths
- Verify that assets are being properly enqueued
- Test your shortcode in a simple environment without other plugins
Advanced Customization
You can hook into the various filters provided by the API:
// Modify arguments for a specific shortcode
add_filter( 'tribe_shortcode_my_shortcode_arguments', function( $args, $instance ) {
// Custom logic to modify args
return $args;
}, 10, 2 );
// Add aliased arguments to all shortcodes
add_filter( 'tec_shortcode_aliased_arguments', function( $aliases, $instance ) {
$aliases['count'] = 'limit';
return $aliases;
}, 10, 2 );
This documentation provides a comprehensive overview of The Events Calendar’s Shortcode API. By following these guidelines, internal and third-party developers can create custom shortcodes that seamlessly integrate with The Events Calendar and Event Tickets, providing users with additional functionality while maintaining a consistent experience throughout the plugins ecosystem.