Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(POC) Add hook_civicrm_postCommit, a less foot-gunny variant of hook_civicrm_post #15338

Merged
merged 1 commit into from
Mar 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CRM/Core/Transaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -252,4 +252,24 @@ public static function addCallback($phase, $callback, $params = NULL, $id = NULL
$frame->addCallback($phase, $callback, $params, $id);
}

/**
* Whenever hook_civicrm_post fires, schedule an equivalent
* call to hook_civicrm_postCommit.
*
* @param \Civi\Core\Event\PostEvent $e
* @see CRM_Utils_Hook::post
*/
public static function addPostCommit($e) {
// Do we want to dedupe post-commit hooks for the same txn? Setting an ID
// would allow this.
// $id = $e->entity . chr(0) . $e->action . chr(0) . $e->id;
$frame = \Civi\Core\Transaction\Manager::singleton()->getBaseFrame();
if ($frame) {
$frame->addCallback(self::PHASE_POST_COMMIT, ['CRM_Utils_Hook', 'postCommit'], [$e->action, $e->entity, $e->id, $e->object]);
}
else {
\CRM_Utils_Hook::postCommit($e->action, $e->entity, $e->id, $e->object);
}
}

}
30 changes: 30 additions & 0 deletions CRM/Utils/Hook.php
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,36 @@ public static function post($op, $objectName, $objectId, &$objectRef = NULL) {
return $event->getReturnValues();
}

/**
* This hook is equivalent to post(), except that it is guaranteed to run
* outside of any SQL transaction. The objectRef is not modifiable.
*
* This hook is defined for two cases:
*
* 1. If the original action runs within a transaction, then the hook fires
* after the transaction commits.
* 2. If the original action runs outside a transaction, then the data was
* committed immediately, and we can run the hook immediately.
*
* @param string $op
* The type of operation being performed.
* @param string $objectName
* The name of the object.
* @param int $objectId
* The unique identifier for the object.
* @param object $objectRef
* The reference to the object if available.
*
* @return mixed
* based on op. pre-hooks return a boolean or
* an error message which aborts the operation
*/
public static function postCommit($op, $objectName, $objectId, $objectRef = NULL) {
$event = new \Civi\Core\Event\PostEvent($op, $objectName, $objectId, $objectRef);
\Civi::dispatcher()->dispatch('hook_civicrm_postCommit', $event);
return $event->getReturnValues();
}

/**
* This hook retrieves links from other modules and injects it into.
* the view contact tabs
Expand Down
1 change: 1 addition & 0 deletions Civi/Core/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ public function createEventDispatcher($container) {
$dispatcher->addListener(SystemInstallEvent::EVENT_NAME, ['\Civi\Core\InstallationCanary', 'check']);
$dispatcher->addListener(SystemInstallEvent::EVENT_NAME, ['\Civi\Core\DatabaseInitializer', 'initialize']);
$dispatcher->addListener(SystemInstallEvent::EVENT_NAME, ['\Civi\Core\LocalizationInitializer', 'initialize']);
$dispatcher->addListener('hook_civicrm_post', ['\CRM_Core_Transaction', 'addPostCommit'], -1000);
$dispatcher->addListener('hook_civicrm_pre', ['\Civi\Core\Event\PreEvent', 'dispatchSubevent'], 100);
$dispatcher->addListener('hook_civicrm_post', ['\Civi\Core\Event\PostEvent', 'dispatchSubevent'], 100);
$dispatcher->addListener('hook_civicrm_post::Activity', ['\Civi\CCase\Events', 'fireCaseChange']);
Expand Down