Creating plugins for Shop-Script

Plugins are used for adding extra functionality to the online store without modifying its source code. Each plugin is stored in a separate directory inside wa-apps/shop/plugins/.

Plugins can execute the following kinds of actions:

  • event handling
  • URL request handling
  • handling of command-line calls (e.g., for setting up cron jobs)

The basic principles of plugin development and plugin operation are described in the Webasyst developer documentation. Below is a more detailed description of what you need to know to develop plugins for Shop-Script.

1. Event handling

Every time when some action is executed in an online store the appropriate PHP code is executed in the order defined by the app's developers. The source code of Shop-Script contains special places where additional algorithms can be executed; such algorithms must be described in plugins attached to those specific places. Such special places in the source code are called hooks and the fact of execution of source code containing a hook is called an event.

There are quite a few events in Shop-Script which you can process by means of plugins; e.g., request of a product page in the storefront, calculation of the discount during checkout, opening of a category settings dialog in the backend, etc. View the full list of hooks available in Shop-Script →

Each hook has a unique id (name) which should be used to specify for each plugin in which place and at which moment it should be triggered. The list of hooks to be handled by a plugin must be specified in file lib/config/plugin.php in plugin's subdirectory. In this file, for each hook's name you should specify the name of method which should be called upon occurrence of the corresponding event. If some event should not be handled by a plugin, its name must not be specified in file lib/config/plugin.php. Methods whose names are listed in file lib/config/plugin.php must be described in plugin's main class file lib/shop[PLUGIN_ID].plugin.php located in plugin's subdirectory.

Below is an example of such file wa-apps/shop/plugins/someplugin/lib/config/plugin.php:

<?php

return array(
    'name' => 'Plugin name',
    'version' => '1.0',
    
    // event name => event handler (name of method described in main class file)
    'handlers' => array(
      'frontend_homepage' => 'frontendHomepage',
    ),
    
    // other optional parameters
    'img' => 'img/plugin.png', // 16x16 icon
    'description' => 'Plugin description'
);

In the bold section shown above for hook frontend_homepage defines method named frontendHomepage as its handler. Hook name “frontend_homepage” must be exactly as shown here because it is used so in the source code of Shop-Script. Method name “frontendHomepage” can be specified arbitrarily; e.g., “homepageEventHandler”, at your discretion. It is only important to be sure that the method name specified in this file must match that used in plugin class file. Main class file may look as follows for the above example:

<?php

class shopSomepluginPlugin extends waPlugin
{

    public function frontendHomepage ($params)  //you may write anything else instead of frontendHomepage, depending what method name you have specified in plugin configuration file lib/config/plugin.php
    {
        // method‘s source code here

        return ...;    //returning a value is not a requirement because a plugin can only save some data to the database upon occurrence of a certain event
    }

    // ... other event handlers

}

If an event handling method returns a value, that value will be added to the HTML code of the web page containing the corresponding hook. Each hook may provide one or several connection points to display returned values in backend and frontend pages. For example, hook frontend_homepage provides only one such point by means of the following snippet in template home.html in design themes:

<!-- plugin hook: 'frontend_homepage' -->
{* @event frontend_homepage.%plugin_id% *}
{foreach $frontend_homepage as $_}{$_}{/foreach}

Depending on the place where this snippet is located in source code for a template, values returned by plugins attached to that specific hook may be displayed in various places in a web page.

Other hooks may provide multiple connection points to display results returned by plugins. For example, hook frontend_product (used in template product.html) as shown below:

<!-- plugin hook: 'frontend_product.cart' -->
{* @event frontend_product.%plugin_id%.cart *}
{foreach $frontend_product as $_}{$_.cart}{/foreach}
<!-- plugin hook: 'frontend_product.block_aux' -->
{* @event frontend_product.%plugin_id%.block_aux *}
{if !empty($frontend_product)}
<div class="aux">
    {foreach $frontend_product as $_}{$_.block_aux}{/foreach}    
</div>
{/if}
<!-- plugin hook: 'frontend_product.menu' -->
{* @event frontend_product.%plugin_id%.menu *}
{foreach $frontend_product as $_}{$_.menu}{/foreach}
<!-- plugin hook: 'frontend_product.block' -->
{* @event frontend_product.%plugin_id%.block *}
{foreach $frontend_product as $_}{$_.block}{/foreach}

If a hook provides only one connection point, event handling methods attached to that hook should return a simple string.

If a hook provides multiple connection points for plugins then an event handling method must return an associative array with connection points' ids as its keys (they are written in bold font in the above example). Below is an example of an event handling method returning an array of values for multiple connection points:

<?php

class shopSomepluginPlugin extends waPlugin
{

    public function frontendHomepage ($params)
    {
        ...
        
        return array(
            'cart'      => 'value1',
            'block_aux' => 'value2',
            'menu'      => 'value3',
            'block'     => 'value4',
        );
    }

}

Values mentioned in this example as 'value1', 'value2', 'value3', and 'value4' will be included in the resulting HTML code in the places where the corresponding connection points are located in a template (in this case product.html).

2. URL request handling

Request routing in frontend

Regardless of whether a plugin is set to handle events it also can handle requests to URLs formed in accordance with certain templates (masks) similarly to the way the framework handles user requests using routing rules set up in the Site app. Like the framework's routing rules stored in coinfiguration file wa-config/routing.php, a plugin's routing rules should be specified in file lib/config/routing.php in plugin subdirectory.

Below is shown the format of file lib/config/routing.php:

<?php

return array(
    'path/<name1>/<name2>/' => 'module/action',
    '...' => 'module/action',
    /* other routing rules */
);

Instead of array keys (shown as path/<name1>/<name2>/ in the above example), URL masks should be specified, which will be accepted by the plugin. Dynamic parts of URLs must be specified in the form <name1>, <name2>, etc. Values corresponding to those parts are accessible in plugin's event handling methods by means of system method waRequest::param($name).

Note that the order and number of dynamic URL parts do not need to match those of the above example; you may create URL masks with any other structure.

For example, if a URL mask is written as extra/<section_id>/<item_id>/ then values specified in actual URLs instead of <section_id> and <item_id> will be available in the appropriate action's source code as waRequest::param('section_id') and waRequest::param('item_id').

URL masks must be relative, i.e. they must not begin with a slash character: /. Absolute URLs handled by plugins are generated with the corresponding settlement's base URL taken into account. For example, if you have set up a settlement for your online store at a URL like http://yourdomain.com/shop/ then in the above example the plugin will handle URLs of the form http://yourdomain.com/shop/extra/some/value/ where “some” corresponds to <section_id> and “value” corresponds to <item_id> (according to plugin's routing rule extra/<section_id>/<item_id>/).

Instead of module and action portions the following values must be specified:

  • module: id of the module whose action should handle requests sent at this specific kind of URLs
  • action: the id of the action which will be executed when URLs matching the specified mask are requested; plugin action files must be created similarly to app action files (read more →)

Example of file lib/config/routing.php:

<?php

return array(
    'extra/<section_id>/<item_id>/' => 'frontend/extra',
);

The source code of action with id “extra” specified in the above example may reside:

  • in file wa-apps/shop/plugins/someplugin/lib/actions/frontend/shopSomepluginPluginFrontend.actions.php declared as method actionExtra() либо
  • in file wa-apps/shop/plugins/someplugin/lib/actions/frontend/shopSomepluginPluginFrontendExtra.action.php declared as method execute().

Requests to backend

Routing setup described above is necessary for requests sent by frontend users. In backend, simple URLs corresponding to the framework's system rules are applied; e.g.:

http://yourdomain.com/webasyst/shop/?plugin=someplugin&action=extra — calling a action with id extra of the backend module

3. Handling of command-line calls

Command-line calls may be useful for setting up scheduler (cron) jobs or for debugging purposes. Read more about creating this type of handlers in article “Plugins” in the Webasyst developer documentation.

0 comments

    Add comment

    To add a comment please sign up or login