| 1 | <?php |
| 2 | /* |
| 3 | +--------------------------------------------------------------------+ |
| 4 | | CiviCRM version 4.3 | |
| 5 | +--------------------------------------------------------------------+ |
| 6 | | Copyright CiviCRM LLC (c) 2004-2013 | |
| 7 | +--------------------------------------------------------------------+ |
| 8 | | This file is a part of CiviCRM. | |
| 9 | | | |
| 10 | | CiviCRM is free software; you can copy, modify, and distribute it | |
| 11 | | under the terms of the GNU Affero General Public License | |
| 12 | | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | |
| 13 | | | |
| 14 | | CiviCRM is distributed in the hope that it will be useful, but | |
| 15 | | WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
| 17 | | See the GNU Affero General Public License for more details. | |
| 18 | | | |
| 19 | | You should have received a copy of the GNU Affero General Public | |
| 20 | | License and the CiviCRM Licensing Exception along | |
| 21 | | with this program; if not, contact CiviCRM LLC | |
| 22 | | at info[AT]civicrm[DOT]org. If you have questions about the | |
| 23 | | GNU Affero General Public License or the licensing of CiviCRM, | |
| 24 | | see the CiviCRM license FAQ at http://civicrm.org/licensing | |
| 25 | +--------------------------------------------------------------------+ |
| 26 | */ |
| 27 | |
| 28 | /** |
| 29 | * |
| 30 | * @package CRM |
| 31 | * @copyright CiviCRM LLC (c) 2004-2013 |
| 32 | * $Id$ |
| 33 | * |
| 34 | */ |
| 35 | class CRM_Logging_ReportDetail extends CRM_Report_Form { |
| 36 | protected $cid; |
| 37 | protected $db; |
| 38 | protected $log_conn_id; |
| 39 | protected $log_date; |
| 40 | protected $raw; |
| 41 | protected $tables = array(); |
| 42 | protected $interval = '10 SECOND'; |
| 43 | |
| 44 | // detail/summary report ids |
| 45 | protected $detail; |
| 46 | protected $summary; |
| 47 | |
| 48 | function __construct() { |
| 49 | // don’t display the ‘Add these Contacts to Group’ button |
| 50 | $this->_add2groupSupported = FALSE; |
| 51 | |
| 52 | $dsn = defined('CIVICRM_LOGGING_DSN') ? DB::parseDSN(CIVICRM_LOGGING_DSN) : DB::parseDSN(CIVICRM_DSN); |
| 53 | $this->db = $dsn['database']; |
| 54 | |
| 55 | $this->log_conn_id = CRM_Utils_Request::retrieve('log_conn_id', 'Integer', CRM_Core_DAO::$_nullObject); |
| 56 | $this->log_date = CRM_Utils_Request::retrieve('log_date', 'String', CRM_Core_DAO::$_nullObject); |
| 57 | $this->cid = CRM_Utils_Request::retrieve('cid', 'Integer', CRM_Core_DAO::$_nullObject); |
| 58 | $this->raw = CRM_Utils_Request::retrieve('raw', 'Boolean', CRM_Core_DAO::$_nullObject); |
| 59 | |
| 60 | parent::__construct(); |
| 61 | |
| 62 | CRM_Utils_System::resetBreadCrumb(); |
| 63 | $breadcrumb = |
| 64 | array( |
| 65 | array('title' => ts('Home'), |
| 66 | 'url' => CRM_Utils_System::url()), |
| 67 | array('title' => ts('CiviCRM'), |
| 68 | 'url' => CRM_Utils_System::url('civicrm', 'reset=1')), |
| 69 | array('title' => ts('View Contact'), |
| 70 | 'url' => CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$this->cid}")), |
| 71 | array('title' => ts('Search Results'), |
| 72 | 'url' => CRM_Utils_System::url('civicrm/contact/search', "force=1")), |
| 73 | ); |
| 74 | CRM_Utils_System::appendBreadCrumb($breadcrumb); |
| 75 | |
| 76 | if (CRM_Utils_Request::retrieve('revert', 'Boolean', CRM_Core_DAO::$_nullObject)) { |
| 77 | $reverter = new CRM_Logging_Reverter($this->log_conn_id, $this->log_date); |
| 78 | $reverter->revert($this->tables); |
| 79 | CRM_Core_Session::setStatus(ts('The changes have been reverted.'), ts('Reverted'), 'success'); |
| 80 | if ($this->cid) { |
| 81 | CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/view', "reset=1&selectedChild=log&cid={$this->cid}", FALSE, NULL, FALSE)); |
| 82 | } |
| 83 | else { |
| 84 | CRM_Utils_System::redirect(CRM_Report_Utils_Report::getNextUrl($this->summary, 'reset=1', FALSE, TRUE)); |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | // make sure the report works even without the params |
| 89 | if (!$this->log_conn_id or !$this->log_date) { |
| 90 | $dao = new CRM_Core_DAO; |
| 91 | $dao->query("SELECT log_conn_id, log_date FROM `{$this->db}`.log_{$this->tables[0]} WHERE log_action = 'Update' ORDER BY log_date DESC LIMIT 1"); |
| 92 | $dao->fetch(); |
| 93 | $this->log_conn_id = $dao->log_conn_id; |
| 94 | $this->log_date = $dao->log_date; |
| 95 | } |
| 96 | |
| 97 | $this->_columnHeaders = array( |
| 98 | 'field' => array('title' => ts('Field')), |
| 99 | 'from' => array('title' => ts('Changed From')), |
| 100 | 'to' => array('title' => ts('Changed To')), |
| 101 | ); |
| 102 | } |
| 103 | |
| 104 | function buildQuery($applyLimit = TRUE) {} |
| 105 | |
| 106 | function buildRows($sql, &$rows) { |
| 107 | // safeguard for when there aren’t any log entries yet |
| 108 | if (!$this->log_conn_id or !$this->log_date) { |
| 109 | return; |
| 110 | } |
| 111 | |
| 112 | if (empty($rows)) { |
| 113 | |
| 114 | $rows = array(); |
| 115 | |
| 116 | } |
| 117 | |
| 118 | foreach ($this->tables as $table) { |
| 119 | $rows = array_merge($rows, $this->diffsInTable($table)); |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | protected function diffsInTable($table) { |
| 124 | $rows = array(); |
| 125 | |
| 126 | $differ = new CRM_Logging_Differ($this->log_conn_id, $this->log_date, $this->interval); |
| 127 | $diffs = $differ->diffsInTable($table, $this->cid); |
| 128 | |
| 129 | // return early if nothing found |
| 130 | if (empty($diffs)) { |
| 131 | return $rows; |
| 132 | } |
| 133 | |
| 134 | list($titles, $values) = $differ->titlesAndValuesForTable($table); |
| 135 | |
| 136 | // populate $rows with only the differences between $changed and $original (skipping certain columns and NULL ↔ empty changes unless raw requested) |
| 137 | $skipped = array('contact_id', 'entity_id', 'id'); |
| 138 | foreach ($diffs as $diff) { |
| 139 | $field = $diff['field']; |
| 140 | $from = $diff['from']; |
| 141 | $to = $diff['to']; |
| 142 | |
| 143 | if ($this->raw) { |
| 144 | $field = "$table.$field"; |
| 145 | } |
| 146 | else { |
| 147 | if (in_array($field, $skipped)) { |
| 148 | continue; |
| 149 | } |
| 150 | // $differ filters out === values; for presentation hide changes like 42 → '42' |
| 151 | if ($from == $to) { |
| 152 | continue; |
| 153 | } |
| 154 | |
| 155 | // CRM-7251: special-case preferred_communication_method |
| 156 | if ($field == 'preferred_communication_method') { |
| 157 | $froms = array(); |
| 158 | $tos = array(); |
| 159 | foreach (explode(CRM_Core_DAO::VALUE_SEPARATOR, $from) as $val) $froms[] = CRM_Utils_Array::value($val, $values[$field]); |
| 160 | foreach (explode(CRM_Core_DAO::VALUE_SEPARATOR, $to) as $val) $tos[] = CRM_Utils_Array::value($val, $values[$field]); |
| 161 | $from = implode(', ', array_filter($froms)); |
| 162 | $to = implode(', ', array_filter($tos)); |
| 163 | } |
| 164 | |
| 165 | if (isset($values[$field][$from])) { |
| 166 | |
| 167 | $from = $values[$field][$from]; |
| 168 | |
| 169 | } |
| 170 | if (isset($values[$field][$to])) { |
| 171 | $to = $values[$field][$to]; |
| 172 | } |
| 173 | if (isset($titles[$field])) { |
| 174 | $field = $titles[$field]; |
| 175 | } |
| 176 | if ($diff['action'] == 'Insert') { |
| 177 | $from = ''; |
| 178 | } |
| 179 | if ($diff['action'] == 'Delete') { |
| 180 | $to = ''; |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | $rows[] = array('field' => $field . " (id: {$diff['id']})", 'from' => $from, 'to' => $to); |
| 185 | } |
| 186 | |
| 187 | return $rows; |
| 188 | } |
| 189 | |
| 190 | function buildQuickForm() { |
| 191 | parent::buildQuickForm(); |
| 192 | |
| 193 | $params = array( |
| 194 | 1 => array($this->log_conn_id, 'Integer'), |
| 195 | 2 => array($this->log_date, 'String'), |
| 196 | ); |
| 197 | |
| 198 | // let the template know who updated whom when |
| 199 | $dao = CRM_Core_DAO::executeQuery($this->whoWhomWhenSql(), $params); |
| 200 | if ($dao->fetch()) { |
| 201 | $this->assign('who_url', CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$dao->who_id}")); |
| 202 | $this->assign('whom_url', CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$dao->whom_id}")); |
| 203 | $this->assign('who_name', $dao->who_name); |
| 204 | $this->assign('whom_name', $dao->whom_name); |
| 205 | } |
| 206 | $this->assign('log_date', CRM_Utils_Date::mysqlToIso($this->log_date)); |
| 207 | |
| 208 | $q = "reset=1&log_conn_id={$this->log_conn_id}&log_date={$this->log_date}"; |
| 209 | $this->assign('revertURL', CRM_Report_Utils_Report::getNextUrl($this->detail, "$q&revert=1", FALSE, TRUE)); |
| 210 | $this->assign('revertConfirm', ts('Are you sure you want to revert all these changes?')); |
| 211 | } |
| 212 | |
| 213 | // redefine this accordingly in ancestors for buildQuickForm()’s sake |
| 214 | protected function whoWhomWhenSql() {} |
| 215 | } |
| 216 | |