Published:
6 November 2012

Providers is a concept that was introduced with Symphony 2.3 which allows extensions to natively provide new Data Source types. This allowed for a more seamless experience for users and opened up a world of possibilities for extension developers. The upcoming Symphony 2.3.1 release brings Providers to Events as well, allowing developers to provide new event types selectable from the native Event editor.

For Users

For users, the benefits are more flexible and powerful DataSources and Events that can start to do things that previously required custom code. Extensions such as Cacheable DataSource, Union DataSource and Remote DataSource all bring powerful functionality to the fingertips of every Symphony ninja (and those in training). The addition of Events means that we can now create extensions that abstract common API's (such as Github) to read and write information without any knowledge of the underlying API.

For Developers

In this article I'll explain the basics of creating a Provider type, using a basic extension that uses this new feature to interact with Github as a reference.

Extension Structure

The extension.driver.php needs to implement the iProvidable interface, and include it's single method, providerOf(string $type) to make your Provider classes visible to Symphony. The providerOf function takes an optional parameter, a string $type (or null), and should return all the providers this extension has filtered by $type as an array where the key's are the class names, and the values are human readable. At this stage, event and data-sources are the only two valid types, as implied by the iProvider constants, DATASOURCE and EVENT.

In my example, I'm using another function, [registerProviders], which is used privately to build an associative array of providable objects. It's up to you if you want to abstract this or just include it as part of providerOf.

Your extension.driver.php is responsible for loading your provider classes, giving you the freedom to place the classes where ever you think works best. I've chosen to create two folders, data-sources and events, which contain a single class each as this follows usual Symphony convention.

Interfaces

The Data Source and Event classes have their own interface classes, iDataSource and iEvent, which specify the minimum functions that your extension needs to implement to create a new provider.

Basic Data Source and Event Providers

There are a couple of basic functions that are common to the DataSource and Event classes which we will quickly go over. getName returns a human readable name for your Provider. This will be displayed in the Sources drop down on the Editor pages in Symphony.

getSource returns an identifier that allows the Event or Datasource editor to know that the submitted form needs to be handled by providers. Both Events and DataSources usually set their source to be the Section ID or in some cases, a string (used by Static XML, Navigation, Author and Dynamic XML datasources). Your provider should return something that is not numeric, I'm using the classname in this extension.

The DataSource and Event Editors work by saving a new file into the your Symphony /workspace which contains the settings entered in the Editor, saved into a format specified by a template. You may want to look at the default templates for DataSources and Events to give you an idea of the default, and then compare it to Github API extension. Our providable objects will have their own templates and the getTemplate function returns the file path to this class's template.

After an Event or DataSource is saved it appears in the relevant index table. The getSourceColumn(string $handle) method is optional, but allows you to populate this column with whatever information you would like. The function is passed the $handle of your Event/DataSource. If this function is not implemented, Symphony will simply use the value of getSource function to populate this column.

Editors

There are four methods required to make the magic happen for the Symphony Editors, settings, buildEditor, validate and prepare.

settings(): array

This function allows your Datasource or Event to have any default settings. These will be applied when creating a new DataSource or Event and will be passed to the buildEditor function.

buildEditor(XMLElement $wrapper, array &$errors = array(), array $settings = null, $handle = null)`

The buildEditor function returns nothing, but should populate $wrapper with the desired markup (using XMLElement) to create an editor for your providable object. This function should be responsible for:

  • Providing the interface for users to configure your Datasource or Event type
  • Handle any default settings, or remembering user input (these values as provided by Symphony as the $settings parameter). This is an associative array of all the values saved from the Editor. To keep your specific settings abstracted from the Symphony default settings, I'd recommend nesting the settings under a common key.
  • Error handling, any errors are passed through $errors in the same format as $settings.

If the user is editing a Datasource/Event rather than creating a new one, $handle will be populated with the object's handle so that you can create an instance if required, or do some alternative logic.

validate(array &$settings, array &$errors): boolean

The validate function allows you to ensure that users have filled in the settings correctly. This function should populate the $errors variable if an error has occurred and then return false. If there are no errors, return true allows the Editor to continue. Remember that your buildEditor function needs to handle displaying these errors to users!

prepare(array $settings, array $params, $template): string

Finally, this function passes the $settings array, Symphony set $params as an array and your $template as a string. Here you prepare the $template for saving by populating any placeholders with the required settings. In the Github API example, the template uses placeholders suitable for sprintf.

Execution

Datasources and Events both do the bulk of their work in the execute function. It is expected that this function return an XMLElement of the results of the DataSource or Event which will be appended to the Page's XML so that it can be accessed in XSLT.

The DataSource is also passed the current parameter pool by reference which can be populated or accessed. This will contain all the parameters that have been added by DataSources that have been executed before this DataSource.

Page level parameters, for Events and DataSources, can be accessed using Frontend::instance()->Page()->Params(). Events can set page params, but setting them directly via Frontend::instance()->Page()->_param. It is likely that this variable will be changed in future, so keep an eye out of that.

Event Providers

Events and load().

Before an Event is executed, the load() function is called which checks to see if the event should be executed (or __trigger in the old days). The default is usually detecting if the form action matches this event's action or not, eg. isset($_POST['action']['event-handle']). This means that if an Event is attached to a page, the load() function is always executed, so be mindful of what you put in here. If the Event's load() function returns true, the Event's execute function should be called to actually fire the event.

Documentation

All event's have a magical documentation() function. In the scenario of a default Symphony event, saving the editor will generate the markup needed on the frontend to populate entries of this section. This markup is generated by the fields in the Event's section using their getExampleFormMarkup function (oh that's what that does I hear some of you say!) and save the HTML string inside this documentation() function. When the event is viewed again in the editor, this markup is displayed to the user.

You can also take advantage of this in your Provider events by doing the same thing :) If you don't want to display markup at all, just return false.

Conclusion

There we have it. Hopefully this short guide gives you an insight into how you can create your own extensions that add new Data source or Event types to Symphony. Happy coding!

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details