drupal-civicrm/sites/all/modules/civicrm/CRM/Logging/ReportDetail.php
2018-01-14 13:10:16 +00:00

366 lines
11 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Logging_ReportDetail extends CRM_Report_Form {
protected $cid;
/**
* Other contact ID.
*
* This would be set if we are viewing a merge of 2 contacts.
*
* @var int
*/
protected $oid;
protected $db;
protected $log_conn_id;
protected $log_date;
protected $raw;
protected $tables = array();
protected $interval = '10 SECOND';
protected $altered_name;
protected $altered_by;
protected $altered_by_id;
// detail/summary report ids
protected $detail;
protected $summary;
/**
* Instance of Differ.
*
* @var CRM_Logging_Differ
*/
protected $differ;
/**
* Array of changes made.
*
* @var array
*/
protected $diffs = array();
/**
* Don't display the Add these contacts to Group button.
*
* @var bool
*/
protected $_add2groupSupported = FALSE;
/**
* Class constructor.
*/
public function __construct() {
$this->storeDB();
$this->parsePropertiesFromUrl();
parent::__construct();
CRM_Utils_System::resetBreadCrumb();
$breadcrumb = array(
array(
'title' => ts('Home'),
'url' => CRM_Utils_System::url(),
),
array(
'title' => ts('CiviCRM'),
'url' => CRM_Utils_System::url('civicrm', 'reset=1'),
),
array(
'title' => ts('View Contact'),
'url' => CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$this->cid}"),
),
array(
'title' => ts('Search Results'),
'url' => CRM_Utils_System::url('civicrm/contact/search', "force=1"),
),
);
CRM_Utils_System::appendBreadCrumb($breadcrumb);
if (CRM_Utils_Request::retrieve('revert', 'Boolean')) {
$this->revert();
}
$this->_columnHeaders = array(
'field' => array('title' => ts('Field')),
'from' => array('title' => ts('Changed From')),
'to' => array('title' => ts('Changed To')),
);
}
/**
* Build query for report.
*
* We override this to be empty & calculate the rows in the buildRows function.
*
* @param bool $applyLimit
*/
public function buildQuery($applyLimit = TRUE) {
}
/**
* Build rows from query.
*
* @param string $sql
* @param array $rows
*/
public function buildRows($sql, &$rows) {
// safeguard for when there arent any log entries yet
if (!$this->log_conn_id && !$this->log_date) {
return;
}
$this->getDiffs();
$rows = $this->convertDiffsToRows();
}
/**
* Get the diffs for the report, calculating them if not already done.
*
* Note that contact details report now uses a more comprehensive method but
* the contribution logging details report still uses this.
*
* @return array
*/
protected function getDiffs() {
if (empty($this->diffs)) {
foreach ($this->tables as $table) {
$this->diffs = array_merge($this->diffs, $this->diffsInTable($table));
}
}
return $this->diffs;
}
/**
* @param $table
*
* @return array
*/
protected function diffsInTable($table) {
$this->setDiffer();
return $this->differ->diffsInTable($table, $this->cid);
}
/**
* Convert the diffs to row format.
*
* @return array
*/
protected function convertDiffsToRows() {
// return early if nothing found
if (empty($this->diffs)) {
return array();
}
// populate $rows with only the differences between $changed and $original (skipping certain columns and NULL ↔ empty changes unless raw requested)
$skipped = array('id');
foreach ($this->diffs as $diff) {
$table = $diff['table'];
if (empty($metadata[$table])) {
list($metadata[$table]['titles'], $metadata[$table]['values']) = $this->differ->titlesAndValuesForTable($table, $diff['log_date']);
}
$values = CRM_Utils_Array::value('values', $metadata[$diff['table']], array());
$titles = $metadata[$diff['table']]['titles'];
$field = $diff['field'];
$from = $diff['from'];
$to = $diff['to'];
if ($this->raw) {
$field = "$table.$field";
}
else {
if (in_array($field, $skipped)) {
continue;
}
// $differ filters out === values; for presentation hide changes like 42 → '42'
if ($from == $to) {
continue;
}
// special-case for multiple values. Also works for CRM-7251: preferred_communication_method
if ((substr($from, 0, 1) == CRM_Core_DAO::VALUE_SEPARATOR &&
substr($from, -1, 1) == CRM_Core_DAO::VALUE_SEPARATOR) ||
(substr($to, 0, 1) == CRM_Core_DAO::VALUE_SEPARATOR &&
substr($to, -1, 1) == CRM_Core_DAO::VALUE_SEPARATOR)
) {
$froms = $tos = array();
foreach (explode(CRM_Core_DAO::VALUE_SEPARATOR, trim($from, CRM_Core_DAO::VALUE_SEPARATOR)) as $val) {
$froms[] = CRM_Utils_Array::value($val, $values[$field]);
}
foreach (explode(CRM_Core_DAO::VALUE_SEPARATOR, trim($to, CRM_Core_DAO::VALUE_SEPARATOR)) as $val) {
$tos[] = CRM_Utils_Array::value($val, $values[$field]);
}
$from = implode(', ', array_filter($froms));
$to = implode(', ', array_filter($tos));
}
if (isset($values[$field][$from])) {
$from = $values[$field][$from];
}
if (isset($values[$field][$to])) {
$to = $values[$field][$to];
}
if (isset($titles[$field])) {
$field = $titles[$field];
}
if ($diff['action'] == 'Insert') {
$from = '';
}
if ($diff['action'] == 'Delete') {
$to = '';
}
}
$rows[] = array('field' => $field . " (id: {$diff['id']})", 'from' => $from, 'to' => $to);
}
return $rows;
}
public function buildQuickForm() {
parent::buildQuickForm();
$this->assign('whom_url', CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$this->cid}"));
$this->assign('who_url', CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$this->altered_by_id}"));
$this->assign('whom_name', $this->altered_name);
$this->assign('who_name', $this->altered_by);
$this->assign('log_date', CRM_Utils_Date::mysqlToIso($this->log_date));
$q = "reset=1&log_conn_id={$this->log_conn_id}&log_date={$this->log_date}";
if ($this->oid) {
$q .= '&oid=' . $this->oid;
}
$this->assign('revertURL', CRM_Report_Utils_Report::getNextUrl($this->detail, "$q&revert=1", FALSE, TRUE));
$this->assign('revertConfirm', ts('Are you sure you want to revert all changes?'));
}
/**
* Store the dsn for the logging database in $this->db.
*/
protected function storeDB() {
$dsn = defined('CIVICRM_LOGGING_DSN') ? DB::parseDSN(CIVICRM_LOGGING_DSN) : DB::parseDSN(CIVICRM_DSN);
$this->db = $dsn['database'];
}
/**
* Calculate all the contact related diffs for the change.
*/
protected function calculateContactDiffs() {
$this->diffs = $this->getAllContactChangesForConnection();
}
/**
* Get an array of changes made in the mysql connection.
*
* @return mixed
*/
public function getAllContactChangesForConnection() {
if (empty($this->log_conn_id)) {
return array();
}
$this->setDiffer();
try {
return $this->differ->getAllChangesForConnection($this->tables);
}
catch (CRM_Core_Exception $e) {
CRM_Core_Error::statusBounce(ts($e->getMessage()));
}
}
/**
* Make sure the differ is defined.
*/
protected function setDiffer() {
if (empty($this->differ)) {
$this->differ = new CRM_Logging_Differ($this->log_conn_id, $this->log_date, $this->interval);
}
}
/**
* Set this tables to reflect tables changed in a merge.
*/
protected function setTablesToContactRelatedTables() {
$schema = new CRM_Logging_Schema();
$this->tables = $schema->getLogTablesForContact();
// allow tables to be extended by report hook query objects.
// This is a report specific hook. It's unclear how it interacts to / overlaps the main one.
// It probably precedes the main one and was never reconciled with it....
CRM_Report_BAO_Hook::singleton()->alterLogTables($this, $this->tables);
}
/**
* Revert the changes defined by the parameters.
*/
protected function revert() {
$reverter = new CRM_Logging_Reverter($this->log_conn_id, $this->log_date);
$reverter->calculateDiffsFromLogConnAndDate($this->tables);
$reverter->revert();
CRM_Core_Session::setStatus(ts('The changes have been reverted.'), ts('Reverted'), 'success');
if ($this->cid) {
if ($this->oid) {
CRM_Utils_System::redirect(CRM_Utils_System::url(
'civicrm/contact/merge',
"reset=1&cid={$this->cid}&oid={$this->oid}",
FALSE,
NULL,
FALSE)
);
}
else {
CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/view', "reset=1&selectedChild=log&cid={$this->cid}", FALSE, NULL, FALSE));
}
}
else {
CRM_Utils_System::redirect(CRM_Report_Utils_Report::getNextUrl($this->summary, 'reset=1', FALSE, TRUE));
}
}
/**
* Get the properties that might be in the URL.
*/
protected function parsePropertiesFromUrl() {
$this->log_conn_id = CRM_Utils_Request::retrieve('log_conn_id', 'String');
$this->log_date = CRM_Utils_Request::retrieve('log_date', 'String');
$this->cid = CRM_Utils_Request::retrieve('cid', 'Integer');
$this->raw = CRM_Utils_Request::retrieve('raw', 'Boolean');
$this->altered_name = CRM_Utils_Request::retrieve('alteredName', 'String');
$this->altered_by = CRM_Utils_Request::retrieve('alteredBy', 'String');
$this->altered_by_id = CRM_Utils_Request::retrieve('alteredById', 'Integer');
}
}