prevent recursion on postSave-Hook

This commit is contained in:
Marc Michalsky forumZFD 2021-01-26 14:51:33 +01:00
parent 279d6e6576
commit 74b1286d25
Signed by untrusted user who does not match committer: marc.koch
GPG key ID: 12406554CFB028B9
2 changed files with 51 additions and 37 deletions

View file

@ -2,8 +2,10 @@
use CRM_TwingleCampaign_Utils_ExtensionCache as Cache; use CRM_TwingleCampaign_Utils_ExtensionCache as Cache;
use CRM_TwingleCampaign_BAO_Campaign as Campaign; use CRM_TwingleCampaign_BAO_Campaign as Campaign;
use CRM_TwingleCampaign_ExtensionUtil as E;
use CRM_TwingleCampaign_BAO_TwingleApiCall as TwingleApiCall; use CRM_TwingleCampaign_BAO_TwingleApiCall as TwingleApiCall;
class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign { class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
/** /**
@ -15,9 +17,8 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
* *
* @param int|null $id * @param int|null $id
* *
* @throws \Exception
*/ */
function __construct(array $project, int $id = NULL) { public function __construct(array $project, int $id = NULL) {
parent::__construct($project); parent::__construct($project);
$this->id = $id; $this->id = $id;
@ -60,8 +61,8 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
/** /**
* Create the Campaign as a campaign in CiviCRM if it does not exist * Create the Campaign as a campaign in CiviCRM if it does not exist
* *
* @param bool $is_test * @param bool $no_hook
* If true: don't do any changes * Do not trigger postSave hook to prevent recursion
* *
* @return bool * @return bool
* Returns a boolean * Returns a boolean
@ -69,10 +70,7 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
* @throws \CiviCRM_API3_Exception * @throws \CiviCRM_API3_Exception
* @throws \Exception * @throws \Exception
*/ */
public function create(bool $is_test = FALSE): array { public function create(bool $no_hook = FALSE): bool {
// Create campaign only if this is not a test
if (!$is_test) {
// Prepare project values for import into database // Prepare project values for import into database
$values_prepared_for_import = $this->values; $values_prepared_for_import = $this->values;
@ -92,8 +90,13 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
// Set id // Set id
$values_prepared_for_import['id'] = $this->id; $values_prepared_for_import['id'] = $this->id;
// Create campaign // Set a flag to not trigger the hook
$result = civicrm_api3('Campaign', 'create', $values_prepared_for_import); if ($no_hook) {
$_SESSION['CiviCRM']['de.forumzfd.twinglecampaign']['no_hook'] = TRUE;
}
// Create campaign
$result = civicrm_api3('Campaign', 'create', $values_prepared_for_import);
// Update id // Update id
$this->id = $result['id']; $this->id = $result['id'];
@ -152,8 +155,8 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
// Set default for 'allow_more' // Set default for 'allow_more'
$values['allow_more'] = empty($values['allow_more']) $values['allow_more'] = empty($values['allow_more'])
? False ? FALSE
: True; : TRUE;
} }
else { else {

View file

@ -2,45 +2,56 @@
use CRM_TwingleCampaign_BAO_CampaignType as CampaignType; use CRM_TwingleCampaign_BAO_CampaignType as CampaignType;
use CRM_TwingleCampaign_Utils_ExtensionCache as ExtensionCache; use CRM_TwingleCampaign_Utils_ExtensionCache as ExtensionCache;
use CRM_TwingleCampaign_ExtensionUtil as E;
require_once 'twinglecampaign.civix.php'; require_once 'twinglecampaign.civix.php';
use CRM_TwingleCampaign_ExtensionUtil as E;
//
//Civi::dispatcher()->addListener('hook_civicrm_postSave_civicrm_campaign',
// "twinglecampaign_postSave_civicrm_campaign", -1000);
/** /**
* Implements hook_civicrm_postSave_Campaigns(). * Implements hook_civicrm_postSave_Campaigns().
* This function synchronizes TwingleProject campaigns between CiviCRM and
* Twingle when they get created, edited or cloned. To prevent recursion a no
* hook flag is getting used.
* *
* @param $dao * @param $dao
* *
* @throws CiviCRM_API3_Exception * @throws CiviCRM_API3_Exception
*/ */
function twinglecampaign_civicrm_postSave_civicrm_campaign($dao) { function twinglecampaign_civicrm_postSave_civicrm_campaign($dao) {
$twingle_campaign_types = ExtensionCache::getInstance()
->getCampaigns()['campaign_types']; if (empty($_SESSION['CiviCRM']['de.forumzfd.twinglecampaign']['no_hook']) ||
$twingle_campaign_type_ids = []; $_SESSION['CiviCRM']['de.forumzfd.twinglecampaign']['no_hook'] != TRUE) {
$hook_campaign_type_id = $dao->campaign_type_id;
$hook_campaign_id = $dao->id; // extract variables from $dao object
foreach ($twingle_campaign_types as $twingle_campaign_type) { $hook_campaign_type_id = $dao->campaign_type_id;
$id = civicrm_api3('OptionValue', 'get', $hook_campaign_id = $dao->id;
['sequential' => 1, 'name' => $twingle_campaign_type['name']]
// Get campaign type id for TwingleProject
$twingle_project_campaign_type_id = civicrm_api3(
'OptionValue',
'get',
['sequential' => 1, 'name' => 'twingle_project']
)['values'][0]['value']; )['values'][0]['value'];
array_push($twingle_campaign_type_ids, $id);
} // If $dao is a TwingleProject campaign, synchronize it
if (in_array($hook_campaign_type_id, $twingle_campaign_type_ids)) { if ($hook_campaign_type_id == $twingle_project_campaign_type_id) {
if (CRM_Core_Transaction::isActive()) { // If the db transaction is still running, add a function to it that will
CRM_Core_Transaction::addCallback( // be called afterwards
CRM_Core_Transaction::PHASE_POST_COMMIT, if (CRM_Core_Transaction::isActive()) {
'twinglecampaign_postSave_callback', CRM_Core_Transaction::addCallback(
[$hook_campaign_id] CRM_Core_Transaction::PHASE_POST_COMMIT,
); 'twinglecampaign_postSave_callback',
} [$hook_campaign_id]
else { );
twinglecampaign_postSave_callback($hook_campaign_id); }
// If the transaction is already finished, call the function directly
else {
twinglecampaign_postSave_callback($hook_campaign_id);
}
} }
} }
// Remove no hook flag
unset($_SESSION['CiviCRM']['de.forumzfd.twinglecampaign']['no_hook']);
} }
/** /**