CRM-14727 - Move $isActive from SequenceListener to Events
authorTim Otten <totten@civicrm.org>
Tue, 27 May 2014 19:55:59 +0000 (12:55 -0700)
committerTim Otten <totten@civicrm.org>
Wed, 28 May 2014 04:00:11 +0000 (21:00 -0700)
When a case-change listener makes another change to a case, we don't want to
refire all the case-change listeners.  $isActive helps avoid that (infinite)
recursion.

This commit has two important qualities:

 1. The code is simpler. There's a single set() and single unset().
 2. Developers of new case-change listeners don't need to worry
    about recursion problems -- it's handled centrally.

Civi/CCase/Events.php
Civi/CCase/SequenceListener.php

index f1556c490f82ee1f8303bc81e5801e3c291c2ea1..9c5c10c588758508d51b306f12193c588adc6f3b 100644 (file)
 namespace Civi\CCase;
 
 class Events {
+  /**
+   * @var array (int $caseId => bool $active) list of cases for which we are actively firing case-change event
+   *
+   * We do not want to fire case-change events recursively.
+   */
+  static $isActive = array();
+
   /**
    * Following a change to an activity or case, fire the case-change event.
    *
@@ -48,9 +55,11 @@ class Events {
         throw new \CRM_Core_Exception("CRM_Case_Listener does not support entity {$event->entity}");
     }
 
-    if ($caseId) {
+    if ($caseId && !isset(self::$isActive[$caseId])) {
+      self::$isActive[$caseId] = 1;
       $analyzer = new \Civi\CCase\Analyzer($caseId);
       \CRM_Utils_Hook::caseChange($analyzer);
+      unset(self::$isActive[$caseId]);
     }
   }
 
index 5eaa32d0caa11d11a62b3437bba76ea7aefd8348..1472b8afc892f938eb72c166b93e369fa1a5ce9d 100644 (file)
@@ -28,17 +28,10 @@ class SequenceListener implements CaseChangeListener {
     self::singleton()->onCaseChange($event);
   }
 
-  private $isActive = array();
-
   public function onCaseChange(\Civi\CCase\Event\CaseChangeEvent $event) {
     /** @var \Civi\CCase\Analyzer $analyzer */
     $analyzer = $event->analyzer;
 
-    if (isset($this->isActive[$analyzer->getCaseId()])) {
-      return;
-    }
-    $this->isActive[$analyzer->getCaseId()] = 1;
-
     $activitySetXML = $this->getSequenceXml($analyzer->getXml());
     if (!$activitySetXML) {
       return;
@@ -54,12 +47,10 @@ class SequenceListener implements CaseChangeListener {
       if (empty($actIndex[$actTypeId])) {
         // Haven't tried this step yet!
         $this->createActivity($analyzer, $actTypeXML);
-        unset($this->isActive[$analyzer->getCaseId()]);
         return;
       }
       elseif (empty($actIndex[$actTypeId][$actStatuses['Completed']])) {
         // Haven't gotten past this step yet!
-        unset($this->isActive[$analyzer->getCaseId()]);
         return;
       }
     }
@@ -70,9 +61,6 @@ class SequenceListener implements CaseChangeListener {
       'status_id' => 'Closed',
     ));
     $analyzer->flush();
-
-    // Wrap-up
-    unset($this->isActive[$analyzer->getCaseId()]);
   }
 
   /**