3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
17 class CRM_Logging_Reverter
{
23 * The diffs to be reverted.
32 * @param string $log_conn_id
35 public function __construct($log_conn_id, $log_date) {
36 $dsn = defined('CIVICRM_LOGGING_DSN') ? CRM_Utils_SQL
::autoSwitchDSN(CIVICRM_LOGGING_DSN
) : CRM_Utils_SQL
::autoSwitchDSN(CIVICRM_DSN
);
37 $dsn = DB
::parseDSN($dsn);
38 $this->db
= $dsn['database'];
39 $this->log_conn_id
= $log_conn_id;
40 $this->log_date
= $log_date;
45 * Calculate a set of diffs based on the connection_id and changes at a close time.
47 * @param array $tables
49 public function calculateDiffsFromLogConnAndDate($tables) {
50 $differ = new CRM_Logging_Differ($this->log_conn_id
, $this->log_date
);
51 $this->diffs
= $differ->diffsInTables($tables);
59 public function setDiffs($diffs) {
60 $this->diffs
= $diffs;
64 * Revert changes in the array of diffs in $this->diffs.
66 public function revert() {
68 // get custom data tables, columns and types
70 $dao = CRM_Core_DAO
::executeQuery('SELECT table_name, column_name, data_type FROM civicrm_custom_group cg JOIN civicrm_custom_field cf ON (cf.custom_group_id = cg.id)');
71 while ($dao->fetch()) {
72 if (!isset($ctypes[$dao->table_name
])) {
73 $ctypes[$dao->table_name
] = ['entity_id' => 'Integer'];
75 $ctypes[$dao->table_name
][$dao->column_name
] = $dao->data_type
;
78 $diffs = $this->diffs
;
81 foreach ($diffs as $table => $changes) {
82 foreach ($changes as $change) {
83 switch ($change['action']) {
85 if (!isset($deletes[$table])) {
86 $deletes[$table] = [];
88 $deletes[$table][] = $change['id'];
93 if (!isset($reverts[$table])) {
94 $reverts[$table] = [];
96 if (!isset($reverts[$table][$change['id']])) {
97 $reverts[$table][$change['id']] = ['log_action' => $change['action']];
99 $reverts[$table][$change['id']][$change['field']] = $change['from'];
105 // revert inserts by deleting
106 foreach ($deletes as $table => $ids) {
107 CRM_Core_DAO
::executeQuery("DELETE FROM `$table` WHERE id IN (" . implode(', ', array_unique($ids)) . ')');
110 // revert updates by updating to previous values
111 foreach ($reverts as $table => $row) {
115 case (($tableDAO = CRM_Core_DAO_AllCoreTables
::getClassForTable($table)) != FALSE):
116 $dao = new $tableDAO();
117 foreach ($row as $id => $changes) {
119 foreach ($changes as $field => $value) {
120 if ($field == 'log_action') {
123 if (empty($value) and $value !== 0 and $value !== '0') {
126 // Date reaches this point in ISO format (possibly) so strip out stuff
127 // if it does have hyphens of colons demarking the date & it regexes as being a date
128 // or datetime format.
129 if (preg_match('/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/', $value)) {
130 $value = str_replace('-', '', $value);
131 $value = str_replace(':', '', $value);
133 $dao->$field = $value;
135 $changes['log_action'] == 'Delete' ?
$dao->insert() : $dao->update();
141 // custom data tables
143 case array_key_exists($table, $ctypes):
144 foreach ($row as $id => $changes) {
145 $inserts = ['id' => '%1'];
147 $params = [1 => [$id, 'Integer']];
149 foreach ($changes as $field => $value) {
150 // don’t try reverting a field that’s no longer there
151 if (!isset($ctypes[$table][$field])) {
154 $fldVal = "%{$counter}";
155 switch ($ctypes[$table][$field]) {
157 $value = substr(CRM_Utils_Date
::isoToMysql($value), 0, 8);
161 $value = CRM_Utils_Date
::isoToMysql($value);
169 $inserts[$field] = "%$counter";
170 $updates[] = "{$field} = {$fldVal}";
171 if ($fldVal != 'DEFAULT') {
172 $params[$counter] = [$value, $ctypes[$table][$field]];
176 if ($changes['log_action'] == 'Delete') {
177 $sql = "INSERT INTO `$table` (" . implode(', ', array_keys($inserts)) . ') VALUES (' . implode(', ', $inserts) . ')';
180 $sql = "UPDATE `$table` SET " . implode(', ', $updates) . ' WHERE id = %1';
182 CRM_Core_DAO
::executeQuery($sql, $params);