array('onApiPrepare', Events::W_EARLY), Events::RESPOND => array('onApiRespond', Events::W_MIDDLE), Events::EXCEPTION => array('onApiException', Events::W_EARLY), ); } /** * @var array (scalar $apiRequestId => CRM_Core_Transaction $tx) */ private $transactions = array(); /** * Determine if an API request should be treated as transactional * * @param \Civi\API\Provider\ProviderInterface $apiProvider * @param array $apiRequest * @return bool */ public function isTransactional($apiProvider, $apiRequest) { if (isset($apiRequest['params']['is_transactional'])) { return \CRM_Utils_String::strtobool($apiRequest['params']['is_transactional']); } return strtolower($apiRequest['action']) == 'create' || strtolower($apiRequest['action']) == 'delete' || strtolower($apiRequest['action']) == 'submit'; } /** * Open a new transaction instance (if appropriate in the current policy) * * @param \Civi\API\Event\PrepareEvent $event */ function onApiPrepare(\Civi\API\Event\PrepareEvent $event) { $apiRequest = $event->getApiRequest(); if ($this->isTransactional($event->getApiProvider(), $apiRequest)) { $this->transactions[$apiRequest['id']] = new \CRM_Core_Transaction(); } } /** * Close any pending transactions */ function onApiRespond(\Civi\API\Event\RespondEvent $event) { $apiRequest = $event->getApiRequest(); if (isset($this->transactions[$apiRequest['id']])) { if (civicrm_error($event->getResponse())) { $this->transactions[$apiRequest['id']]->rollback(); } unset($this->transactions[$apiRequest['id']]); } } /** * Rollback the pending transaction * * @param \Civi\API\Event\ExceptionEvent $event */ function onApiException(\Civi\API\Event\ExceptionEvent $event) { $apiRequest = $event->getApiRequest(); if (isset($this->transactions[$apiRequest['id']])) { $this->transactions[$apiRequest['id']]->rollback(); unset($this->transactions[$apiRequest['id']]); } } }