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