From: eileen Date: Mon, 20 Feb 2017 01:30:48 +0000 (+1300) Subject: CRM-20061 Add tables as a parameter on the revert api X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=f16074c9d89c5b561a1712ef5ec7613311122b9a;p=civicrm-core.git CRM-20061 Add tables as a parameter on the revert api --- diff --git a/CRM/Logging/Reverter.php b/CRM/Logging/Reverter.php index 7d838dc641..4e9310ff03 100644 --- a/CRM/Logging/Reverter.php +++ b/CRM/Logging/Reverter.php @@ -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(); - } - } } } diff --git a/api/v3/Logging.php b/api/v3/Logging.php index c1a9010a77..3287b8794f 100644 --- a/api/v3/Logging.php +++ b/api/v3/Logging.php @@ -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'), + ); } diff --git a/tests/phpunit/api/v3/LoggingTest.php b/tests/phpunit/api/v3/LoggingTest.php index 96f3095b64..568cffcfff 100644 --- a/tests/phpunit/api/v3/LoggingTest.php +++ b/tests/phpunit/api/v3/LoggingTest.php @@ -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}'");