CRM-20061 Add tables as a parameter on the revert api
authoreileen <emcnaughton@wikimedia.org>
Mon, 20 Feb 2017 01:30:48 +0000 (14:30 +1300)
committereileen <emcnaughton@wikimedia.org>
Mon, 20 Feb 2017 07:33:52 +0000 (20:33 +1300)
CRM/Logging/Reverter.php
api/v3/Logging.php
tests/phpunit/api/v3/LoggingTest.php

index 7d838dc641d251bb2a30a4befbf60febac5bb987..4e9310ff03ed9452e2503b63277b0fa829aece49 100644 (file)
@@ -200,32 +200,6 @@ class CRM_Logging_Reverter {
       }
     }
 
-    // CRM-7353: if nothing altered civicrm_contact, touch it; this will
-    // make sure there’s an entry in log_civicrm_contact for this revert
-    if (empty($diffs['civicrm_contact'])) {
-      $query = "
-                SELECT id FROM `{$this->db}`.log_civicrm_contact
-                WHERE log_conn_id = %1 AND log_date BETWEEN DATE_SUB(%2, INTERVAL 10 SECOND) AND DATE_ADD(%2, INTERVAL 10 SECOND)
-                ORDER BY log_date DESC LIMIT 1
-            ";
-      $params = array(
-        1 => array($this->log_conn_id, 'String'),
-        2 => array($this->log_date, 'String'),
-      );
-      $cid = CRM_Core_DAO::singleValueQuery($query, $params);
-      if (!$cid) {
-        return;
-      }
-
-      $dao = new CRM_Contact_DAO_Contact();
-      $dao->id = $cid;
-      if ($dao->find(TRUE)) {
-        // CRM-8102: MySQL can’t parse its own dates
-        $dao->birth_date = CRM_Utils_Date::isoToMysql($dao->birth_date);
-        $dao->deceased_date = CRM_Utils_Date::isoToMysql($dao->deceased_date);
-        $dao->save();
-      }
-    }
   }
 
 }
index c1a9010a777c08386c2da2c993cbea127b118863..3287b8794f675febda5dc29548e21dbcc7077f8f 100644 (file)
@@ -44,7 +44,8 @@
 function civicrm_api3_logging_revert($params) {
   $schema = new CRM_Logging_Schema();
   $reverter = new CRM_Logging_Reverter($params['log_conn_id'], CRM_Utils_Array::value('log_date', $params));
-  $reverter->calculateDiffsFromLogConnAndDate($schema->getLogTablesForContact());
+  $tables = !empty($params['tables']) ? (array) $params['tables'] : $schema->getLogTablesForContact();
+  $reverter->calculateDiffsFromLogConnAndDate($tables);
   $reverter->revert();
   return civicrm_api3_create_success(1);
 }
@@ -73,6 +74,12 @@ function _civicrm_api3_logging_revert_spec(&$params) {
     'api.default' => '10 SECOND',
     'description' => ts('Used when log_date is passed in'),
   );
+
+  $params['tables'] = array(
+    'title' => ts('Tables to revert'),
+    'type' => CRM_Utils_Type::T_STRING,
+    'description' => ts('Tables to revert, if not set all contact-referring entities will be reverted'),
+  );
 }
 
 /**
@@ -89,7 +96,8 @@ function civicrm_api3_logging_get($params) {
   $schema = new CRM_Logging_Schema();
   $interval = (empty($params['log_date'])) ? NULL : $params['interval'];
   $differ = new CRM_Logging_Differ($params['log_conn_id'], CRM_Utils_Array::value('log_date', $params), $interval);
-  return civicrm_api3_create_success($differ->getAllChangesForConnection($schema->getLogTablesForContact()));
+  $tables = !empty($params['tables']) ? (array) $params['tables'] : $schema->getLogTablesForContact();
+  return civicrm_api3_create_success($differ->getAllChangesForConnection($tables));
 }
 
 /**
@@ -116,4 +124,9 @@ function _civicrm_api3_logging_get_spec(&$params) {
     'api.default' => '10 SECOND',
     'description' => ts('Used when log_date is passed in'),
   );
+  $params['tables'] = array(
+    'title' => ts('Tables to query'),
+    'type' => CRM_Utils_Type::T_STRING,
+    'description' => ts('Tables to query, if not set all contact-referring entities will be queried'),
+  );
 }
index 96f3095b6498b257f28b2ca5d0ffe43bed2c3025..568cffcfffc9d6e17e1031683273d2c37f37d982 100644 (file)
@@ -47,7 +47,7 @@ class api_v3_LoggingTest extends CiviUnitTestCase {
    * Clean up log tables.
    */
   protected function tearDown() {
-    $this->quickCleanup(array('civicrm_email'));
+    $this->quickCleanup(array('civicrm_email', 'civicrm_address'));
     parent::tearDown();
     $this->callAPISuccess('Setting', 'create', array('logging' => FALSE));
     $schema = new CRM_Logging_Schema();
@@ -213,6 +213,9 @@ class api_v3_LoggingTest extends CiviUnitTestCase {
 
   /**
    * Check the triggers were created and look OK.
+   *
+   * @param bool $unique
+   *   Is the site configured for unique logging connection IDs per CRM-18193?
    */
   protected function checkTriggersCreated($unique) {
     $dao = CRM_Core_DAO::executeQuery("SHOW TRIGGERS LIKE 'civicrm_contact'");
@@ -289,6 +292,57 @@ class api_v3_LoggingTest extends CiviUnitTestCase {
     $this->callAPISuccessGetCount('Email', array('id' => $email['id']), 0);
   }
 
+  /**
+   * Ensure that a limited list of tables can be reverted.
+   *
+   * In this case ONLY civicrm_address is reverted and we check that email, contact and contribution
+   * entities have not been.
+   *
+   * @throws \Exception
+   */
+  public function testRevertRestrictedTables() {
+
+    CRM_Core_DAO::executeQuery("SET @uniqueID = 'temp name'");
+    $this->callAPISuccessGetValue('Setting', array('name' => 'logging_all_tables_uniquid'), TRUE);
+    $this->callAPISuccess('Setting', 'create', array('logging' => TRUE));
+
+    $contactId = $this->individualCreate(array('address' => array(array('street_address' => '27 Cool way', 'location_type_id' => 1))));
+    $contact = $this->callAPISuccessGetSingle('contact', array('id' => $contactId));
+    $this->assertEquals('Anthony', $contact['first_name']);
+    $this->assertEquals('anthony_anderson@civicrm.org', $contact['email']);
+    $this->assertEquals('27 Cool way', $contact['street_address']);
+
+    CRM_Core_DAO::executeQuery("SET @uniqueID = 'bitty bot bot'");
+    $this->callAPISuccess('Contact', 'create', array(
+        'id' => $contactId,
+        'first_name' => 'Dopey',
+        'address' => array(array('street_address' => '25 Dorky way', 'location_type_id' => 1)),
+        'email' => array('email' => array('email' => 'dopey@mail.com', 'location_type_id' => 1)),
+        'api.contribution.create' => array('financial_type_id' => 'Donation', 'receive_date' => 'now', 'total_amount' => 10),
+      )
+    );
+    $contact = $this->callAPISuccessGetSingle('contact', array('id' => $contactId, 'return' => array('first_name', 'email', 'modified_date', 'street_address')));
+    $this->assertEquals('Dopey', $contact['first_name']);
+    $this->assertEquals('dopey@mail.com', $contact['email']);
+    $this->assertEquals('25 Dorky way', $contact['street_address']);
+    $modifiedDate = $contact['modified_date'];
+    // To protect against the modified date not changing due to the updates being too close together.
+    sleep(1);
+    $loggings = $this->callAPISuccess('Logging', 'get', array('log_conn_id' => 'bitty bot bot', 'tables' => array('civicrm_address')));
+    $this->assertEquals('civicrm_address', $loggings['values'][0]['table'], CRM_Core_DAO::executeQuery('SELECT * FROM log_civicrm_address')->toArray());
+    $this->assertEquals(1, $loggings['count'], CRM_Core_DAO::executeQuery('SELECT * FROM log_civicrm_address')->toArray());
+    $this->assertEquals('27 Cool way', $loggings['values'][0]['from']);
+    $this->assertEquals('25 Dorky way', $loggings['values'][0]['to']);
+    $this->callAPISuccess('Logging', 'revert', array('log_conn_id' => 'bitty bot bot', 'tables' => array('civicrm_address')));
+
+    $contact = $this->callAPISuccessGetSingle('contact', array('id' => $contactId, 'return' => array('first_name', 'email', 'modified_date', 'street_address')));
+    $this->assertEquals('Dopey', $contact['first_name']);
+    $this->assertEquals('dopey@mail.com', $contact['email']);
+    $this->assertEquals('27 Cool way', $contact['street_address']);
+    $this->callAPISuccessGetCount('Contribution', array('contact_id' => $contactId), 1);
+    $this->assertTrue(strtotime($modifiedDate) < strtotime($contact['modified_date']));
+  }
+
   /**
    * Test changes can be reverted.
    */
@@ -379,7 +433,7 @@ class api_v3_LoggingTest extends CiviUnitTestCase {
    * @param string $table
    * @param string $column
    *
-   * @return \CRM_Core_DAO|object
+   * @return bool
    */
   protected function checkColumnExistsInTable($table, $column) {
     $dao = CRM_Core_DAO::executeQuery("SHOW columns FROM {$table} WHERE Field = '{$column}'");