Advanced CWIS Plugin Implementation

Plugin Events

Just as CWIS provides the ability for you to run your code when certain events occur, you may want to provide the ability for others to run their code when events happen within your plugin. To do this you'll need to declare these events via your Plugin::DeclareEvents() method:

    function DeclareEvents()
    {
        return array(
                "MYPLUGIN_EVENT_MY_FIRST_EVENT" => ApplicationFramework::EVENTTYPE_DEFAULT,
                "MYPLUGIN_EVENT_MY_SECOND_EVENT" => ApplicationFramework::EVENTTYPE_CHAIN,
                );
    }

By convention, plugin event names should begin with the plugin name in all upper-case (e.g. MYPLUGIN), followed by an underscore and the word EVENT (MYPLUGIN_EVENT), and then underscore-separated terms in all upper case describing the event (MYPLUGIN_EVENT_MY_FIRST_EVENT).

At the point in the code where the event occurs, you'll then signal the event, to give anyone who has hooked into it the chance to run their code:

        global $AF;
        $AF->SignalEvent("MYPLUGIN_EVENT_MY_FIRST_EVENT", array(
                "EventFirstParameter" => $ValueForFirstParam,
                "EventSecondParameter" => $ValueForSecondParam
                ));

The second argument to ApplicationFramework::SignalEvent() allows you to pass parameters to any hooked event handlers, as most of the events listed on the CWIS Event Callbacks page do.

For EVENTTYPE_DEFAULT events any value returned from the event handlers is ignored, however with EVENTTYPE_CHAIN events the return value is a (possibly) modified version of the parameter(s):

        global $AF;
        $SignalResult = $AF->SignalEvent("MYPLUGIN_EVENT_MY_SECOND_EVENT", array(
                "EventFirstParameter" => $ValueForFirstParam
                ));
        $PossiblyModifiedFirstParam = $SignalResult["EventFirstParameter"];

This is why EVENTTYPE_CHAIN events are often used to provide the opportunity for other plugins to modify a value before it is displayed or otherwise used.

Plugin Pages

For more complex plugins that require their own pages (perhaps for complex configuration settings or to display results), you can include PHP and/or HTML files as part of your plugin, and link to them via a path-independent mechanism.

To implement a plugin-specific PHP file, you would place all of your plugin files into a subdirectory named with your plugin base name (e.g. MyPlugin) and then put your plugin class file (MyPlugin.php) and any PHP files (PageOne.php, PageTwo.php) into that directory.

To link to your plugin pages within HTML, use the page base name (PageOne) prefixed with P_ and your plugin base name (MyPlugin):

    <a href="index.php?P=P_MyPlugin_PageOne">

This will also load a similarly-named HTML file (MyPlugin/PageOne.html) at the appropriate time, if one is available.

Plugin Objects

For more complex plugins that include their own object classes, the object files should be one class per file, named after the object class. For example, class MyPlugin_MyObject would go in MyPlugin/MyPlugin_MyObject.php.

To prevent class name collisions, plugin object class names should be prepended with the plugin name and an underscore (e.g. MyPlugin_MyObject). (This somewhat awkward requirement will likely disappear when namespace support becomes widely available with PHP 5.3.)

Following these guidelines, classes for any enabled plugins will be automatically loaded when instances of the object are created, as occurs with native CWIS objects; no require() statements are needed.