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') ? DB
::parseDSN(CIVICRM_LOGGING_DSN
) : DB
::parseDSN(CIVICRM_DSN
);
37 $this->db
= $dsn['database'];
38 $this->log_conn_id
= $log_conn_id;
39 $this->log_date
= $log_date;
44 * Calculate a set of diffs based on the connection_id and changes at a close time.
46 * @param array $tables
48 public function calculateDiffsFromLogConnAndDate($tables) {
49 $differ = new CRM_Logging_Differ($this->log_conn_id
, $this->log_date
);
50 $this->diffs
= $differ->diffsInTables($tables);
58 public function setDiffs($diffs) {
59 $this->diffs
= $diffs;
63 * Revert changes in the array of diffs in $this->diffs.
65 public function revert() {
67 // get custom data tables, columns and types
69 $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)');
70 while ($dao->fetch()) {
71 if (!isset($ctypes[$dao->table_name
])) {
72 $ctypes[$dao->table_name
] = ['entity_id' => 'Integer'];
74 $ctypes[$dao->table_name
][$dao->column_name
] = $dao->data_type
;
77 $diffs = $this->diffs
;
80 foreach ($diffs as $table => $changes) {
81 foreach ($changes as $change) {
82 switch ($change['action']) {
84 if (!isset($deletes[$table])) {
85 $deletes[$table] = [];
87 $deletes[$table][] = $change['id'];
92 if (!isset($reverts[$table])) {
93 $reverts[$table] = [];
95 if (!isset($reverts[$table][$change['id']])) {
96 $reverts[$table][$change['id']] = ['log_action' => $change['action']];
98 $reverts[$table][$change['id']][$change['field']] = $change['from'];
104 // revert inserts by deleting
105 foreach ($deletes as $table => $ids) {
106 CRM_Core_DAO
::executeQuery("DELETE FROM `$table` WHERE id IN (" . implode(', ', array_unique($ids)) . ')');
109 // revert updates by updating to previous values
110 foreach ($reverts as $table => $row) {
114 case (($tableDAO = CRM_Core_DAO_AllCoreTables
::getClassForTable($table)) != FALSE):
115 $dao = new $tableDAO();
116 foreach ($row as $id => $changes) {
118 foreach ($changes as $field => $value) {
119 if ($field == 'log_action') {
122 if (empty($value) and $value !== 0 and $value !== '0') {
125 // Date reaches this point in ISO format (possibly) so strip out stuff
126 // if it does have hyphens of colons demarking the date & it regexes as being a date
127 // or datetime format.
128 if (preg_match('/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/', $value)) {
129 $value = str_replace('-', '', $value);
130 $value = str_replace(':', '', $value);
132 $dao->$field = $value;
134 $changes['log_action'] == 'Delete' ?
$dao->insert() : $dao->update();
140 // custom data tables
142 case in_array($table, array_keys($ctypes)):
143 foreach ($row as $id => $changes) {
144 $inserts = ['id' => '%1'];
146 $params = [1 => [$id, 'Integer']];
148 foreach ($changes as $field => $value) {
149 // don’t try reverting a field that’s no longer there
150 if (!isset($ctypes[$table][$field])) {
153 $fldVal = "%{$counter}";
154 switch ($ctypes[$table][$field]) {
156 $value = substr(CRM_Utils_Date
::isoToMysql($value), 0, 8);
160 $value = CRM_Utils_Date
::isoToMysql($value);
168 $inserts[$field] = "%$counter";
169 $updates[] = "{$field} = {$fldVal}";
170 if ($fldVal != 'DEFAULT') {
171 $params[$counter] = [$value, $ctypes[$table][$field]];
175 if ($changes['log_action'] == 'Delete') {
176 $sql = "INSERT INTO `$table` (" . implode(', ', array_keys($inserts)) . ') VALUES (' . implode(', ', $inserts) . ')';
179 $sql = "UPDATE `$table` SET " . implode(', ', $updates) . ' WHERE id = %1';
181 CRM_Core_DAO
::executeQuery($sql, $params);