Persistent Observer - allow to listen for event for all records of a model
authorPaul Mehrer <p.mehrer@metaways.de>
Thu, 29 Jun 2017 09:58:29 +0000 (11:58 +0200)
committerCornelius Weiss <c.weiss@metaways.de>
Thu, 29 Jun 2017 13:54:27 +0000 (15:54 +0200)
- allow to listen for a event for all records of a given model (instead of
  just one specific record)
- change API, fire event takes an event now. So concrete implementation can
  pass additional information through the fired event

Change-Id: Ia1deb210f4a9bfe0d36965590a3465ed3f98c90e
Reviewed-on: http://gerrit.tine20.com/customers/4976
Tested-by: Jenkins CI (http://ci.tine20.com/)
Reviewed-by: Cornelius Weiss <c.weiss@metaways.de>
tests/tine20/ExampleApplication/ControllerTest.php
tine20/Tinebase/Container.php
tine20/Tinebase/Model/PersistentObserver.php
tine20/Tinebase/Record/PersistentObserver.php
tine20/Tinebase/Setup/Update/Release10.php
tine20/Tinebase/Setup/setup.xml

index 3731c6d..f1bbedd 100644 (file)
@@ -37,7 +37,9 @@ class ExampleApplication_ControllerTest extends ExampleApplication_TestCase
 
         ob_start();
         ob_clean();
-        $observerController->fireEvent($observable, 'Tinebase_Event_Record_Update');
+        $event = new Tinebase_Event_Record_Update();
+        $event->observable = $observable;
+        $observerController->fireEvent($event);
         $result = ob_get_clean();
 
         $this->assertEquals('catched record update for observing id: exampleIdentifier', $result);
index 9514a0a..11758d1 100644 (file)
@@ -1112,7 +1112,9 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract implements Tineba
             $this->deleteContainerContents($container, $_ignoreAcl);
             $deletedContainer = $this->_setRecordMetaDataAndUpdate($container, 'delete');
 
-            Tinebase_Record_PersistentObserver::getInstance()->fireEvent($deletedContainer, 'Tinebase_Event_Record_Delete');
+            $event = new Tinebase_Event_Record_Delete();
+            $event->observable = $deletedContainer;
+            Tinebase_Record_PersistentObserver::getInstance()->fireEvent($event);
         } catch (Exception $e) {
             $tm->rollBack();
             throw $e;
@@ -1948,7 +1950,9 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract implements Tineba
         unset($oldContainer->account_grants);
         $this->_writeModLog($result, $oldContainer);
 
-        Tinebase_Record_PersistentObserver::getInstance()->fireEvent($result, 'Tinebase_Event_Record_Update');
+        $event = new Tinebase_Event_Record_Update();
+        $event->observable = $result;
+        Tinebase_Record_PersistentObserver::getInstance()->fireEvent($event);
 
         Tinebase_TransactionManager::getInstance()->commitTransaction($transactionId);
 
index 98c5b51..b9d21cc 100644 (file)
@@ -38,7 +38,7 @@ class Tinebase_Model_PersistentObserver extends Tinebase_Record_Abstract
         'created_by'             => array('allowEmpty' => true,        ),
         'creation_time'          => array('allowEmpty' => true         ),
         'observable_model'       => array('presence' => 'required', 'allowEmpty' => false),
-        'observable_identifier'  => array('presence' => 'required', 'allowEmpty' => false, 'Alnum'),
+        'observable_identifier'  => array('allowEmpty' => true, 'Alnum'),
         'observer_model'         => array('presence' => 'required', 'allowEmpty' => false),
         'observer_identifier'    => array('presence' => 'required', 'allowEmpty' => false, 'Alnum'),
         'observed_event'         => array('presence' => 'required', 'allowEmpty' => false)
index d13ee09..b74f6bd 100644 (file)
@@ -81,15 +81,10 @@ class Tinebase_Record_PersistentObserver
     
     /**
      *
-     * @param Tinebase_Record_Interface $_observable 
-     * @param string $_event
+     * @param Tinebase_Event_Observer_Abstract $_event
      */
-    public function fireEvent(Tinebase_Record_Interface $_observable, $_event)
+    public function fireEvent(Tinebase_Event_Observer_Abstract $_event)
     {
-        if (!class_exists($_event)) {
-            throw new Tinebase_Exception_InvalidArgument('Event ' . $_event . ' doesn\'t exist');
-        }
-
         $setOuterCall = false;
         if (true === $this->_outerCall) {
             $this->_eventRecursionPrevention = array();
@@ -98,10 +93,7 @@ class Tinebase_Record_PersistentObserver
         }
 
         try {
-            $observers = $this->getObserversByEvent($_observable, $_event);
-            /** @var Tinebase_Event_Observer_Abstract $eventObject */
-            $eventObject = new $_event();
-            $eventObject->observable = $_observable;
+            $observers = $this->getObserversByEvent($_event->observable, get_class($_event));
 
             /** @var Tinebase_Model_PersistentObserver $observer */
             foreach ($observers as $observer) {
@@ -120,9 +112,9 @@ class Tinebase_Record_PersistentObserver
                     $controller = $this->_controllerCache[$observer->observer_model];
                 }
 
-                $eventObject->persistentObserver = $observer;
+                $_event->persistentObserver = $observer;
 
-                $controller->handleEvent($eventObject);
+                $controller->handleEvent($_event);
             }
         } finally {
             $this->_outerCall = $setOuterCall;
@@ -237,11 +229,12 @@ class Tinebase_Record_PersistentObserver
      */
     protected function getObserversByEvent(Tinebase_Record_Interface $_observable,  $_event)
     {
-        $where = array(
-            $this->_db->quoteIdentifier('observable_model') .       ' = ' . $this->_db->quote(get_class($_observable)),
-            $this->_db->quoteIdentifier('observable_identifier') .  ' = ' . $this->_db->quote((string)$_observable->getId()),
-            $this->_db->quoteIdentifier('observed_event') .         ' = ' . $this->_db->quote((string)$_event)
-        );
+        $where =
+            $this->_db->quoteIdentifier('observable_model') .      ' = ' . $this->_db->quote(get_class($_observable)) . ' AND (' .
+            $this->_db->quoteIdentifier('observable_identifier') . ' = ' . $this->_db->quote((string)$_observable->getId()) . ' OR ' .
+            $this->_db->quoteIdentifier('observable_identifier') . ' IS NULL ) AND ' .
+            $this->_db->quoteIdentifier('observed_event') .        ' = ' . $this->_db->quote((string)$_event)
+        ;
 
         return new Tinebase_Record_RecordSet('Tinebase_Model_PersistentObserver', $this->_table->fetchAll($where)->toArray(), true);
     }
index fedf482..2d644ab 100644 (file)
@@ -1179,4 +1179,45 @@ class Tinebase_Setup_Update_Release10 extends Setup_Update_Abstract
 
         $this->setApplicationVersion('Tinebase', '10.29');
     }
+
+    /**
+     * update to 10.30
+     *
+     * add scope column to importexport_definition
+     */
+    public function update_29()
+    {
+        $this->_backend->dropIndex('record_observer', 'observable-observer-event');
+
+        $this->_backend->alterCol('record_observer', new Setup_Backend_Schema_Field_Xml('<field>
+                    <name>observable_identifier</name>
+                    <type>text</type>
+                    <length>40</length>
+                    <notnull>false</notnull>
+                </field>'));
+
+        $this->_backend->addIndex('record_observer', new Setup_Backend_Schema_Index_Xml('<index>
+                    <name>observable-observer-event</name>
+                    <unique>true</unique>
+                    <field>
+                        <name>observable_model</name>
+                    </field>
+                    <field>
+                        <name>observed_event</name>
+                    </field>
+                    <field>
+                        <name>observable_identifier</name>
+                    </field>
+                    <field>
+                        <name>observer_model</name>
+                    </field>
+                    <field>
+                        <name>observer_identifier</name>
+                    </field>
+                </index>'));
+
+        $this->setTableVersion('record_observer', 5);
+
+        $this->setApplicationVersion('Tinebase', '10.30');
+    }
 }
index 281fd4b..8be429e 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <application>
     <name>Tinebase</name>
-    <version>10.29</version>
+    <version>10.30</version>
     <tables>
         <table>
             <name>applications</name>
 
         <table>
             <name>record_observer</name>
-            <version>4</version>
+            <version>5</version>
             <declaration>
                 <field>
                     <name>id</name>
                     <name>observable_identifier</name>
                     <type>text</type>
                     <length>40</length>
-                    <notnull>true</notnull>
+                    <notnull>false</notnull>
                 </field>
                 <field>
                     <name>observer_model</name>
                         <name>observable_model</name>
                     </field>
                     <field>
+                        <name>observed_event</name>
+                    </field>
+                    <field>
                         <name>observable_identifier</name>
                     </field>
                     <field>
                     <field>
                         <name>observer_identifier</name>
                     </field>
-                    <field>
-                        <name>observed_event</name>
-                    </field>
                 </index>
                 <index>
                     <name>observer</name>