Plugins can be created to add REST endpoints to ProcessMaker in version 3.0.1.7 and later. Follow the steps below to create a new REST endpoint.
Create a plugin
The Gulliver framework is used to create new plugins in ProcessMaker. This tool exports and packages the new plugins, so they can be imported into other installations of ProcessMaker. Note that new plugins can only be developed in Linux/UNIX installations of ProcessMaker, but then they can be imported into Windows or Linux/UNIX installations.
The following steps describe how to create a plugin with Gulliver:
Login as root (or use the sudo
command). Then, make a symbolic link between the gulliver/bin/gulliver directory and the workflow/engine directory:
Generally ProcessMaker is installed under the /opt/processmaker directory, so that directory will be used for all subsequent examples:
Change to the /opt/processmaker/workflow/engine directory and execute the php gulliver
command to see a list of options:
Then, create the new plugin:
For example:
After executing this command, the script will ask a series of yes/no questions. Unless the new REST endpoint will need these features, type "n" to answer no to the following questions:
- Change system logo? n
- Create an example page? n
- Create new option in the menu of cases? n
- Create the Role 'PROCESSMAKER_PLUGIN_NAME' and the Permission 'PM_PLUGIN_NAME'? n
- Create external step for Processmaker? n
- Create a PmFunction Class for extending Processmaker? n
When the plugin is created, its new files will be placed in an external plugins directory in the same location where ProcessMaker is installed. For example, if ProcessMaker is installed at /opt/processmaker and the new plugin is named epSample, then it will be located at /opt/plugins/epSample.
Make symbolic links from the generated plugin files to the /opt/processmaker/workflow/engine/plugins directory. For example:
Note: It is recommended to create symbolic links, but it is also possible to directly copy the plugin files to the /opt/processmaker/workflow/engine/plugins/ directory.
Configuration of the REST plugin
It is recommended to grant write permissions to the entire plugins folder for development purposes:
Then, edit the /opt/plugins/pluginName/pluginName.php file and add the following line to the pluginNamePlugin() function in order to enable it to be accessed by REST:
For example, the following code is used for the epSample plugin:
{
$res = parent::PMPlugin($sNamespace, $sFilename);
$this->sFriendlyName = "epSample Plugin";
$this->sDescription = "Autogenerated plugin for class epSample";
$this->sPluginFolder = "epSample";
$this->sSetupPage = "setup";
$this->iVersion = 1;
//$this->iPMVersion = 2425;
$this->aWorkspaces = null;
//$this->aWorkspaces = array("os");
$this->enableRestService(true);
return $res;
}
In order to define the REST endpoints for the plugin, first create the following directory path:
/opt/plugins/pluginName/pluginName/src/Services/Api/PluginName
For example:
Note: The first letter of PluginName needs to be in upper case, so make sure that the final directory in the path is src/Services/Api/EpSample and not src/Services/Api/epSample.
Then create the endpoints in a PHP file inside this directory. In this example, the PHP file is named:
/opt/plugins/epSample/epSample/src/Services/Api/EpSample/Sample.php
Now the plugin has the following file structure:
When done editing the plugin's files, then login to ProcessMaker as a user who has the PM_SETUPADVANCE permission in her role, such as the “admin” user. Go to Admin > Plugins > Plugins Manager and the new plugin should appear in the list.
Click on the plugin to select it and then click on the Enable button to activate it.
Note: If the new plugin doesn't appear in the list, then the plugin files probably are not readable by the Apache user, so either use chmod to make them readable or use chown to change the owner of the plugins to the Apache user (which is named apache
in Red Hat/CentOS or www-data
in Debian/Ubuntu). If the files are readable by the Apache user, then there is probably a problem in the pluginName.php file or in the file structure of the plugin. Also, some file editors such as gedit create a hidden file in the same location when editing files. Delete these hidden files, because they may be read by the plugin.
When editing a plugin's files, changes to the definition of an endpoint will not be automatically registered in ProcessMaker. Each time an endpoint's URL, its GET or POST variables or the parameters of the function it calls are changed, the shared/sites/workspace/routes.php file needs to be deleted so that it will automatically be regenerated the next time a REST endpoint is called. The routes.php file can be deleted by either by disabled and then reenabled the plugin in the ProcessMaker interface or by manually deleting it with the command:
On the other hand, it is not necessary to delete the routes.php file if just changing code inside a function called by the REST endpoint.
Testing the new REST endpoint
The Postman extension in Chrome or HttpRequester add-on in Firefox can be used to send requests to the new REST endpoint, which is located at the address:
{server-address}/api/1.0/{workspace}/{plugin-name}/{routed-path}
In our case the path is:
http://127.0.0.1:3020/api/1.0/workflow/plugin-EpSample/sample/hello/{var}
Now you can check the response with Postman or HttpRequester.
Note: It may be necessary to re-enable the plugin within ProcessMaker each time the endpoint file has been modified.
REST endpoint creation
Supported Annotations:
You may use PHPDoc comments to annotate your API methods. All tags except @url
, @param
and @var
can also be defined at the class level so that they will be applied for all the API methods. You can override them at method level individually when needed.
HTTP Methods:
@url GET|POST|PUT|PATCH|DELETE custom/{dynamic}/route
Access:
@access private|public|protected|hybrid
Smart routing:
@smart-auto-routing true|false
Parameters:
@param [type] Name [Description] {@name value}
For example:
This method is only recommended when you define a GET request. There is no need to define the route. Only define the class name.
//example:
function postMethod($anyparameter, $parameter=optional)
{
return "Post method called";
}
//POST request:
// Api/method/{parameter}
Notice that the HTTP method is defined along with the function name and the route for this method is in the path of the function name.
Parameters:
The function parameter definition can be optional as shown above.
Smart Auto routing:
It is also an automatic method, which allows all possible routes to be created for the function's defined parameters.
/**
* @smart-auto-routing true
*/
public function sRouting($p1, $p2, $p3='optional')
{
return 'smart routing sample called parameters'.$p1.$p2.$p3;
}
Manual Routing
In this routing it is necessary to define the path and the HTTP method.
The URI (Uniform Resource Identifier) of the REST endpoint, which is its route, is created manually using a PHPDoc comment. We can specify as many routes as we want.
* Manually routed method. We can specify as many routes as we want.
*
* @url POST smanual
* @url POST smanual/{param}
* @url GET any/required/path
*/
public function whatEver($param)
{
return 'Manual routed called'.$param;
}
Note: If the flush-cache command is executed after creating an endpoint, the new endpoint is automatically regenerated.
Examples
"GET" example
use ProcessMaker\Services\Api;
class Sample extends Api
{
private $_keys;
private $_values;
function add($key, $value){
$this->_keys[]=$key;
$this->_values[]=$value;
}
function __construct($key, $value){
$this->keys[]=$key;
$this->values[]=$value;
}
/**
* @url GET /sample/new/:var/:content
*/
public function newsample($var,$content)
{
$s = new Sample("firstkey","secondvalue");
$newarray=(array) $s;
return $newarray;
}
Note that the namespace is important in the REST endpoint PHP class.
"POST" example
* @url POST /sample/new/{var}/{content}
*/
public function newsample($var,$content)
{
$s = new Sample();
$newarray=(array) $s;
return $newarray;
}
"PUT" example
* @url PUT /sample/new/{var}/{content}
*/
public function newsample($var,$content) {
$s = new Sample();
$newarray=(array) $s;
return $newarray;
}