In recent months, I’ve designed and developed several Customer Portal projects for SuiteCRM. These applications are working based on SuiteCRM REST API. But there is a serious weakness in SuiteCRM API in response to all that we need.
So, as you know, the most important part of each common Customer Portal is a part that lets users put updates on their Tickets or Cases. But, unfortunately, there is no REST API method in SuiteCRM that allows developers to select the existing updates of a Case or Put new update for a case.
Ok, in this article, I will show you how to add two new APIs to SuiteCRM.
-
To begin, you should understand the structure of SuiteCRM API service. SuiteCRM API has a core and several enhancements version. So, the latest version of SuiteCRM API is 4.2. For reviewing each version’s features, you can visit SugarCRM website.
If you open the ‘service’ folder on this SuiteCRM root folder, then you will see the structure as follows:
So, the folder that their name begins with ‘v
’ is various versions of SuiteCRM APIs. This is very important to know that each version has all previous versions functionalities as also each extended classes from their last version.
-
In each version folder, you will see this common structure:
For creating and developing your own version of SuiteCRM API, you should change some code in all files. It’s very logical and practical that you extend your SuiteCRM API version from the latest version (v 4.1) of SuiteCRM API. So let's start.
- For creating your own service, clone the v4_1 folder and rename it to your version name. I rename it to fcc.
- So, rename the two files (SugarWebServiceImplv4_1.php, SugarWebServiceUtilv4_1.php) and replace v4_1 phrase to your version name. For example, I renamed them to SugarWebServiceImplfcc.php and SugarWebServiceUtilfcc.php. For your knowledge, the main codes of your extended version will be written in these two files.
- Now open the rest.php file. In the rest.php file, you should register and include all of your API version. So, it’s very easy and not complicated. As I mentioned below, my API name is
fcc
. So you can see the code of rest.php for fcc:
require_once('SugarWebServiceImplfcc.php');
$webservice_class = 'SugarRestService';
$webservice_path = 'service/core/SugarRestService.php';
$webservice_impl_class = 'SugarWebServiceImplfcc';
$registry_class = 'registry';
$location = '/service/fcc/rest.php';
$registry_path = 'service/fcc/registry.php';
require_once('service/core/webservice.php');
You should repeat this step for the soap.php file too.
-
So, the next file we discuss is SugarWebServiceUtilfcc.php. The SugarWebServiceUtil[version name].php contains all utilities and helper functions that you use in the main API method. So, this file contains a class that is extended from one of the latest versions. As I mentioned, it’s better to extend from the latest version of SuiteCRM API service that is v4_1. So, the class structure will be such as follows:
So, depending on your API functions needs, you can write your own functions in this class. Also, as you can see, you need to include the SugarWebServicecUtilv4_1.php in your script. It points to the version that you extend your API from.
require_once('service/v4_1/SugarWebServiceUtilv4_1.php');
class SugarWebServiceUtilfcc extends SugarWebServiceUtilv4_1
{
}
-
In this step, we start to write our own API method functions. The main API method and functions are written in the SugarWebServiceImpl[Version Name].php. So, we want to add two new API methods (I suppose you are familiar with SuiteCRM
common functions);
set_case_update
get_case_updates
At first, we write the prototypes of two new functions:
function get_case_updates($session, $module_name, $name_value_list) {
}
And
function set_case_update($session, $module_name, $name_value_list) {
}
Both two new functions have the same parameters:
$session
: The common parameter of all SuiteCRM
API methods. This parameter contains the session Id that the login function returns and shows that the request has a sufficient credential. $module_name
: This parameter belongs to methods that are working for all modules such as get_entry_list
, set_entry
and … . It contains the name of the module that request has been done for its data. In our case, this parameter is not necessary because both methods are working on Case_Updates
module. But I didn’t remove this parameter from the methods prototype. $name_value_list
: This parameter is an array that contains all sent data from the client such as queries, fields values, etc.
So, we wrote the API methods prototypes successfully, now let’s start to write the methods.
-
As it shows, the set_case_update
method has the responsibility to insert or update a case_update
on a case record. So, the method will look like:
$case_update = new AOP_Case_Updates();
$GLOBALS['log']->info('Begin: SugarWebServiceImpl->set_case_update');
if (!self::$helperObject->checkSessionAndModuleAccess
($session, 'invalid_session',
"AOP_Case_Updates", 'read', 'no_access', $error)) {
return;
}
foreach ($name_value_list as &$value) {
$name = $value['name'];
$case_update->$name = $value['value'];
}
$case_update->save();
$GLOBALS['log']->info('End: SugarWebServiceImpl->set_case_update');
return array('id'=> $case_update->id);
At the first line, we create a new instance from AOP_Case_Update
. As you know, in SuiteCRM
for inserting or updating a new record, you just need to get a new instance from a module class. So, when you call the Save
method, if the id field is empty, then a new record will be created and if the id has been filled, then the method updates a record that the id belongs to.
The next code line just writes a new line in the SuiteCRM
log file.
$GLOBALS['log']->info('Begin: SugarWebServiceImpl->set_case_update');
The next condition statement is for checking the credentials and user access. If the session Id is empty or has a wrong value, then the method returns. In another case, if the user does not have sufficient access to the module, the methods return too. At the next statement, there is a foreach
loop that loops through the $anem_value_list
array and fills the $case_update
parameters.
And at the final statement, the save
method of the case_update
instance is called. As I said below, this method works based on the value of Id
property. If the Id
is empty, the method will add a new record and if the id
property has a correct id value, the method will update that record.
And the final line of the method returns the Id
of the new or updated record. It’s a necessary part of all insert
or update
methods to return id
value the code that calls it.
-
The next method of this API is get_case_updates
. This method gets a Case id and returns all of its case_updates
. So the method is very easy:
function get_case_updates($session, $module_name, $name_value_list){
$caseUpdateBean = BeanFactory::getBean('AOP_Case_Updates');
$caseUpdate = $caseUpdateBean->get_full_list
('date_entered desc',"case_id = '" .
$name_value_list[0]['value'] . "' ");
$counter = 0;
foreach ($caseUpdate as &$value) {
$item = array();
$i = 1;
foreach ($value as $key => $val)
{
try
{
if ($i < 22)
{
array_push($item, array
("name" => $key, "value" => $val));
}
}
catch (Exception $e) {
}
$i++;
}
if ($counter == 0)
$items = array($item);
else
array_push($items, $item);
$counter++;
}
$result = array("count" => $i, "items" => $items);
return array('entry_list'=> $result);
}
At the first line, we create a new instance of Case_Update
. It has been done using the BeanFactory::getBean
method. So, at the next line, we call the get_full_list
method. This method gets two string
parameters, sort order, and query statement and returns a list of the records that match the query.
The loop at the next step fills a new array based on suitable return value that the client can handle it.
And at the final line, the method returns the array to the client.
-
Now, we wrote two new API methods. But these are inaccessible for the client. Because we should register these new methods as the rest methods. So, for doing this task, we should write some new code line in registry.php. This file has two methods for registering Functions and Types of the current API version. I have to mention that these new methods are very simple. There are some so complicated APIs that need new variable type and …
So, I write a sample of how to register an API in registry.php:
$this->serviceClass->registerFunction(
'set_case_update',
array('session'=>'xsd:string', 'module_name'=>'xsd:string',
'name_value_list'=>'tns:name_value_list'),
array('return'=>'tns:new_set_entry_result'));