Extension:WidgetsFramework

From MediaWiki.org
Jump to: navigation, search
MediaWiki extensions manual
Crystal Clear action run.png
WidgetsFramework

Release status: experimental

Implementation Parser extension, Parser function, Tag
Description Provides a framework to develop and integrate widgets to MediaWiki's parser.
Author(s) Yann Missler, Clément Dietschy
Latest version 0.3 (2012-11-12)
MediaWiki 1.18+
PHP 5.3+
Database changes No
License GPL v3 or any later version
Download From Seizam's GitHub

Archive from Seizam

Example on Seizam.com
Parameters
  • $wgWFMKMaxWidth
Hooks used
BeforePageDisplay

ParserFirstCallInit

Translate the WidgetsFramework extension if it is available at translatewiki.net

Check usage and version matrix; code metrics

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 {{Twitter:user=seizam}}.

About[edit | edit source]

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.

Installation[edit | edit source]

require_once "$IP/extensions/WidgetsFramework/WidgetsFramework.php";
  • Done! Navigate to "Special:Version" on your wiki to verify that the extension is successfully installed.

History[edit | edit source]

Why has this extension been created ?[edit | edit source]

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 was a security problem that was unresolved for months, which allowed 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[edit | edit source]

  • The framework is fully functional for parser functions widgets.
  • Available widgets are:
Widget Mandatory parameters Optional parameters Example
YouTube (more help) id= OR playlist= width= |height= |right |left {{YouTube:id=NIIwct9QNi4|width=392|height=220|right}}
Dailymotion
Vimeo
Bandcamp
Flickr
500px
SoundCloud
"Jamendo"
AddThis
Twitter (more help) user= OR search= mode= |title= |subject= |width= |height= |count= |scrollbar |live |loop |all |float= {{Twitter:user=davidcanwin|width=220|height=180|scrollbar|live|left}}
Flattr
Disqus
Skype (more help) name= status |float= {{Skype:myname|status|right}}
Facebook
GooglePlus
"Gravatar"
Audio (HTML5 player)
Video (HTML5 player)
Google doc (more help) {{GoogleDoc: id=1EAHt8RnIoB7g2mrzBWoIzLP561Xkkz5s9ycznd4ntEo|width=300|height=500}}
Google viewer(more help) {{GoogleViewer:url=http://www.yellpedia.com/mediawiki/images/f/f1/PDF_EXAMPLE.pdf|width=200|height=200}}
  • Documentation (en+fr) has been written for each widget at Seizam.com.

How could this extension evolve ?[edit | edit source]

  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 head (1.20.x tested and ok, no tests above but should work)
  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![edit | edit source]

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[edit | edit source]

Widgets are already installed in WidgetsFramework. For the moment, they are all parser functions with no "#" prefix.

See #About_Parameters for more details about parameters parsing and setting.

Install widgets[edit | edit source]

  1. The same way as you install MediaWiki's extensions, simply copy the new widget folder in the WidgetsFramework/Widgets/ 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...

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

Develop widgets[edit | edit source]

From Scratch[edit | edit source]

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: #declareParameters() and #getOutput()... 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[edit | edit source]

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 #getOutput() and replace the smarty markup by regular php. The only struggle is that the parameters needs to be declared and tuned first in #declareParameters().

How do widgets work?[edit | edit source]

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 Vimeo inside WidgetsFramework/Widgets/ contains only 2 files.

Vimeo.php[edit | edit source]

This is the core file.

namespace WidgetsFramework;

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.

class Vimeo extends ParserFunction { // This is NOT a core ParserFunction class! This is a WidgetsFramework class.

This creates the widget Vimeo as a parser function.

    protected $id;
    protected $width;
    protected $height;
    protected $right;
    protected $left;

Theses are the parameter the widget accepts.

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

declareParameters()[edit | edit source]

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



    protected function declareParameters() {
 
        $this->id = new String('id');
        $this->id->setRequired();
        $this->id->setEscapeMode('urlpathinfo');
        $this->addParameter($this->id);

The first parameter is a string named "id".

  • This parameter must be set (setRequired()).
  • Its value is subject to an urlpathinfo escape (for now, available modes are the same as in smarty escape used in Widgets extension)
  • This parameter is finally added to the widget (addParameter($this->id)).



        $this->width = new IntegerInPixel('width');
        $this->width->setDefaultValue($wgWFMKMaxWidth);
        $this->width->setMin(0);
        $this->width->setMax($wgWFMKMaxWidth);
        $this->addParameter($this->width);

The second parameter is an integer in pixel called "width".

  • It is optionnal.
  • If not set, it's default value is 784. It's range goes from 0 to 784 (both included).



        $this->height = new IntegerInPixel('height');
        $this->height->setDefaultValue(441);
        $this->height->setMin(0);
        $this->addParameter($this->height);

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



        $float = new XorParameter('float');
 
        $this->right = new Option('right');
        $float->addParameter($this->right);
 
        $this->left = new Option('left');
        $float->addParameter($this->left);
 
        $this->addParameter($float);
    }

The fourth and final parameter is a xor parameter called "float"

  • It is optional.
  • It contains 2 options: right and left, this means that user either type:
    • float=right (or right, or right=true, or float=right=true ),
    • float=left,
    • but should not set both right and left


getOutput()[edit | edit source]
    public function getOutput() {
 
        return '<iframe 
                    class="' . $this->getCSSClasses() . '"
                    allowfullscreen=""
                    frameborder="0"
                    height="' . $this->height->getOutput() . 'px"
                    src="http://player.vimeo.com/video/' . $this->id->getOutput() . '?title=0&amp;byline=0&amp;portrait=0"
                    webkitallowfullscreen=""
                    width="' . $this->width->getOutput() . 'px">
                </iframe>';
    }

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.



    public function getCSSClasses() {
 
        $classes = array();
 
        $classes[] = 'vimeo';
        $classes[] = 'wfmk_block';
        $classes[] = 'wfmk_frame';
 
        if ($this->right->getValue()) {
            $classes[] = 'wfmk_right';
        } elseif ($this->left->getValue()) {
            $classes[] = 'wfmk_left';
        }
 
        return Tools::arrayToCSSClasses($classes);
    }

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[edit | edit source]

<?php
 
$magicWords = array();
 
$magicWords['en'] = array(
    'Vimeo' => array( 0, 'vimeo' ),
);

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

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![edit | edit source]

Users can now embed Vimeo in the wiki :) See an example here.

About Parameters[edit | edit source]

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 "id" of type "string", and
  • the second parameter "width" of type "integer in pixel" (an integer that could have the "px" unit).

Set parameters by name[edit | edit source]

This is the clearest case. The order arguments are written doesn't matter:

{{Vimeo: id=43347454 | width=300px }} is equivalent to
{{Vimeo: width=300px | id=43347454 }} is equivalent to
{{Vimeo: | | width=300px | | | id=43347454 | | }} ...

Set parameters by order[edit | edit source]

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.

{{Vimeo: 43347454 | 300px }} is equivalent to
{{Vimeo: id=43347454 | width=300px }} (because id is the first widget parameter, and width is the second one)

Set some parameters by name and some by order[edit | edit source]

First, parameters are set by name, then the remaining parameters are set by order. Example with {{Vimeo: 300px | id=43347454 }}.

  1. Before the widget reads the arguments:
    both parameters are not set,
    "id" is the first one and
    "width" is the second one.
  2. First read of the named arguments:
    parameter "id" is set to value 43347454,
  3. Second read of the unamed arguments:
    the first parameter (now it is "width") is set to 300px.

See also[edit | edit source]

Sites using this extension[edit | edit source]