3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2014
35 class CRM_Logging_ReportDetail
extends CRM_Report_Form
{
38 protected $log_conn_id;
41 protected $tables = array();
42 protected $interval = '10 SECOND';
44 protected $altered_name;
45 protected $altered_by;
46 protected $altered_by_id;
48 // detail/summary report ids
54 public function __construct() {
55 // don’t display the ‘Add these Contacts to Group’ button
56 $this->_add2groupSupported
= FALSE;
58 $dsn = defined('CIVICRM_LOGGING_DSN') ? DB
::parseDSN(CIVICRM_LOGGING_DSN
) : DB
::parseDSN(CIVICRM_DSN
);
59 $this->db
= $dsn['database'];
61 $this->log_conn_id
= CRM_Utils_Request
::retrieve('log_conn_id', 'Integer', CRM_Core_DAO
::$_nullObject);
62 $this->log_date
= CRM_Utils_Request
::retrieve('log_date', 'String', CRM_Core_DAO
::$_nullObject);
63 $this->cid
= CRM_Utils_Request
::retrieve('cid', 'Integer', CRM_Core_DAO
::$_nullObject);
64 $this->raw
= CRM_Utils_Request
::retrieve('raw', 'Boolean', CRM_Core_DAO
::$_nullObject);
66 $this->altered_name
= CRM_Utils_Request
::retrieve('alteredName', 'String', CRM_Core_DAO
::$_nullObject);
67 $this->altered_by
= CRM_Utils_Request
::retrieve('alteredBy', 'String', CRM_Core_DAO
::$_nullObject);
68 $this->altered_by_id
= CRM_Utils_Request
::retrieve('alteredById', 'Integer', CRM_Core_DAO
::$_nullObject);
70 parent
::__construct();
72 CRM_Utils_System
::resetBreadCrumb();
75 array('title' => ts('Home'),
76 'url' => CRM_Utils_System
::url()),
77 array('title' => ts('CiviCRM'),
78 'url' => CRM_Utils_System
::url('civicrm', 'reset=1')),
79 array('title' => ts('View Contact'),
80 'url' => CRM_Utils_System
::url('civicrm/contact/view', "reset=1&cid={$this->cid}")),
81 array('title' => ts('Search Results'),
82 'url' => CRM_Utils_System
::url('civicrm/contact/search', "force=1")),
84 CRM_Utils_System
::appendBreadCrumb($breadcrumb);
86 if (CRM_Utils_Request
::retrieve('revert', 'Boolean', CRM_Core_DAO
::$_nullObject)) {
87 $reverter = new CRM_Logging_Reverter($this->log_conn_id
, $this->log_date
);
88 $reverter->revert($this->tables
);
89 CRM_Core_Session
::setStatus(ts('The changes have been reverted.'), ts('Reverted'), 'success');
91 CRM_Utils_System
::redirect(CRM_Utils_System
::url('civicrm/contact/view', "reset=1&selectedChild=log&cid={$this->cid}", FALSE, NULL, FALSE));
94 CRM_Utils_System
::redirect(CRM_Report_Utils_Report
::getNextUrl($this->summary
, 'reset=1', FALSE, TRUE));
98 // make sure the report works even without the params
99 if (!$this->log_conn_id
or !$this->log_date
) {
100 $dao = new CRM_Core_DAO
;
101 $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");
103 $this->log_conn_id
= $dao->log_conn_id
;
104 $this->log_date
= $dao->log_date
;
107 $this->_columnHeaders
= array(
108 'field' => array('title' => ts('Field')),
109 'from' => array('title' => ts('Changed From')),
110 'to' => array('title' => ts('Changed To')),
115 * @param bool $applyLimit
117 public function buildQuery($applyLimit = TRUE) {}
123 public function buildRows($sql, &$rows) {
124 // safeguard for when there aren’t any log entries yet
125 if (!$this->log_conn_id
or !$this->log_date
) {
135 foreach ($this->tables
as $table) {
136 $rows = array_merge($rows, $this->diffsInTable($table));
145 protected function diffsInTable($table) {
148 $differ = new CRM_Logging_Differ($this->log_conn_id
, $this->log_date
, $this->interval
);
149 $diffs = $differ->diffsInTable($table, $this->cid
);
151 // return early if nothing found
156 list($titles, $values) = $differ->titlesAndValuesForTable($table);
158 // populate $rows with only the differences between $changed and $original (skipping certain columns and NULL ↔ empty changes unless raw requested)
159 $skipped = array('contact_id', 'entity_id', 'id');
160 foreach ($diffs as $diff) {
161 $field = $diff['field'];
162 $from = $diff['from'];
166 $field = "$table.$field";
169 if (in_array($field, $skipped)) {
172 // $differ filters out === values; for presentation hide changes like 42 → '42'
177 // special-case for multiple values. Also works for CRM-7251: preferred_communication_method
178 if ((substr($from, 0, 1) == CRM_Core_DAO
::VALUE_SEPARATOR
&&
179 substr($from, -1, 1) == CRM_Core_DAO
::VALUE_SEPARATOR
) ||
180 (substr($to, 0, 1) == CRM_Core_DAO
::VALUE_SEPARATOR
&&
181 substr($to, -1, 1) == CRM_Core_DAO
::VALUE_SEPARATOR
)) {
182 $froms = $tos = array();
183 foreach (explode(CRM_Core_DAO
::VALUE_SEPARATOR
, trim($from, CRM_Core_DAO
::VALUE_SEPARATOR
)) as $val) {
184 $froms[] = CRM_Utils_Array
::value($val, $values[$field]);
186 foreach (explode(CRM_Core_DAO
::VALUE_SEPARATOR
, trim($to, CRM_Core_DAO
::VALUE_SEPARATOR
)) as $val) {
187 $tos[] = CRM_Utils_Array
::value($val, $values[$field]);
189 $from = implode(', ', array_filter($froms));
190 $to = implode(', ', array_filter($tos));
193 if (isset($values[$field][$from])) {
194 $from = $values[$field][$from];
196 if (isset($values[$field][$to])) {
197 $to = $values[$field][$to];
199 if (isset($titles[$field])) {
200 $field = $titles[$field];
202 if ($diff['action'] == 'Insert') {
205 if ($diff['action'] == 'Delete') {
210 $rows[] = array('field' => $field . " (id: {$diff['id']})", 'from' => $from, 'to' => $to);
216 public function buildQuickForm() {
217 parent
::buildQuickForm();
220 1 => array($this->log_conn_id
, 'Integer'),
221 2 => array($this->log_date
, 'String'),
224 $this->assign('whom_url', CRM_Utils_System
::url('civicrm/contact/view', "reset=1&cid={$this->cid}"));
225 $this->assign('who_url', CRM_Utils_System
::url('civicrm/contact/view', "reset=1&cid={$this->altered_by_id}"));
226 $this->assign('whom_name', $this->altered_name
);
227 $this->assign('who_name', $this->altered_by
);
229 $this->assign('log_date', CRM_Utils_Date
::mysqlToIso($this->log_date
));
231 $q = "reset=1&log_conn_id={$this->log_conn_id}&log_date={$this->log_date}";
232 $this->assign('revertURL', CRM_Report_Utils_Report
::getNextUrl($this->detail
, "$q&revert=1", FALSE, TRUE));
233 $this->assign('revertConfirm', ts('Are you sure you want to revert all these changes?'));