1<?php 2 3/* 4 * This file is part of the TYPO3 CMS project. 5 * 6 * It is free software; you can redistribute it and/or modify it under 7 * the terms of the GNU General Public License, either version 2 8 * of the License, or any later version. 9 * 10 * For the full copyright and license information, please read the 11 * LICENSE.txt file that was distributed with this source code. 12 * 13 * The TYPO3 project - inspiring people to share! 14 */ 15 16namespace TYPO3\CMS\Workspaces\Service; 17 18use TYPO3\CMS\Backend\Backend\Avatar\Avatar; 19use TYPO3\CMS\Backend\History\RecordHistory; 20use TYPO3\CMS\Backend\Utility\BackendUtility; 21use TYPO3\CMS\Core\Localization\LanguageService; 22use TYPO3\CMS\Core\SingletonInterface; 23use TYPO3\CMS\Core\Utility\DiffUtility; 24use TYPO3\CMS\Core\Utility\GeneralUtility; 25 26/** 27 * Service for history 28 */ 29class HistoryService implements SingletonInterface 30{ 31 /** 32 * @var array 33 */ 34 protected $backendUserNames; 35 36 /** 37 * @var array 38 */ 39 protected $historyEntries = []; 40 41 /** 42 * @var DiffUtility 43 */ 44 protected $differencesObject; 45 46 /** 47 * Creates this object. 48 */ 49 public function __construct() 50 { 51 $this->backendUserNames = BackendUtility::getUserNames(); 52 } 53 54 /** 55 * Gets the editing history of a record. 56 * 57 * @param string $table Name of the table 58 * @param int $id Uid of the record 59 * @return array Record history entries 60 */ 61 public function getHistory($table, $id) 62 { 63 $history = []; 64 $i = 0; 65 foreach ((array)$this->getHistoryEntries($table, $id) as $entry) { 66 if ($i++ > 20) { 67 break; 68 } 69 $history[] = $this->getHistoryEntry($entry); 70 } 71 return $history; 72 } 73 74 /** 75 * Gets the human readable representation of one 76 * record history entry. 77 * 78 * @param array $entry Record history entry 79 * @return array 80 * @see getHistory 81 */ 82 protected function getHistoryEntry(array $entry) 83 { 84 if (!empty($entry['action'])) { 85 $differences = $entry['action']; 86 } else { 87 $differences = $this->getDifferences($entry); 88 } 89 90 $avatar = GeneralUtility::makeInstance(Avatar::class); 91 $beUserRecord = BackendUtility::getRecord('be_users', $entry['userid']); 92 93 return [ 94 'datetime' => htmlspecialchars(BackendUtility::datetime($entry['tstamp'])), 95 'user' => htmlspecialchars($this->getUserName($entry['userid'])), 96 'user_avatar' => $avatar->render($beUserRecord), 97 'differences' => $differences 98 ]; 99 } 100 101 /** 102 * Gets the differences between two record versions out 103 * of one record history entry. 104 * 105 * @param array $entry Record history entry 106 * @return array 107 */ 108 protected function getDifferences(array $entry) 109 { 110 $differences = []; 111 $tableName = $entry['tablename']; 112 if (is_array($entry['newRecord'])) { 113 $fields = array_keys($entry['newRecord']); 114 foreach ($fields as $field) { 115 if (!empty($GLOBALS['TCA'][$tableName]['columns'][$field]['config']['type']) && $GLOBALS['TCA'][$tableName]['columns'][$field]['config']['type'] !== 'passthrough') { 116 // Create diff-result: 117 $fieldDifferences = $this->getDifferencesObject()->makeDiffDisplay( 118 BackendUtility::getProcessedValue($tableName, $field, $entry['oldRecord'][$field], 0, true), 119 BackendUtility::getProcessedValue($tableName, $field, $entry['newRecord'][$field], 0, true) 120 ); 121 if (!empty($fieldDifferences)) { 122 $differences[] = [ 123 'label' => $this->getLanguageService()->sL((string)BackendUtility::getItemLabel($tableName, $field)), 124 'html' => nl2br(trim($fieldDifferences)), 125 ]; 126 } 127 } 128 } 129 } 130 return $differences; 131 } 132 133 /** 134 * Gets the username of a backend user. 135 * 136 * @param string $user 137 * @return string 138 */ 139 protected function getUserName($user) 140 { 141 $userName = 'unknown'; 142 if (!empty($this->backendUserNames[$user]['username'])) { 143 $userName = $this->backendUserNames[$user]['username']; 144 } 145 return $userName; 146 } 147 148 /** 149 * Gets an instance of the record history of a record. 150 * 151 * @param string $table Name of the table 152 * @param int $id Uid of the record 153 * @return array 154 */ 155 protected function getHistoryEntries($table, $id) 156 { 157 if (!isset($this->historyEntries[$table][$id])) { 158 $this->historyEntries[$table][$id] = GeneralUtility::makeInstance(RecordHistory::class) 159 ->getHistoryDataForRecord($table, $id); 160 } 161 return $this->historyEntries[$table][$id]; 162 } 163 164 /** 165 * Gets an instance of the record differences utility. 166 * 167 * @return DiffUtility 168 */ 169 protected function getDifferencesObject() 170 { 171 if (!isset($this->differencesObject)) { 172 $this->differencesObject = GeneralUtility::makeInstance(DiffUtility::class); 173 $this->differencesObject->stripTags = false; 174 } 175 return $this->differencesObject; 176 } 177 178 /** 179 * @return LanguageService 180 */ 181 protected function getLanguageService() 182 { 183 return $GLOBALS['LANG']; 184 } 185} 186