Custom Event – Type
Before Save
Before Save events are executed before the model is saved to the database, following an ascending order based on the value of the position field.
A common use case is when, after an entity has been filled in, default values must be assigned before saving. At this stage, the Before Save event can assign default values to empty fields or apply standard values under certain conditions.
Example: Before Save – Assigning Default Values
In the following example, a Before Save event is configured on the DeepService – Operation model. If the priority field of a new ticket is left empty and the selected category is Network, the event automatically sets the priority to High.
The code is inserted in the “Method” scripting area under: System > Custom Fields > Events Tab.
/* It is tested that the current model instance is new */
if($this->isObjectNew()){
/* We test that the piority field is not filled in, that the ticket type is Incident, and that the selected category is Network */
if(!$this->getPriorityId() && $this->getTypeId() == 1 && $this->getCategory1() == 5){
/* In this case, the Priority field is set to High */
$this->setPriorityId(2);
}
}
After Save
After Save events are executed after the model has been saved in the database, in ascending order based on the position field.
These events are useful when it is necessary to ensure that an object has been saved before performing a configured action. A typical use case involves using the newly generated ID of a record to create a foreign key relationship with another entity.
Example: After Save – Assigning ‘Company Id’ to an Associated User
In this example, an After Save event is configured in the DeepCrm – Contact model. After a contact is saved, the event assigns the related company’s ID to the associated user’s CompanyId field.
Below is the code implemented in the Method scripting area, accessible via the path: System > Custom Fields > Tab Event.
// Checks whether there is an Account ID associated with the current object
if($this->getAccountId()){
// Load the Account object using the loadAccount() method.
$account = $this->loadAccount();
// From the uploaded Account, retrieve the related Company object
$company = $account->loadCompany();
// Load the associated User object using the loadUser() method.
$linkeUser = $this->loadUser();
// Sets the ID of the Company loaded in the User as CompanyId
$linkeUser->setCompanyId($company->getId());
// Save changes to the user object
$linkeUser->save();
}
Before Delete
Before Delete type events are executed before a record is deleted from the database and, consequently, from Deepser. These events follow an ascending order determined by the value of the position attribute.
A frequent use case for the use of a Before Delete type Custom Event is the need to delete any references present in other entities related to the record to be deleted, or, record the successful deletion within a dedicated log file.
Example: Before Delete – Logging Record Deletion
In this example, a Before Delete event is configured in the DeepService – Operation model. It logs the deletion of a ticket in a dedicated log file. The code is written in the “Method” scripting area under: System > Custom Fields > Events Tab.
/* A username of the current user is retrieved */
$currentUsername = Deep::helper('deep_admin')->getCurrentUser()->getUsername();
/* In Before Delete type events the $this object does not contain the full instance of the
object but only the 'entity_id' attribute for this reason the instance of the current object is loaded,
i.e. the one that is about to be deleted via the load method of the deep_service/operation model */
$operation = Deep::getModel('deep_service/operation')->load($this->getId());
/* The string with Title ID and user is formed and will be added to the log */
$logString = 'ID ticket: '. $this->getId() . ' | Titolo: ' . $operation->getTitle(). ' | Utente: '. $currentUsername;
/* Via the static log method of the Deep class the $logString is added to the file
'Ticket_Eliminated.log' if this file does not exist it will be created. */
Deep::log($logString, null, 'Ticket_Eliminati.log');
After Delete
After Delete events are executed after a record has been removed from the database and from Deepser, following an ascending order based on the position field.
A common use case involves updating or removing references after the deletion of a specific service.
Example: After Delete – Updating the Status of a Device Linked to a Deleted User
In this example, a Delete After event is configured in the DeepAdmin – User model. The event updates the status of a device that was associated with the deleted user.
Below is the code implemented in the Method scripting area, accessible via the path: System > Custom Fields > Tab Event.
// Create a collection of devices
$deviceCollection = Deep::getResourceModel('deep_cmdb/ci_collection');
// Adds a filter to display only ci = Device
$deviceCollection->addFieldToFilter('class_id', ['eq' => 2]);
// Adds a filter to the collection to select only devices associated with a given username
$deviceCollection->addFieldToFilter('cust_utente_assegnatario', $this->getUsername());
// iterate through each device in the filtered collection
foreach ($deviceCollection as $device) {
// Sets the status of the device as 0 = inactive
$device->setData('status', 0);
// Save changes made to the device
$device->save();
}
Best Practices
ID Availability
In Before Save events, the entity_id for new objects will only be available after the record is saved.
Avoid Infinite Loops
Incorrect configuration of Before Save or After Save events can lead to infinite loops, causing memory consumption to grow until it reaches the system limit.
Below is an example of a case where code inserted in an After Save event could generate an infinite loop, resulting in excessive memory consumption until the configured system limit is reached.
/* Incorrect code that would cause a loop */
$linkedId = $this->getCustAssociatedOperation();
if($linkedId){
$linkedOperation = Deep::getModel('deep_service/operation')->load($linkedId);
$linkedOperation->setCustAssociatedOperation($this->getId());
$linkedOperation->save();
}
Below is the corrected version of the previously shown code, which includes an appropriate check to prevent the generation of unintended loops.
/* orrected version that avoids unintentional loop triggering */
$linkedId = $this->getCustAssociatedOperation();
if($linkedId){
$linkedOperation = Deep::getModel('deep_service/operation')->load($linkedId);
/* Control needed so that the associated ticket instance save event does not
trigger an event loop */
if(!$linkedOperation->getCustAssociatedOperation()) {
$linkedOperation->setCustAssociatedOperation($this->getId());
$linkedOperation->save();
}
}