Extension:WidgetsFramework

The WidgetsFramework extension provides a php base for widgets to be easily added to the parser. Integrating external services, such as social networks and multimedia players, can then be done using the wiki markup (no html, no js), like.

About
This extension was initially developed for the needs of Seizam.com by Yann Missler and Clément Dietschy. Inspired by the work on the Widgets extension by Sergey Chernyshev, Jeroen De Dauw, Yaron Koren.

For the moment, the source code is hosted on the "seizamcore" repository at Seizam's github. This is a complete MediaWiki installation with extensions, currently running on Seizam.com and named WikiZam. We also created archives containing only the WidgetsFramework extension.

The 0.3 version is stable with MediaWiki 1.18.5, but we chose to mark it as experimental, as the architecture may change depending on the community.

Why has this extension been created ?
On Seizam.com, we wanted artists to be able to embed external services. At the beginning, we used the Widgets extension. We found lots of existing widgets, they were easy to use, it looked like perfect.

But:
 * there is a security problem that is still unresolved, which allows anyone to inject HTML on wiki pages (see bug 39883),
 * there are some other security issues (adding JS from pages for example),
 * the extension is slowly dying (at least the website http://www.mediawikiwidgets.com is),
 * smarty scripts can be a pain to write,
 * we wanted to "catch" widgets syntax errors and internationalize the display,
 * we wanted widgets to have full access to MediaWiki PHP backend (internal MediaWiki widgets? API query for visual editor?),
 * we would like to handle both parser functions and parser tags widgets in the same extension, and
 * we would like widgets to be version controlled (Git/Gerrit).

So, we decided to create this extension:
 * HTML cannot be injected any more, and because widgets are backend side in static PHP files, only system administrators manage widgets,
 * parser functions are already implemented, and parser tags could be in the future,
 * we integrated parameter validation, error messages (english and french languages are already available) and
 * widgets can access all of MediaWiki's functionalities.

The current state

 * The framework is fully functional for parser functions widgets.
 * Available widgets are: Bandcamp, Vimeo, Flickr, SoundCloud, AddThis, Twitter, Facebook, GooglePlus, Audio (HTML5 player), Video (HTML5 player), Dailymotion, and YouTube.
 * Documentation (en+fr) has been written for each widget at Seizam.com.

How could this extension evolve ?

 * 1) More and more widgets!
 * 2) Migration of the source to Wikimedia's git
 * 3) Migration of the (full) documentation to mediawiki.org
 * 4) Made compatible with MediaWiki 1.20.0 (should work as it is, but not tested yet)
 * 5) Better, much more clever, automatic handling of widgets modules (CSS + JS) through the ResourceLoader (with some wrapper at the Framework level?)
 * 6) Widgets arguments could be parsed by MediaWiki parser, in order to use magic words and templates as parameter values
 * 7) Parser tags widgets could be added
 * 8) Automatic documentation for widgets
 * 9) Better, more clever, Argument to Parameters parsing (set by type?)

Your help is needed!
Do not hesitate to give feedback on |the talk page.

Currently, this extension is just at its beginning. Our goal is to improve it, add features and make it as easy to use for wiki editors and for widgets developers as possible. Any help is more than welcome!

Pending discussion with admins and if this extension receives good reviews, code might migrate to the MediaWiki repository (or whatever favors the community most).

Using widgets
Widgets are already installed in WidgetsFramework. For the moment, they are all parser functions with no "#" prefix.
 * See the quick overview or
 * browse widgets documentations with examples.

See for more details about parameters parsing and setting.

Install widgets

 * 1) The same way as you install MediaWiki's extensions, simply copy the new widget folder in the  directory.
 * 2) That's it! The WidgetsFramework extension detects the widget and installs it automatically.

For the moment, all available widgets are the in WidgetsFramework archive but they could be hosted separately somehow. (Or we always release all the widgets together and admins enable/disable them from LocalSettings?). Discussion is open...

Fell free to contribute, develop your own widgets, and (for the moment) |contact us to add it in the Git repository!

From Scratch
It should not take more than an hour to develop a new widget. A developer would just have to write 1 class within 1 file containing 2 functions: and ... The framework takes care of the rest (setup, parser hooking, error handling, i18n...). Note: for the moment there is a very simple second i18n file to create.

Of course if more functionalities are needed the framework is meant to be flexible and easily extendable.

From Extension:Widgets
As we were using Extension:Widgets before and because we want to keep the amazing work done there, migration to WidgetsFramework should be fairly easy. Simply paste the smarty code inside and replace the smarty markup by regular php. The only struggle is that the parameters needs to be declared and tuned first in.

How do widgets work?
Each widget consists of a folder containing the source files, all names are camel cased.

Let's have a look on the Vimeo widget to understand how it works.

The folder  inside   contains only 2 files.

Vimeo.php
This is the core file.

The framework uses PHP namespaces (require PHP >= 5.3.0). It avoids name collisions for classes/functions/constants without having extra long names. This allows shorter and cleverer names, without breaking MediaWiki or other extensions.

This creates the widget Vimeo as a parser function.

Theses are the parameter the widget accepts.

Then, there are the two methods a widget must have.

declareParameters
This method sets all the parameters up. See the PHP documentation in the code.

The first parameter is a string named " ".
 * This parameter must be set.
 * Its value is subject to an  escape (for now, available modes are the same as in smarty escape used in Widgets extension)
 * This parameter is finally added to the widget.

The second parameter is an integer in pixel called " ".
 * It is optionnal.
 * If not set, it's default value is . It's range goes from   to   (both included).

The third parameter is called " ". It is similar to " " parameter.

The fourth and final parameter is a xor parameter called " "
 * It is optional.
 * It contains 2 options:  and , this means that user either type:
 * (or, or  , or   ),
 * but should not set both  and
 * but should not set both  and

getOutput
When a widget is called and the framework validates successfully its parameters (required, min, max, ...), this rendering method is called. It returns the raw HTML.

To make the code easier to read, this widget has its CSS class selection in a separate method. CSS classes are selected according to the value of the parameters.

Vimeo.i18n.magic.php
As a parser function, the widget has to tell MediaWiki the keyword  is associated to it. Furthermore, the keyword is set case insensitive, so there will be no difference is someone type  or.

It is possible to add logic within the framework setup to avoid the creation of such a file for each widget.

See MediaWiki documentation about magic words declaration

That's it!
Users can now embed Vimeo in the wiki :) See an example here.

About Parameters
Widget parameters can be of different types (like boolean, string or integer). Each type validates only certain value format. The parameter escaping can be selected at will.

Parameters can either be set by name, or by order, or both. Here is an example from the Vimeo widget:
 * the first parameter " " of type "string", and
 * the second parameter " " of type "integer in pixel" (an integer that could have the "px" unit).

Set parameters by name
This is the clearest case. The order arguments are written doesn't matter:
 * is equivalent to
 * is equivalent to

Set parameters by order
When there is no name, the order in which the arguments are written must be same as the order of the parameters declaration in the widget PHP source code. See the documentation of the widget.
 * is equivalent to
 * (because  is the first widget parameter, and   is the second one)

Set some parameters by name and some by order
First, parameters are set by name, then the remaining parameters are set by order. Example with.
 * 1) Before the widget reads the arguments:
 * both parameters are not set,
 * " " is the first one and
 * " " is the second one.
 * 1) First read of the named arguments:
 * parameter " " is set to value ,
 * 1) Second read of the unamed arguments:
 * the first parameter (now it is " ") is set to.