‪TYPO3CMS  10.4
RecordHistory.php
Go to the documentation of this file.
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 
17 
27 
33 {
36 
40  private ‪$deprecatedPublicMethods = [
41  'getHistoryEntry' => 'Using RecordHistory::getHistoryEntry() is deprecated and will not be possible anymore in TYPO3 v11.0.',
42  'getHistoryData' => 'Using RecordHistory::getHistoryData() is deprecated and will not be possible anymore in TYPO3 v11.0.',
43  ];
44 
49  'changeLog' => 'Using changeLog is deprecated and will not be possible anymore in TYPO3 v11.0. Use getChangeLog() instead.',
50  'lastHistoryEntry' => 'Using lastHistoryEntry is deprecated and will not be possible anymore in TYPO3 v11.0. Use getLastHistoryEntryNumber() instead.',
51  ];
52 
58  protected ‪$maxSteps = 20;
59 
65  protected ‪$showSubElements = true;
66 
72  protected ‪$element;
73 
79  protected ‪$lastHistoryEntry = 0;
80 
84  protected ‪$changeLog = [];
85 
90  protected ‪$pageAccessCache = [];
91 
96  protected ‪$rollbackFields = '';
97 
104  public function ‪__construct(‪$element = '', ‪$rollbackFields = '')
105  {
106  $this->element = $this->‪sanitizeElementValue(‪$element);
107  $this->rollbackFields = $this->‪sanitizeRollbackFieldsValue(‪$rollbackFields);
108  }
109 
116  public function ‪setLastHistoryEntry(int $lastHistoryEntryNumber): void
117  {
118  $this->‪setLastHistoryEntryNumber($lastHistoryEntryNumber);
119  }
120 
126  public function ‪setLastHistoryEntryNumber(int ‪$lastHistoryEntry): void
127  {
128  $this->lastHistoryEntry = ‪$lastHistoryEntry;
129  $this->‪updateCurrentElement();
130  }
131 
132  public function ‪getLastHistoryEntryNumber(): int
133  {
135  }
136 
143  public function ‪setMaxSteps(int ‪$maxSteps): void
144  {
145  $this->maxSteps = ‪$maxSteps;
146  }
147 
154  public function ‪setShowSubElements(bool ‪$showSubElements): void
155  {
156  $this->showSubElements = ‪$showSubElements;
157  }
158 
163  public function ‪createChangeLog(): void
164  {
165  $this->changeLog = $this->‪getChangeLog();
166  }
167 
173  public function ‪getChangeLog(): array
174  {
175  if (!empty($this->element)) {
176  [$table, $recordUid] = explode(':', $this->element);
177  return $this->‪getHistoryData($table, (int)$recordUid, $this->showSubElements, $this->lastHistoryEntry);
178  }
179  return [];
180  }
181 
187  public function ‪shouldPerformRollback(): bool
188  {
189  return !empty($this->rollbackFields);
190  }
191 
198  public function ‪getElementData()
199  {
200  return !empty($this->element) ? explode(':', $this->element) : false;
201  }
202 
207  public function ‪getElementInformation(): array
208  {
209  return !empty($this->element) ? explode(':', $this->element) : [];
210  }
211 
215  public function ‪getElementString(): string
216  {
217  return (string)‪$this->element;
218  }
219 
224  public function ‪performRollback(): void
225  {
226  if (!$this->‪shouldPerformRollback()) {
227  return;
228  }
229  GeneralUtility::makeInstance(RecordHistoryRollback::class)
230  ->performRollback($this->rollbackFields, $this->‪getDiff($this->‪getChangeLog()));
231  $this->‪legacyUpdates();
232  }
233 
234  /*******************************
235  *
236  * build up history
237  *
238  *******************************/
239 
246  public function ‪createMultipleDiff(): array
247  {
248  return $this->‪getDiff($this->changeLog);
249  }
250 
257  public function ‪getDiff(array ‪$changeLog): array
258  {
259  $insertsDeletes = [];
260  $newArr = [];
261  $differences = [];
262  // traverse changelog array
263  foreach (‪$changeLog as $value) {
264  $field = $value['tablename'] . ':' . $value['recuid'];
265  // inserts / deletes
266  if ((int)$value['actiontype'] !== ‪RecordHistoryStore::ACTION_MODIFY) {
267  if (!$insertsDeletes[$field]) {
268  $insertsDeletes[$field] = 0;
269  }
270  $value['action'] === 'insert' ? $insertsDeletes[$field]++ : $insertsDeletes[$field]--;
271  // unset not needed fields
272  if ($insertsDeletes[$field] === 0) {
273  unset($insertsDeletes[$field]);
274  }
275  } elseif (!isset($newArr[$field])) {
276  $newArr[$field] = $value['newRecord'];
277  $differences[$field] = $value['oldRecord'];
278  } else {
279  $differences[$field] = array_merge($differences[$field], $value['oldRecord']);
280  }
281  }
282  // remove entries where there were no changes effectively
283  foreach ($newArr as $record => $value) {
284  foreach ($value as $key => $innerVal) {
285  if ($newArr[$record][$key] === $differences[$record][$key]) {
286  unset($newArr[$record][$key], $differences[$record][$key]);
287  }
288  }
289  if (empty($newArr[$record]) && empty($differences[$record])) {
290  unset($newArr[$record], $differences[$record]);
291  }
292  }
293  return [
294  'newData' => $newArr,
295  'oldData' => $differences,
296  'insertsDeletes' => $insertsDeletes
297  ];
298  }
299 
309  protected function ‪getHistoryData(string $table, int $uid, bool $includeSubEntries = null, int ‪$lastHistoryEntry = null): array
310  {
311  $historyDataForRecord = $this->‪getHistoryDataForRecord($table, $uid, ‪$lastHistoryEntry);
312  // get history of tables of this page and merge it into changelog
313  if ($table === 'pages' && $includeSubEntries && $this->‪hasPageAccess('pages', $uid)) {
314  foreach (‪$GLOBALS['TCA'] as $tablename => $value) {
315  // check if there are records on the page
316  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($tablename);
317  $queryBuilder->getRestrictions()->removeAll();
318 
319  $rows = $queryBuilder
320  ->select('uid')
321  ->from($tablename)
322  ->where(
323  $queryBuilder->expr()->eq(
324  'pid',
325  $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
326  )
327  )
328  ->execute();
329  $rowCount = (int)$queryBuilder->count('uid')->execute()->fetchColumn(0);
330  if ($rowCount === 0) {
331  continue;
332  }
333  foreach ($rows as $row) {
334  // if there is history data available, merge it into changelog
335  $newChangeLog = $this->‪getHistoryDataForRecord($tablename, $row['uid'], ‪$lastHistoryEntry);
336  if (is_array($newChangeLog) && !empty($newChangeLog)) {
337  foreach ($newChangeLog as $key => $newChangeLogEntry) {
338  $historyDataForRecord[$key] = $newChangeLogEntry;
339  }
340  }
341  }
342  }
343  }
344  usort($historyDataForRecord, static function (array $a, array $b): int {
345  if ($a['tstamp'] < $b['tstamp']) {
346  return 1;
347  }
348  if ($a['tstamp'] > $b['tstamp']) {
349  return -1;
350  }
351  return 0;
352  });
353  return $historyDataForRecord;
354  }
355 
365  public function ‪getHistoryDataForRecord(string $table, int $uid, int ‪$lastHistoryEntry = null): array
366  {
367  if (empty(‪$GLOBALS['TCA'][$table]) || !$this->‪hasTableAccess($table) || !$this->‪hasPageAccess($table, $uid)) {
368  return [];
369  }
370 
371  $uid = $this->‪resolveElement($table, $uid);
372  return $this->‪findEventsForRecord($table, $uid, ($this->maxSteps ?: 0), ‪$lastHistoryEntry);
373  }
374 
375  /*******************************
376  *
377  * Various helper functions
378  *
379  *******************************/
380 
388  protected function ‪resolveElement(string $table, int $uid): int
389  {
390  if (isset(‪$GLOBALS['TCA'][$table])
391  && $workspaceVersion = ‪BackendUtility::getWorkspaceVersionOfRecord($this->‪getBackendUser()->workspace, $table, $uid, 'uid')) {
392  $uid = $workspaceVersion['uid'];
393  }
394  return $uid;
395  }
396 
403  protected function ‪getHistoryEntry(int ‪$lastHistoryEntry): array
404  {
405  $queryBuilder = $this->‪getQueryBuilder();
406  $record = $queryBuilder
407  ->select('uid', 'tablename', 'recuid')
408  ->from('sys_history')
409  ->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter(‪$lastHistoryEntry, \PDO::PARAM_INT)))
410  ->execute()
411  ->fetch();
412 
413  if (empty($record)) {
414  return [];
415  }
416 
417  return $record;
418  }
419 
430  public function ‪findEventsForRecord(string $table, int $uid, int $limit = 0, int $minimumUid = null): array
431  {
432  $queryBuilder = $this->‪getQueryBuilder();
433  $queryBuilder
434  ->select('*')
435  ->from('sys_history')
436  ->where(
437  $queryBuilder->expr()->eq('tablename', $queryBuilder->createNamedParameter($table, \PDO::PARAM_STR)),
438  $queryBuilder->expr()->eq('recuid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT))
439  );
440 
441  if ($limit) {
442  $queryBuilder->setMaxResults($limit);
443  }
444 
445  if ($minimumUid) {
446  $queryBuilder->andWhere($queryBuilder->expr()->gte('uid', $queryBuilder->createNamedParameter($minimumUid, \PDO::PARAM_INT)));
447  }
448 
449  return $this->‪prepareEventDataFromQueryBuilder($queryBuilder);
450  }
451 
452  public function ‪findEventsForCorrelation(string $correlationId): array
453  {
454  $queryBuilder = $this->‪getQueryBuilder();
455  $queryBuilder
456  ->select('*')
457  ->from('sys_history')
458  ->where($queryBuilder->expr()->eq('correlation_id', $queryBuilder->createNamedParameter($correlationId, \PDO::PARAM_STR)));
459 
460  return $this->‪prepareEventDataFromQueryBuilder($queryBuilder);
461  }
462 
463  protected function ‪prepareEventDataFromQueryBuilder(‪QueryBuilder $queryBuilder): array
464  {
465  $events = [];
466  $result = $queryBuilder->‪orderBy('tstamp', 'DESC')->‪execute();
467  while ($row = $result->fetch()) {
468  $identifier = (int)$row['uid'];
469  $actionType = (int)$row['actiontype'];
470  if ($actionType === ‪RecordHistoryStore::ACTION_ADD || $actionType === ‪RecordHistoryStore::ACTION_UNDELETE) {
471  $row['action'] = 'insert';
472  }
473  if ($actionType === ‪RecordHistoryStore::ACTION_DELETE) {
474  $row['action'] = 'delete';
475  }
476  if (strpos($row['history_data'], 'a') === 0) {
477  // legacy code
478  $row['history_data'] = unserialize($row['history_data'], ['allowed_classes' => false]);
479  } else {
480  $row['history_data'] = json_decode($row['history_data'], true);
481  }
482  if (isset($row['history_data']['newRecord'])) {
483  $row['newRecord'] = $row['history_data']['newRecord'];
484  }
485  if (isset($row['history_data']['oldRecord'])) {
486  $row['oldRecord'] = $row['history_data']['oldRecord'];
487  }
488  $events[$identifier] = $row;
489  }
490  krsort($events);
491  return $events;
492  }
493 
501  protected function ‪hasPageAccess($table, $uid): bool
502  {
503  $pageRecord = null;
504  $uid = (int)$uid;
505 
506  if ($table === 'pages') {
507  $pageId = $uid;
508  } else {
509  $record = ‪BackendUtility::getRecord($table, $uid, '*', '', false);
510  $pageId = $record['pid'];
511  }
512 
513  if ($pageId === 0 && ‪$GLOBALS['TCA'][$table]['ctrl']['security']['ignoreRootLevelRestriction'] ?? false) {
514  return true;
515  }
516 
517  if (!isset($this->pageAccessCache[$pageId])) {
518  $isDeletedPage = false;
519  if (isset(‪$GLOBALS['TCA']['pages']['ctrl']['delete'])) {
520  $deletedField = ‪$GLOBALS['TCA']['pages']['ctrl']['delete'];
521  ‪$fields = 'pid,' . $deletedField;
522  $pageRecord = ‪BackendUtility::getRecord('pages', $pageId, ‪$fields, '', false);
523  $isDeletedPage = (bool)$pageRecord[$deletedField];
524  }
525  if ($isDeletedPage) {
526  // The page is deleted, so we fake its uid to be the one of the parent page.
527  // By doing so, the following API will use this id to traverse the rootline
528  // and check whether it is in the users' web mounts.
529  // We check however if the user has (or better had) access to the deleted page itself.
530  // Since the only way we got here is by requesting the history of the parent page
531  // we can be sure this parent page actually exists.
532  $pageRecord['uid'] = $pageRecord['pid'];
533  $this->pageAccessCache[$pageId] = $this->‪getBackendUser()->doesUserHaveAccess($pageRecord, ‪Permission::PAGE_SHOW);
534  } else {
535  $this->pageAccessCache[$pageId] = ‪BackendUtility::readPageAccess(
536  $pageId,
537  $this->‪getBackendUser()->getPagePermsClause(‪Permission::PAGE_SHOW)
538  );
539  }
540  }
541 
542  return $this->pageAccessCache[$pageId] !== false;
543  }
544 
552  protected function ‪sanitizeElementValue($value): string
553  {
554  if ($value !== '' && !preg_match('#^[a-z\d_.]+:[\d]+$#i', $value)) {
555  return '';
556  }
557  return $value;
558  }
559 
566  protected function ‪sanitizeRollbackFieldsValue($value): string
567  {
568  if ($value !== '' && !preg_match('#^[a-z\d_.]+(:[\d]+(:[a-z\d_.]+)?)?$#i', $value)) {
569  return '';
570  }
571  return $value;
572  }
573 
580  protected function ‪hasTableAccess($table): bool
581  {
582  return $this->‪getBackendUser()->check('tables_select', $table);
583  }
584 
586  {
587  return ‪$GLOBALS['BE_USER'];
588  }
589 
590  protected function ‪getQueryBuilder(): ‪QueryBuilder
591  {
592  return GeneralUtility::makeInstance(ConnectionPool::class)
593  ->getQueryBuilderForTable('sys_history');
594  }
595 
596  protected function ‪updateCurrentElement(): void
597  {
598  if ($this->lastHistoryEntry) {
599  $elementData = $this->‪getHistoryEntry($this->lastHistoryEntry);
600  if (!empty($elementData) && empty($this->element)) {
601  $this->element = $elementData['tablename'] . ':' . $elementData['recuid'];
602  }
603  }
604  }
605 
610  public function ‪legacyUpdates(): void
611  {
612  $this->lastHistoryEntry = false;
613  $this->changeLog = $this->‪getChangeLog();
614  }
615 }
‪TYPO3\CMS\Backend\History\RecordHistory\getElementString
‪string getElementString()
Definition: RecordHistory.php:204
‪TYPO3\CMS\Backend\History\RecordHistory\getDiff
‪array getDiff(array $changeLog)
Definition: RecordHistory.php:246
‪TYPO3\CMS\Backend\History\RecordHistory\getChangeLog
‪getChangeLog()
Definition: RecordHistory.php:162
‪TYPO3\CMS\Backend\History\RecordHistory\getHistoryEntry
‪array getHistoryEntry(int $lastHistoryEntry)
Definition: RecordHistory.php:392
‪TYPO3\CMS\Backend\History\RecordHistory\$changeLog
‪array $changeLog
Definition: RecordHistory.php:75
‪TYPO3\CMS\Backend\History\RecordHistory\sanitizeRollbackFieldsValue
‪string sanitizeRollbackFieldsValue($value)
Definition: RecordHistory.php:555
‪TYPO3\CMS\Backend\History\RecordHistory\hasPageAccess
‪bool hasPageAccess($table, $uid)
Definition: RecordHistory.php:490
‪TYPO3\CMS\Backend\History\RecordHistory\$rollbackFields
‪string $rollbackFields
Definition: RecordHistory.php:85
‪TYPO3\CMS\Backend\History\RecordHistory\shouldPerformRollback
‪bool shouldPerformRollback()
Definition: RecordHistory.php:176
‪TYPO3\CMS\Backend\History\RecordHistory\setShowSubElements
‪setShowSubElements(bool $showSubElements)
Definition: RecordHistory.php:143
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\orderBy
‪QueryBuilder orderBy(string $fieldName, string $order=null)
Definition: QueryBuilder.php:841
‪TYPO3\CMS\Backend\History\RecordHistory\$deprecatedPublicProperties
‪string[] $deprecatedPublicProperties
Definition: RecordHistory.php:44
‪TYPO3\CMS\Core\DataHandling\History\RecordHistoryStore\ACTION_MODIFY
‪const ACTION_MODIFY
Definition: RecordHistoryStore.php:33
‪$fields
‪$fields
Definition: pages.php:5
‪TYPO3\CMS\Backend\History\RecordHistory\resolveElement
‪int resolveElement(string $table, int $uid)
Definition: RecordHistory.php:377
‪TYPO3\CMS\Backend\History\RecordHistory\getHistoryDataForRecord
‪array getHistoryDataForRecord(string $table, int $uid, int $lastHistoryEntry=null)
Definition: RecordHistory.php:354
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:24
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:52
‪TYPO3\CMS\Core\DataHandling\History\RecordHistoryStore
Definition: RecordHistoryStore.php:31
‪TYPO3\CMS\Backend\History\RecordHistory\$deprecatedPublicMethods
‪string[] $deprecatedPublicMethods
Definition: RecordHistory.php:37
‪TYPO3\CMS\Backend\History
‪TYPO3\CMS\Backend\History\RecordHistory\createMultipleDiff
‪array createMultipleDiff()
Definition: RecordHistory.php:235
‪TYPO3\CMS\Backend\History\RecordHistory\findEventsForRecord
‪array findEventsForRecord(string $table, int $uid, int $limit=0, int $minimumUid=null)
Definition: RecordHistory.php:419
‪TYPO3\CMS\Backend\History\RecordHistory\setLastHistoryEntry
‪setLastHistoryEntry(int $lastHistoryEntryNumber)
Definition: RecordHistory.php:105
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\execute
‪Statement Doctrine DBAL ForwardCompatibility Result Doctrine DBAL Driver ResultStatement int execute()
Definition: QueryBuilder.php:204
‪TYPO3\CMS\Backend\History\RecordHistory\setLastHistoryEntryNumber
‪setLastHistoryEntryNumber(int $lastHistoryEntry)
Definition: RecordHistory.php:115
‪TYPO3\CMS\Backend\History\RecordHistory
Definition: RecordHistory.php:33
‪TYPO3\CMS\Backend\History\RecordHistory\getElementData
‪array bool getElementData()
Definition: RecordHistory.php:187
‪TYPO3\CMS\Backend\History\RecordHistory\setMaxSteps
‪setMaxSteps(int $maxSteps)
Definition: RecordHistory.php:132
‪TYPO3\CMS\Backend\History\RecordHistory\$showSubElements
‪bool $showSubElements
Definition: RecordHistory.php:59
‪TYPO3\CMS\Backend\History\RecordHistory\createChangeLog
‪createChangeLog()
Definition: RecordHistory.php:152
‪TYPO3\CMS\Backend\History\RecordHistory\getElementInformation
‪array getElementInformation()
Definition: RecordHistory.php:196
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Backend\History\RecordHistory\$pageAccessCache
‪array $pageAccessCache
Definition: RecordHistory.php:80
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:33
‪TYPO3\CMS\Backend\History\RecordHistory\sanitizeElementValue
‪string sanitizeElementValue($value)
Definition: RecordHistory.php:541
‪TYPO3\CMS\Backend\History\RecordHistory\getQueryBuilder
‪getQueryBuilder()
Definition: RecordHistory.php:579
‪TYPO3\CMS\Core\Compatibility\PublicMethodDeprecationTrait
Definition: PublicMethodDeprecationTrait.php:70
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:75
‪TYPO3\CMS\Backend\Utility\BackendUtility\getWorkspaceVersionOfRecord
‪static array bool getWorkspaceVersionOfRecord($workspace, $table, $uid, $fields=' *')
Definition: BackendUtility.php:3705
‪TYPO3\CMS\Backend\History\RecordHistory\performRollback
‪performRollback()
Definition: RecordHistory.php:213
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:95
‪TYPO3\CMS\Backend\History\RecordHistory\getHistoryData
‪array getHistoryData(string $table, int $uid, bool $includeSubEntries=null, int $lastHistoryEntry=null)
Definition: RecordHistory.php:298
‪TYPO3\CMS\Backend\Utility\BackendUtility\readPageAccess
‪static array false readPageAccess($id, $perms_clause)
Definition: BackendUtility.php:597
‪TYPO3\CMS\Backend\History\RecordHistory\legacyUpdates
‪legacyUpdates()
Definition: RecordHistory.php:599
‪TYPO3\CMS\Backend\History\RecordHistory\hasTableAccess
‪bool hasTableAccess($table)
Definition: RecordHistory.php:569
‪TYPO3\CMS\Core\DataHandling\History\RecordHistoryStore\ACTION_DELETE
‪const ACTION_DELETE
Definition: RecordHistoryStore.php:35
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Backend\History\RecordHistory\getBackendUser
‪getBackendUser()
Definition: RecordHistory.php:574
‪TYPO3\CMS\Backend\History\RecordHistory\getLastHistoryEntryNumber
‪getLastHistoryEntryNumber()
Definition: RecordHistory.php:121
‪TYPO3\CMS\Backend\History\RecordHistory\$element
‪string $element
Definition: RecordHistory.php:65
‪TYPO3\CMS\Core\DataHandling\History\RecordHistoryStore\ACTION_ADD
‪const ACTION_ADD
Definition: RecordHistoryStore.php:32
‪TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait
Definition: PublicPropertyDeprecationTrait.php:68
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Backend\History\RecordHistory\$lastHistoryEntry
‪int $lastHistoryEntry
Definition: RecordHistory.php:71
‪TYPO3\CMS\Core\DataHandling\History\RecordHistoryStore\ACTION_UNDELETE
‪const ACTION_UNDELETE
Definition: RecordHistoryStore.php:36
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Backend\History\RecordHistory\__construct
‪__construct($element='', $rollbackFields='')
Definition: RecordHistory.php:93
‪TYPO3\CMS\Backend\History\RecordHistory\$maxSteps
‪int $maxSteps
Definition: RecordHistory.php:53
‪TYPO3\CMS\Backend\History\RecordHistory\findEventsForCorrelation
‪findEventsForCorrelation(string $correlationId)
Definition: RecordHistory.php:441
‪TYPO3\CMS\Backend\History\RecordHistory\prepareEventDataFromQueryBuilder
‪prepareEventDataFromQueryBuilder(QueryBuilder $queryBuilder)
Definition: RecordHistory.php:452
‪TYPO3\CMS\Backend\History\RecordHistory\updateCurrentElement
‪updateCurrentElement()
Definition: RecordHistory.php:585