107 $this->returnUrl = $this->
getArgument(
'returnUrl');
109 $this->rollbackFields = $this->
getArgument(
'rollbackFields');
125 $this->rollbackFields = $this->
getArgument(
'revert');
126 $this->showInsertDelete = 0;
127 $this->showSubElements = 0;
128 $element = explode(
':', $this->element);
129 $res =
$GLOBALS[
'TYPO3_DB']->exec_SELECTquery(
'*',
'sys_history',
'tablename=' .
$GLOBALS[
'TYPO3_DB']->fullQuoteStr(
$element[0],
'sys_history') .
' AND recuid=' . (
int)
$element[1],
'',
'uid DESC',
'1');
130 $record =
$GLOBALS[
'TYPO3_DB']->sql_fetch_assoc($res);
131 $this->lastSyslogId = $record[
'sys_log_uid'];
143 if ($this->rollbackFields) {
147 if ($this->lastSyslogId) {
151 if ($this->element) {
172 $res =
$GLOBALS[
'TYPO3_DB']->exec_SELECTquery(
'snapshot',
'sys_history',
'uid=' .
$uid);
173 $tmp =
$GLOBALS[
'TYPO3_DB']->sql_fetch_assoc($res);
174 $GLOBALS[
'TYPO3_DB']->exec_UPDATEquery(
'sys_history',
'uid=' .
$uid, array(
'snapshot' => !$tmp[
'snapshot']));
186 if (!$this->rollbackFields) {
189 $reloadPageFrame = 0;
190 $rollbackData = explode(
':', $this->rollbackFields);
193 $cmdmapArray = array();
194 if ($diff[
'insertsDeletes']) {
195 switch (count($rollbackData)) {
198 $data = $diff[
'insertsDeletes'];
202 if ($diff[
'insertsDeletes'][$this->rollbackFields]) {
203 $data[$this->rollbackFields] = $diff[
'insertsDeletes'][$this->rollbackFields];
211 foreach ($data as $key => $action) {
212 $elParts = explode(
':', $key);
215 $cmdmapArray[$elParts[0]][$elParts[1]][
'delete'] = 1;
217 unset($diff[
'oldData'][$key]);
218 unset($diff[
'newData'][$key]);
219 } elseif ($action == -1) {
221 $cmdmapArray[$elParts[0]][$elParts[1]][
'undelete'] = 1;
229 $tce->stripslashes_values = 0;
231 $tce->dontProcessTransformations = 1;
232 $tce->start(array(), $cmdmapArray);
233 $tce->process_cmdmap();
235 if (isset($cmdmapArray[
'pages'])) {
236 $reloadPageFrame = 1;
241 $diff_modified = array();
242 foreach ($diff[
'oldData'] as $key => $value) {
243 $splitKey = explode(
':', $key);
244 $diff_modified[$splitKey[0]][$splitKey[1]] = $value;
246 switch (count($rollbackData)) {
249 $data = $diff_modified;
253 $data[$rollbackData[0]][$rollbackData[1]] = $diff_modified[$rollbackData[0]][$rollbackData[1]];
257 $data[$rollbackData[0]][$rollbackData[1]][$rollbackData[2]] = $diff_modified[$rollbackData[0]][$rollbackData[1]][$rollbackData[2]];
264 $tce->stripslashes_values = 0;
266 $tce->dontProcessTransformations = 1;
267 $tce->start($data, array());
268 $tce->process_datamap();
270 if (isset($data[
'pages'])) {
271 $reloadPageFrame = 1;
274 $this->lastSyslogId = FALSE;
275 $this->rollbackFields = FALSE;
278 if ($reloadPageFrame) {
279 return '<script type="text/javascript"> 281 if (top.content && top.content.nav_frame && top.content.nav_frame.refresh_nav) { 282 top.content.nav_frame.refresh_nav(); 302 $currentSelection = is_array(
$GLOBALS[
'BE_USER']->uc[
'moduleData'][
'history']) ?
$GLOBALS[
'BE_USER']->uc[
'moduleData'][
'history'] : array(
'maxSteps' =>
'',
'showDiff' => 1,
'showSubElements' => 1,
'showInsertDelete' => 1);
303 $currentSelectionOverride = $this->
getArgument(
'settings');
304 if ($currentSelectionOverride) {
305 $currentSelection = array_merge($currentSelection, $currentSelectionOverride);
306 $GLOBALS[
'BE_USER']->uc[
'moduleData'][
'history'] = $currentSelection;
310 $selector[
'maxSteps'] = array(
315 '' =>
'maxSteps_all',
316 'marked' =>
'maxSteps_marked' 318 $selector[
'showDiff'] = array(
320 1 =>
'showDiff_inline' 322 $selector[
'showSubElements'] = array(
326 $selector[
'showInsertDelete'] = array(
332 foreach ($selector as $key => $values) {
333 $displayCode .=
'<tr><td>' .
$GLOBALS[
'LANG']->getLL($key, 1) .
'</td>';
334 $displayCode .=
'<td><select name="settings[' . $key .
']" onChange="document.settings.submit()" style="width:100px">';
335 foreach ($values as $singleKey => $singleVal) {
336 $caption =
$GLOBALS[
'LANG']->getLL($singleVal, 1) ?: $singleVal;
337 $displayCode .=
'<option value="' . $singleKey .
'"' . ($singleKey == $currentSelection[$key] ?
' selected="selected"' :
'') .
'> ' . $caption .
'</option>';
339 $displayCode .=
'</select></td></tr>';
342 if ($currentSelection[
'maxSteps'] !=
'marked') {
343 $this->maxSteps = $currentSelection[
'maxSteps'] ? (int)$currentSelection[
'maxSteps'] :
'';
345 $this->showMarked = TRUE;
346 $this->maxSteps = FALSE;
348 $this->showDiff = (int)$currentSelection[
'showDiff'];
349 $this->showSubElements = (int)$currentSelection[
'showSubElements'];
350 $this->showInsertDelete = (int)$currentSelection[
'showInsertDelete'];
353 $elParts = explode(
':', $this->element);
354 if (!empty($this->element) && $elParts[0] !=
'pages') {
355 $content .=
'<strong>' .
$GLOBALS[
'LANG']->getLL(
'elementHistory', 1) .
'</strong><br />';
356 $pid = $this->
getRecord($elParts[0], $elParts[1]);
359 $content .= $this->
linkPage(
$GLOBALS[
'LANG']->getLL(
'elementHistory_link', 1), array(
'element' =>
'pages:' . $pid[
'pid']));
362 $content .=
'<form name="settings" action="' . htmlspecialchars(
GeneralUtility::getIndpEnv(
'TYPO3_REQUEST_URL')) .
'" method="post"><table>' . $displayCode .
'</table></form>';
363 return $GLOBALS[
'SOBE']->doc->section(
$GLOBALS[
'LANG']->getLL(
'settings', 1), $content, FALSE, TRUE, FALSE, FALSE);
375 $lines[] =
'<thead><tr> 377 <th>' .
$GLOBALS[
'LANG']->getLL(
'time', 1) .
'</th> 378 <th>' .
$GLOBALS[
'LANG']->getLL(
'age', 1) .
'</th> 379 <th>' .
$GLOBALS[
'LANG']->getLL(
'user', 1) .
'</th> 380 <th>' .
$GLOBALS[
'LANG']->getLL(
'tableUid', 1) .
'</th> 381 <th>' .
$GLOBALS[
'LANG']->getLL(
'differences', 1) .
'</th> 386 if (!$this->changeLog) {
390 foreach ($this->changeLog as $sysLogUid => $entry) {
392 if ($i > $this->maxSteps && $this->maxSteps) {
396 if (!$entry[
'snapshot'] && $this->showMarked) {
401 $userName = $entry[
'user'] ? $be_user_array[$entry[
'user']][
'username'] :
$GLOBALS[
'LANG']->getLL(
'externalChange', 1);
403 $singleLine = array();
406 $singleLine[] =
'<span>' . $this->
linkPage($image, array(
'diff' => $sysLogUid)) .
'</span>';
412 $singleLine[] = htmlspecialchars($userName);
414 $singleLine[] = $this->
linkPage($this->
generateTitle($entry[
'tablename'], $entry[
'recuid']), array(
'element' => $entry[
'tablename'] .
':' . $entry[
'recuid']),
'',
$GLOBALS[
'LANG']->getLL(
'linkRecordHistory', 1));
417 if ($entry[
'action']) {
419 $singleLine[] =
'<strong>' . htmlspecialchars(
$GLOBALS[
'LANG']->getLL($entry[
'action'], 1)) .
'</strong>';
422 if (!$this->showDiff) {
424 $tmpFieldList = explode(
',', $entry[
'fieldlist']);
425 foreach ($tmpFieldList as $key => $value) {
428 $tmpFieldList[$key] = $tmp;
431 unset($tmpFieldList[$key]);
434 $singleLine[] = htmlspecialchars(implode(
',', $tmpFieldList));
437 $diff = $this->
renderDiff($entry, $entry[
'tablename']);
438 $singleLine[] = $diff;
442 if (!$entry[
'action']) {
443 if ($entry[
'snapshot']) {
448 $singleLine[] = $this->
linkPage($image, array(
'highlight' => $entry[
'uid']));
455 <td>' . implode(
'</td><td>', $singleLine) .
'</td> 463 <table class="t3-table" id="typo3-history"> 464 ' . implode(
'', $lines) .
' 466 if ($this->lastSyslogId) {
471 $theCode .=
'<br /><br />' . $flashMessage->render() .
'<br />';
473 return $GLOBALS[
'SOBE']->doc->section(
$GLOBALS[
'LANG']->getLL(
'changes'), $theCode, FALSE, TRUE);
486 $arrayKeys = array_merge(array_keys($diff[
'newData']), array_keys($diff[
'insertsDeletes']), array_keys($diff[
'oldData']));
487 $arrayKeys = array_unique($arrayKeys);
489 foreach ($arrayKeys as $key) {
491 $elParts = explode(
':', $key);
493 if ($diff[
'insertsDeletes'][$key] == 1) {
495 $record .=
'<strong>' .
$GLOBALS[
'LANG']->getLL(
'delete', 1) .
'</strong>';
497 } elseif ($diff[
'insertsDeletes'][$key] == -1) {
498 $record .=
'<strong>' .
$GLOBALS[
'LANG']->getLL(
'insert', 1) .
'</strong>';
503 if ($diff[
'newData'][$key]) {
504 $tmpArr[
'newRecord'] = $diff[
'oldData'][$key];
505 $tmpArr[
'oldRecord'] = $diff[
'newData'][$key];
506 $record .= $this->
renderDiff($tmpArr, $elParts[0], $elParts[1]);
508 $elParts = explode(
':', $key);
510 $record =
'<div style="margin-left:10px;padding-left:5px;border-left:1px solid black;border-bottom:1px dotted black;padding-bottom:2px;">' . $record .
'</div>';
511 $content .=
$GLOBALS[
'SOBE']->doc->section($titleLine, $record, FALSE, FALSE, FALSE, TRUE);
513 $content = $this->
createRollbackLink(
'ALL',
$GLOBALS[
'LANG']->getLL(
'revertAll', 1), 0) .
'<div style="margin-left:10px;padding-left:5px;border-left:1px solid black;border-bottom:1px dotted black;padding-bottom:2px;">' . $content .
'</div>';
515 $content =
$GLOBALS[
'LANG']->getLL(
'noDifferences', 1);
517 return $GLOBALS[
'SOBE']->doc->section(
$GLOBALS[
'LANG']->getLL(
'mergedDifferences', 1), $content, FALSE, TRUE, FALSE, TRUE);
530 public function renderDiff($entry, $table, $rollbackUid = 0) {
532 if (is_array($entry[
'newRecord'])) {
534 $fieldsToDisplay = array_keys($entry[
'newRecord']);
535 foreach ($fieldsToDisplay as $fN) {
536 if (is_array(
$GLOBALS[
'TCA'][$table][
'columns'][$fN]) &&
$GLOBALS[
'TCA'][$table][
'columns'][$fN][
'config'][
'type'] !=
'passthrough') {
538 $diffres = $t3lib_diff_Obj->makeDiffDisplay(BackendUtility::getProcessedValue($table, $fN, $entry[
'oldRecord'][$fN], 0, 1), BackendUtility::getProcessedValue($table, $fN, $entry[
'newRecord'][$fN], 0, 1));
540 <tr class="bgColor4"> 541 ' . ($rollbackUid ?
'<td style="width:33px">' . $this->
createRollbackLink(($table .
':' . $rollbackUid .
':' . $fN),
$GLOBALS[
'LANG']->getLL(
'revertField', 1), 2) .
'</td>' :
'') .
' 543 <td style="width:300px">' . nl2br($diffres) .
'</td> 549 $content =
'<table border="0" cellpadding="2" cellspacing="2" id="typo3-history-item"> 550 ' . implode(
'', $lines) .
' 570 $insertsDeletes = array();
572 $differences = array();
573 if (!$this->changeLog) {
577 foreach ($this->changeLog as $key => $value) {
578 $field = $value[
'tablename'] .
':' . $value[
'recuid'];
580 if ($value[
'action']) {
581 if (!$insertsDeletes[$field]) {
582 $insertsDeletes[$field] = 0;
584 if ($value[
'action'] ==
'insert') {
585 $insertsDeletes[$field]++;
587 $insertsDeletes[$field]--;
590 if ($insertsDeletes[$field] == 0) {
591 unset($insertsDeletes[$field]);
596 if (!isset($newArr[$field])) {
597 $newArr[$field] = $value[
'newRecord'];
598 $differences[$field] = $value[
'oldRecord'];
601 $differences[$field] = array_merge($differences[$field], $value[
'oldRecord']);
606 foreach ($newArr as $record => $value) {
607 foreach ($value as $key => $innerVal) {
608 if ($newArr[$record][$key] == $differences[$record][$key]) {
609 unset($newArr[$record][$key]);
610 unset($differences[$record][$key]);
613 if (empty($newArr[$record]) && empty($differences[$record])) {
614 unset($newArr[$record]);
615 unset($differences[$record]);
619 'newData' => $newArr,
620 'oldData' => $differences,
621 'insertsDeletes' => $insertsDeletes
632 $elParts = explode(
':', $this->element);
634 if (empty($this->element)) {
640 if ($elParts[0] ==
'pages' && $this->showSubElements && $this->
hasPageAccess(
'pages', $elParts[1])) {
641 foreach (
$GLOBALS[
'TCA'] as $tablename => $value) {
643 $res =
$GLOBALS[
'TYPO3_DB']->exec_SELECTquery(
'uid', $tablename,
'pid=' . (
int)$elParts[1]);
644 while ($row =
$GLOBALS[
'TYPO3_DB']->sql_fetch_assoc($res)) {
646 if ($newChangeLog = $this->
getHistoryData($tablename, $row[
'uid'])) {
647 foreach ($newChangeLog as $key => $value) {
675 $res =
$GLOBALS[
'TYPO3_DB']->exec_SELECTquery(
'sys_history.*, sys_log.userid',
'sys_history, sys_log',
'sys_history.sys_log_uid = sys_log.uid 676 AND sys_history.tablename = ' .
$GLOBALS[
'TYPO3_DB']->fullQuoteStr($table,
'sys_history') .
' 677 AND sys_history.recuid = ' . (
int)
$uid,
'',
'sys_log.uid DESC', $this->maxSteps);
680 while ($row =
$GLOBALS[
'TYPO3_DB']->sql_fetch_assoc($res)) {
682 if ($row[
'sys_log_uid'] < $this->lastSyslogId && $this->lastSyslogId) {
685 $hisDat = unserialize($row[
'history_data']);
686 if (is_array($hisDat[
'newRecord']) && is_array($hisDat[
'oldRecord'])) {
688 $hisDat[
'uid'] = $row[
'uid'];
689 $hisDat[
'tstamp'] = $row[
'tstamp'];
690 $hisDat[
'user'] = $row[
'userid'];
691 $hisDat[
'snapshot'] = $row[
'snapshot'];
692 $hisDat[
'fieldlist'] = $row[
'fieldlist'];
693 $hisDat[
'tablename'] = $row[
'tablename'];
694 $hisDat[
'recuid'] = $row[
'recuid'];
697 debug(
'ERROR: [getHistoryData]');
703 if ($this->showInsertDelete) {
705 $res =
$GLOBALS[
'TYPO3_DB']->exec_SELECTquery(
'uid, userid, action, tstamp',
'sys_log',
'type = 1 706 AND (action=1 OR action=3) 707 AND tablename = ' .
$GLOBALS[
'TYPO3_DB']->fullQuoteStr($table,
'sys_log') .
' 708 AND recuid = ' . (
int)$uid,
'',
'uid DESC', $this->maxSteps);
709 while ($row =
$GLOBALS[
'TYPO3_DB']->sql_fetch_assoc($res)) {
710 if ($row[
'uid'] < $this->lastSyslogId && $this->lastSyslogId) {
714 switch ($row[
'action']) {
717 $hisDat[
'action'] =
'insert';
721 $hisDat[
'action'] =
'delete';
724 $hisDat[
'tstamp'] = $row[
'tstamp'];
725 $hisDat[
'user'] = $row[
'userid'];
726 $hisDat[
'tablename'] = $table;
727 $hisDat[
'recuid'] =
$uid;
751 $out = $table .
':' .
$uid;
752 if ($labelField =
$GLOBALS[
'TCA'][$table][
'ctrl'][
'label']) {
769 return $this->
linkPage(
'<img ' .
IconUtility::skinImg(
'', (
'gfx/revert_' . $type .
'.gif'),
'width="33" height="33"') .
' alt="' . $alt .
'" title="' . $alt .
'" align="middle" />', array(
'rollbackFields' => $key));
783 public function linkPage($str, $inparams = array(), $anchor =
'', $title =
'') {
789 $params = array_merge($params, $inparams);
792 return '<a href="' . htmlspecialchars($link) .
'"' . ($title ?
' title="' . $title .
'"' :
'') .
'>' . $str .
'</a>';
806 foreach (
$GLOBALS[
'TCA'][$table][
'columns'] as $field => $config) {
807 if ($config[
'config'][
'type'] ==
'group' && $config[
'config'][
'internal_type'] ==
'file') {
808 unset($dataArray[$field]);
824 if (isset(
$GLOBALS[
'TCA'][$table])) {
826 $uid = $workspaceVersion[
'uid'];
841 $res =
$GLOBALS[
'TYPO3_DB']->exec_SELECTquery(
'*',
'sys_history',
'uid=' . (
int)$sh_uid);
842 $record =
$GLOBALS[
'TYPO3_DB']->sql_fetch_assoc($res);
843 $this->element = $record[
'tablename'] .
':' . $record[
'recuid'];
844 $this->lastSyslogId = $record[
'sys_log_uid'] - 1;
858 if ($table ===
'pages') {
862 $pageId = $record[
'pid'];
865 if (!isset($this->pageAccessCache[$pageId])) {
871 return ($this->pageAccessCache[$pageId] !== FALSE);
892 if (!isset($this->recordCache[$table][
$uid])) {
893 $this->recordCache[$table][
$uid] = BackendUtility::getRecord($table, $uid,
'*',
'', FALSE);
895 return $this->recordCache[$table][
$uid];
920 if ($value !==
'' && !preg_match(
'#^[a-z0-9_.]+:[0-9]+$#i', $value)) {
924 case 'rollbackFields':
926 if ($value !==
'' && !preg_match(
'#^[a-z0-9_.]+(:[0-9]+(:[a-z0-9_.]+)?)?$#i', $value)) {
936 $value = (int)$value;
939 if (!is_array($value)) {
linkPage($str, $inparams=array(), $anchor='', $title='')
createRollbackLink($key, $alt='', $type=0)
removeFilefields($table, $dataArray)
static skinImg($backPath, $src, $wHattribs='', $outputMode=0)
static readPageAccess($id, $perms_clause)
static getWorkspaceVersionOfRecord($workspace, $table, $uid, $fields=' *')
static getItemLabel($table, $col, $printAllWrap='')
static getIndpEnv($getEnvName)
static makeInstance($className)
resolveElement($table, $uid)
static calcAge($seconds, $labels=' min|hrs|days|yrs|min|hour|day|year')
static getRecordTitle($table, $row, $prep=FALSE, $forceResult=TRUE)
static getModuleUrl($moduleName, $urlParameters=array(), $backPathOverride=FALSE, $returnAbsoluteUrl=FALSE)
displayMultipleDiff($diff)
static getUserNames($fields='username, usergroup, usergroup_cached_list, uid', $where='')
generateTitle($table, $uid)
static getSpriteIcon($iconName, array $options=array(), array $overlays=array())
debug($variable='', $name=' *variable *', $line=' *line *', $file=' *file *', $recursiveDepth=3, $debugLevel=E_DEBUG)
static redirect($url, $httpStatus=self::HTTP_STATUS_303)
hasPageAccess($table, $uid)
static sanitizeLocalUrl($url='')
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
getHistoryData($table, $uid)
renderDiff($entry, $table, $rollbackUid=0)