drupal-civicrm/sites/all/modules/civicrm/CRM/Logging/ReportDetail.php

366 lines
11 KiB
PHP
Raw Permalink Normal View History

2018-01-14 15:10:16 +02:00
<?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');
}
}