Module overview

Important

The operation and testing of custom modules is the responsibility of the module creator.  Perforce Software, Inc. is not responsible for the operation of your custom modules, nor does Perforce Software, Inc. make any representations or warranties regarding the interoperability of your custom modules with Helix Swarm.

Tip

You must test your custom modules on a test system before transferring them to your production system. This avoids any negative impact on the operation of your production system. If you have more than one custom module, the modules should all be tested at the same time on the same test system as this ensures that the modules operate correctly with each other and with Helix Swarm.

Tip

If you add or edit a module, Swarm will not use that change until the config cache has been reloaded, this forces Swarm to use the module change. You must be an admin or super user to reload the Swarm config cache. Navigate to the User id dropdown menu, select System Information, click the Cache Info tab, and click the Reload Configuration button.

A Swarm custom module is created in a folder in the modules folder of your Swarm installation. The folder name must match the custom module name and must contain at least a Module.php file and a module.config.php file. A custom module will not work in Swarm until you enable it. Enable your custom modules in Swarm by adding them to the custom.modules.config.php file in the config directory (a peer of the modules directory).

This chapter provides basic information about how custom modules integrate with Swarm and assumes a basic knowledge of the Laminas framework. For more information about the Laminas framework, see Laminas Quick Start documentation.

This section includes:

Migrate existing custom modules to the Laminas framework

Swarm 2020.1 and later uses the Laminas framework, previous Swarm versions used the Zend framework. The move to Laminas is part of our commitment to move away from using versions of platforms that have reached End-of-Life (EOL).

If you have any custom Swarm modules that were created for Swarm 2019.3 or earlier, you must modify them so that they will work in Swarm 2020.1 and later. The modifications required depend on the version of Swarm you were using the custom modules with before your upgraded Swarm:

Custom modules on Swarm 2019.1, 2019.2, or 2019.3

Note

Migrate your custom modules on a test system before transferring them to your production system. This avoids any negative impact on the operation of your production system. If you have more than one custom module, the modules should all be tested at the same time on the same test system as this ensures that the modules operate correctly with each other and with Helix Swarm.

Custom modules used with Swarm 2019.1, 2019.2, and 2019.3 use the Zend 3 framework, they must be migrated to the Laminas framework before they can be used with Swarm 2020.1 and later:

  1. Migrate your Zend 3 custom modules to the Laminas framework by pointing the Laminas migration tool at the folder you store your custom modules in. For the migration tool and full instructions on migrating your custom Zend 3 modules to Laminas, see https://docs.laminas.dev/migration/.
  2. Swarm will not use the custom modules until the Swarm config cache has been deleted. For instructions on deleting the config cache, see Swarm config cache file delete.
  3. Check that your custom modules work as expected before putting them on your production system.

Custom modules on Swarm 2018.3 and earlier

Note

Update and migrate your custom modules on a test system before transferring them to your production system. This avoids any negative impact on the operation of your production system. If you have more than one custom module, the modules should all be tested at the same time on the same test system as this ensures that the modules operate correctly with each other and with Helix Swarm.

Custom modules used with Swarm 2018.3 and earlier use the Zend 2 framework, they must be migrated to the Laminas framework before they can be used with Swarm 2020.1 and later:

  1. Convert your Zend 2 custom modules to the Zend 3 framework, see Upgrade custom modules to work with Zend 3.
  2. Tip

    Laminas is based on the Zend 3 framework, this makes it is relatively simple to convert your Zend 3 custom modules to the Laminas framework:

    • If you only have one or two custom modules, you can manually change all of the Zend references in your modules to Laminas while you are converting them from Zend 2. This means you can skip the Laminas migration step.
    • If you have a larger number of custom modules, it is probably quicker to automatically change all of the references in your custom modules by running the Laminas migration tool as described in the next step.

  3. Migrate your Zend 3 custom modules to the Laminas framework by pointing the Laminas migration tool at the folder you store your custom modules in. For the migration tool and full instructions on migrating your custom Zend 3 modules to Laminas, see https://docs.laminas.dev/migration/.
  4. Swarm will not use the custom modules until the Swarm config cache has been deleted. For instructions on deleting the config cache, see Swarm config cache file delete.
  5. Check that your custom modules work as expected before putting them on your production system.

Influence activity events, emails, etc.

When something happens in Helix Core Server (change submitted, files shelved, job added/edited), or state changes within Swarm (comment added, review state changed, etc.), the event is pushed onto the Swarm task queue. A background worker process pulls events off of the queue and publishes an event alerting modules about activity they may be interested in processing. This architecture allows the Swarm user interface to be fairly quick while accommodating tasks that might require notable processing time, or need to wait for related information to become available.

Subscribers to the worker event flesh the item out (fetch the change/job details, for example) and indicate if it should result in an activity entry, email notification, etc. By subscribing to various event topics, your custom module can pay attention to specific types of events. While your custom module is processing an event, it can modify the text of activity events, change the contents of emails, drop things entirely from activity, etc.

When your custom module subscribes to an event, set the priority to influence how early or late in the process it runs. You will likely want your module to run after most other modules have done their work to flesh out the event, but before Swarm's events module processes it. The events module is a good example of subscribing to these events:

swarm_install/module/Events/config/module.config.php

Tip

Note that its priority is set to -100. Select a value before that for your own module (for example, 0 would be neutral and -90 would indicate that you are interested in being last).

Event priority is from the highest positive number to the lowest negative number with 0 in the middle. For a full list of tasks and their event priorities, see Task details.

Task types

For details of each of the following tasks, see Task details.

  • task.commit
  • task.shelve
  • task.review
  • task.change
  • task.mail
  • task.cleanup.attachment
  • task.cleanup.archive
  • task.shelvedel
  • task.changesave
  • task.changesaved
  • task.comment
  • task.comment.batch
  • task.commentSendDelay
  • task.group
  • task.groupdel
  • task.job
  • task.user
  • task.userdel
  • task.workflow.created
  • task.workflow.updated

Templates

Override existing view templates using your custom module. Have a look at this example module that demonstrates how to customize the email templates Swarm uses for comment notifications.

For more information about views, see the Laminas-View Quick Start.

Note

Swarm supports the Laminas component versions in the LICENSE.txt file, features and functions in the Laminas documentation that were introduced in later versions of Laminas will not work with Swarm. The LICENSE.txt file is in the readme folder of your Swarm installation.

Custom module file locations

The custom module files must be stored using the PSR-4 standard locations shown below:

config/
      custom.modules.config.php (required)
module/
      ModuleName/ (required)
                config/ (required)
                      module.config.php (required)
                src/ (php files here, required)
                   Controller/
                             MyIndexController.php
                   Listener/ (optional)
                           MyListener.php (optional)
                   ...
                   other directories (non-php files here, optional)
                   ...  
                Module.php (required)

IndexControllers

Create your IndexControllers using factories. The IndexControllers should extend Application\Controller\AbstractIndexController and use the Swarm IndexControllerFactory, this means that the IndexControllerFactory can automatically inject the services .

Tip

We recommend you follow the ::class description to avoid errors in string representation.

'controllers' => array(
    'factories' => [
        MyModuleName\Controller\IndexController::class => Application\Controller\IndexControllerFactory::class,
    ],
),

View helpers

Create your view helpers using factories. The factories that create the view helpers must inject any services that are required.

Tip

We recommend using ::class rather than arbitrary strings as this can limit the possibility of errors. The use of classes also makes your factory simpler because reflection can be used to construct the helpers if they all extend a common parent class.

'view_helpers' => array(
        'factories' => array_fill_keys(
            [
                MyModuleName\View\Helper\Helper1::class,
                MyModuleName\View\Helper\Helper2::class,
            ],
            <YourHelperFactory>::class
        )
    )

Set options on existing helpers

It is possible to influence the behavior of existing view helpers by setting options on them; for an example see: swarm_install/module/Application/Module.php.

Register new helpers

It is also possible to register new view helpers by placing them within your module's hierarchy, for example, MyModule/src/View/Helper/Foo.php. Use the following Swarm view helper for inspiration: swarm_install/module/Activity/src/View/Helper/Activity.php.

Then register your view helper with the view manager via your ModuleConfig: swarm_root/module/Activity/config/module.config.php.

Event listeners

Your event listeners should extend Events\Listener\AbstractEventListener. This means that the ListenerFactory can create them without you having to write your own factory.

The Listener.php file contains the implementation of your event listener and the module.config.php file configures your event listeners.

Tip
  • Look at the code in the AbstractEventListener.php file in module/events/src/Listener to see the functions that are available to you.
  • We strongly recommend that you create your event listeners to use the declarative model because it has a number of advantages over the non-declarative model:
    • AbstractEventListener provides common code for listeners to use
    • The declarative model offers better debug options (logging)
    • The declarative model is neater, easier to read, easier to support, and easier to maintain

Example module.config.php file that uses the declarative model for event listeners:

Tip

Listener::class example details:

  • Events\Listener\ListenerFactory::ALL => [
  • We are listening to ALL here for convenience because we are listening for mail events but this means it will trigger on every event. Usually is better to just listen for the events you are interested in. For example, if you are interested in commits and shelves you would listen on COMMIT and SHELVE events.

  • Events\Listener\ListenerFactory::PRIORITY => -199,
  • Declares an event priority of -199 for the event listener because email delivery events are processed with a priority of -200 and the example event needs to run just before the email delivery event.

  • Events\Listener\ListenerFactory::CALLBACK => 'handleEmail',
  • Declares the function name within the listener class that is called.

  • Events\Listener\ListenerFactory::MANAGER_CONTEXT => 'queue'
  • Triggers your custom listener when Swarm processes the Swarm event queue.

<?php
/**
 * Perforce Swarm
 *
 * @copyright   2019 Perforce Software. All rights reserved.
 * @license     Please see LICENSE.txt in top-level folder of this distribution.
 * @version     <release>/<patch>
*/

$listeners = [EmailExample\Listener\Listener::class];
return [
    'listeners' => $listeners,
    'service_manager' =>[
        'factories' => array_fill_keys(
            $listeners,
            Events\Listener\ListenerFactory::class
        )
    ],
    Events\Listener\ListenerFactory::EVENT_LISTENER_CONFIG => [ 
        Events\Listener\ListenerFactory::ALL => [
            EmailExample\Listener\Listener::class => [
                [
                    Events\Listener\ListenerFactory::PRIORITY => -199,
                    Events\Listener\ListenerFactory::CALLBACK => 'handleEmail',
                    Events\Listener\ListenerFactory::MANAGER_CONTEXT => 'queue'
                ]
            ]
        ]
    ]
];		

Example of an email Listener.php file:

namespace MyModuleName\Listener;

use Events\Listener\AbstractEventListener;
use Laminas\EventManager\Event;

class Listener extends AbstractEventListener
{
    public function handleEmail(Event $event)
    {
        $mail = $event->getParam('mail');
        if (!$mail || !isset($mail['htmlTemplate'], $mail['textTemplate'])) {
            return;			
        }
    }
}

Enabling your custom modules

Swarm uses the custom.modules.config.php file to check which custom modules it should load. This gives you control over which modules Swarm loads and prevents modules from being loaded by mistake.

Create the custom.modules.config.php file in the config directory (a peer of the modules directory) if it does not already exist. Edit the file so that it contains the following details for each of your modules:

  • namespaces array: enter your custom module names and paths
  • return array : enter your custom module names

For example, if you have three modules called MyModuleName, AnotherModuleName, and NewModuleName the file content would look similar to:

<?php
\Laminas\Loader\AutoloaderFactory::factory(
    array(
        'Laminas\Loader\StandardAutoloader' => array(
            'namespaces' => array(
                'MyModuleName'       => BASE_PATH . '/module/MyModuleName/src',
                'AnotherModuleName'  => BASE_PATH . '/module/AnotherModuleName/src',
                'NewModuleName'      => BASE_PATH . '/module/NewModuleName/src',
            )
        )
    )
);
return [
    'MyModuleName',
    'AnotherModuleName',
    'NewModuleName',
];

Further reading

For detailed information about the Laminas framework and examples see the following:

  • The Laminas Quick Start documentation and Laminas framework documentation portal, it is useful to have a basic knowledge of the Laminas framework before you create your own modules. .
  • Note

    Swarm supports the Laminas component versions in the LICENSE.txt file, features and functions in the Laminas documentation that were introduced in later versions of Laminas will not work with Swarm. The LICENSE.txt file is in the readme folder of your Swarm installation.

  • Example email module, a simple custom module that makes Swarm use a custom email template when it sends out when a comment notification is sent out.
  • Swarm JIRA module, a simple module implementation within Swarm: swarm_install/module/Jira