17 use Psr\Http\Message\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
79 $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
90 public function mainAction(ServerRequestInterface $request): ResponseInterface
92 $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation([]);
94 $parsedBody = $request->getParsedBody();
95 $queryParams = $request->getQueryParams();
96 $lastHistoryEntry = (int)($parsedBody[
'historyEntry'] ?? $queryParams[
'historyEntry'] ?? 0);
97 $rollbackFields = $parsedBody[
'rollbackFields'] ?? $queryParams[
'rollbackFields'] ??
null;
98 $element = $parsedBody[
'element'] ?? $queryParams[
'element'] ??
null;
100 $this->view->assign(
'currentSelection', $displaySettings);
102 $this->showDiff = (int)$displaySettings[
'showDiff'];
105 $this->historyObject = GeneralUtility::makeInstance(RecordHistory::class, $element, $rollbackFields);
106 $this->historyObject->setShowSubElements((
int)$displaySettings[
'showSubElements']);
107 $this->historyObject->setLastHistoryEntry($lastHistoryEntry);
108 if ($displaySettings[
'maxSteps']) {
109 $this->historyObject->setMaxSteps((
int)$displaySettings[
'maxSteps']);
114 $this->historyObject->createChangeLog();
115 if (!empty($this->historyObject->changeLog)) {
116 if ($this->historyObject->shouldPerformRollback()) {
117 $this->historyObject->performRollback();
118 } elseif ($lastHistoryEntry) {
119 $completeDiff = $this->historyObject->createMultipleDiff();
121 $this->view->assign(
'showDifferences',
true);
122 $this->view->assign(
'fullViewUrl', $this->
buildUrl([
'historyEntry' =>
'']));
124 if ($this->historyObject->getElementData()) {
130 $normalizedParams = $request->getAttribute(
'normalizedParams');
131 $elementData = $this->historyObject->getElementData();
136 if ($elementData[0] !==
'pages') {
137 $this->view->assign(
'singleElement',
true);
140 $this->view->assign(
'fullHistoryUrl', $this->
buildUrl([
141 'element' =>
'pages:' . $parentPage[
'pid'],
142 'historyEntry' =>
'',
143 'returnUrl' => $normalizedParams->getRequestUri(),
149 $this->view->assign(
'TYPO3_REQUEST_URI', $normalizedParams->getRequestUrl());
150 $this->view->assign(
'editLock', $this->editLock);
155 $this->moduleTemplate->setContent($this->view->render());
157 return new HtmlResponse($this->moduleTemplate->renderContent());
170 if ($table ===
'pages') {
174 $pageId = $record[
'pid'];
178 if (is_array($pageAccess)) {
179 $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($pageAccess);
188 protected function getButtons(ServerRequestInterface $request)
190 $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
192 $helpButton = $buttonBar->makeHelpButton()
193 ->setModuleName(
'xMOD_csh_corebe')
194 ->setFieldName(
'history_log');
195 $buttonBar->addButton($helpButton);
198 $parsedBody = $request->getParsedBody();
199 $queryParams = $request->getQueryParams();
200 $returnUrl = GeneralUtility::sanitizeLocalUrl($parsedBody[
'returnUrl'] ?? $queryParams[
'returnUrl'] ??
'');
203 $backButton = $buttonBar->makeLinkButton()
204 ->setHref($returnUrl)
205 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.closeDoc'))
206 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-view-go-back',
Icon::SIZE_SMALL));
220 $currentSelection = is_array($this->
getBackendUser()->uc[
'moduleData'][
'history'])
222 : [
'maxSteps' =>
'',
'showDiff' => 1,
'showSubElements' => 1];
223 $parsedBody = $request->getParsedBody();
224 $queryParams = $request->getQueryParams();
225 $currentSelectionOverride = $parsedBody[
'settings'] ?? $queryParams[
'settings'] ??
null;
227 if (is_array($currentSelectionOverride) && !empty($currentSelectionOverride)) {
228 $currentSelection = array_merge($currentSelection, $currentSelectionOverride);
229 $this->
getBackendUser()->uc[
'moduleData'][
'history'] = $currentSelection;
234 $selector[
'maxSteps'] = [
248 'value' =>
'maxSteps_all'
251 $selector[
'showDiff'] = [
253 'value' =>
'showDiff_no'
256 'value' =>
'showDiff_inline'
259 $selector[
'showSubElements'] = [
268 $scriptUrl = GeneralUtility::linkThisScript();
270 foreach ($selector as $key => $values) {
271 foreach ($values as $singleKey => $singleVal) {
272 $selector[$key][$singleKey][
'scriptUrl'] = htmlspecialchars(GeneralUtility::quoteJSvalue($scriptUrl .
'&settings[' . $key .
']=' . $singleKey));
275 $this->view->assign(
'settings', $selector);
276 return $currentSelection;
287 $arrayKeys = array_merge(array_keys($diff[
'newData']), array_keys($diff[
'insertsDeletes']), array_keys($diff[
'oldData']));
288 $arrayKeys = array_unique($arrayKeys);
289 if (!empty($arrayKeys)) {
291 foreach ($arrayKeys as $key) {
293 $elParts = explode(
':', $key);
295 if ((
int)$diff[
'insertsDeletes'][$key] === 1) {
297 $singleLine[
'insertDelete'] =
'delete';
298 } elseif ((
int)$diff[
'insertsDeletes'][$key] === -1) {
299 $singleLine[
'insertDelete'] =
'insert';
303 if ($diff[
'newData'][$key]) {
305 'newRecord' => $diff[
'oldData'][$key],
306 'oldRecord' => $diff[
'newData'][$key]
308 $singleLine[
'differences'] = $this->
renderDiff($tmpArr, $elParts[0], $elParts[1]);
310 $elParts = explode(
':', $key);
311 $singleLine[
'revertRecordUrl'] = $this->
buildUrl([
'rollbackFields' => $key]);
312 $singleLine[
'title'] = $this->
generateTitle($elParts[0], $elParts[1]);
313 $lines[] = $singleLine;
315 $this->view->assign(
'revertAllUrl', $this->
buildUrl([
'rollbackFields' =>
'ALL']));
316 $this->view->assign(
'multipleDiff', $lines);
327 if (empty($historyEntries)) {
335 foreach ($historyEntries as $entry) {
340 $singleLine[
'backendUserUid'] = $entry[
'userid'];
341 $singleLine[
'backendUserName'] = $entry[
'userid'] ? $beUserArray[$entry[
'userid']][
'username'] :
'';
343 if (!empty($entry[
'originaluserid'])) {
344 $singleLine[
'originalBackendUserName'] = $beUserArray[$entry[
'originaluserid']][
'username'];
348 $singleLine[
'diffUrl'] = $this->
buildUrl([
'historyEntry' => $entry[
'uid']]);
352 $singleLine[
'age'] =
BackendUtility::calcAge(
$GLOBALS[
'EXEC_TIME'] - $entry[
'tstamp'], $languageService->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.minutesHoursDaysYears'));
354 $singleLine[
'title'] = $this->
generateTitle($entry[
'tablename'], $entry[
'recuid']);
355 $singleLine[
'elementUrl'] = $this->
buildUrl([
'element' => $entry[
'tablename'] .
':' . $entry[
'recuid']]);
356 $singleLine[
'actiontype'] = $entry[
'actiontype'];
359 if (!$this->showDiff) {
362 $tmpFieldList = array_keys($entry[
'newRecord']);
363 foreach ($tmpFieldList as $key => $value) {
366 $tmpFieldList[$key] = $tmp;
369 unset($tmpFieldList[$key]);
372 $singleLine[
'fieldNames'] = implode(
',', $tmpFieldList);
375 $singleLine[
'differences'] = $this->
renderDiff($entry, $entry[
'tablename']);
379 $lines[] = $singleLine;
381 $this->view->assign(
'history', $lines);
392 protected function renderDiff($entry, $table, $rollbackUid = 0): array
395 if (is_array($entry[
'newRecord'])) {
397 $diffUtility = GeneralUtility::makeInstance(DiffUtility::class);
398 $diffUtility->stripTags =
false;
399 $fieldsToDisplay = array_keys($entry[
'newRecord']);
401 foreach ($fieldsToDisplay as $fN) {
402 if (is_array(
$GLOBALS[
'TCA'][$table][
'columns'][$fN]) &&
$GLOBALS[
'TCA'][$table][
'columns'][$fN][
'config'][
'type'] !==
'passthrough') {
404 $diffres = $diffUtility->makeDiffDisplay(
410 $rollbackUrl = $this->
buildUrl([
'rollbackFields' => $table .
':' . $rollbackUid .
':' . $fN]);
414 'rollbackUrl' => $rollbackUrl,
415 'result' => str_replace(
'\n', PHP_EOL, str_replace(
'\r\n',
'\n', $diffres))
429 protected function buildUrl($overrideParameters = []): string
433 if ($this->historyObject->getElementData()) {
434 $params[
'element'] = $this->historyObject->getElementString();
436 $params[
'historyEntry'] = $this->historyObject->lastHistoryEntry;
438 $params = array_merge($params, $overrideParameters);
442 $uriBuilder = GeneralUtility::makeInstance(\
TYPO3\CMS\Backend\Routing\UriBuilder::class);
443 return (
string)$uriBuilder->buildUriFromRoute(
'record_history', $params);
455 $title = $table .
':' . $uid;
456 if (!empty(
$GLOBALS[
'TCA'][$table][
'ctrl'][
'label'])) {
472 if (!isset($this->recordCache[$table][$uid])) {
475 return $this->recordCache[$table][$uid];
486 $view = GeneralUtility::makeInstance(StandaloneView::class);
534 if ($tableName !==
'pages') {
535 $pageId = $record[
'pid'];
539 return (
bool)$record[
'editlock'];