Documentation TYPO3 par Ameos |
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com) 00006 * (c) 2006 Sebastian Kurfuerst (sebastian@garbage-group.de) 00007 * All rights reserved 00008 * 00009 * This script is part of the TYPO3 project. The TYPO3 project is 00010 * free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * The GNU General Public License can be found at 00016 * http://www.gnu.org/copyleft/gpl.html. 00017 * A copy is found in the textfile GPL.txt and important notices to the license 00018 * from the author is found in LICENSE.txt distributed with these scripts. 00019 * 00020 * 00021 * This script is distributed in the hope that it will be useful, 00022 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00024 * GNU General Public License for more details. 00025 * 00026 * This copyright notice MUST APPEAR in all copies of the script! 00027 ***************************************************************/ 00045 class recordHistory { 00046 // External, static: 00047 var $maxSteps=20; // Maximum number of sys_history steps to show. 00048 var $showDiff=1; // display diff or not (0-no diff, 1-inline) 00049 var $showSubElements=1; // on a pages table - show sub elements as well. 00050 var $showInsertDelete=1; // show inserts and deletes as well 00051 00052 // Internal, GPvars 00053 var $element; // Element reference, syntax [tablename]:[uid] 00054 var $lastSyslogId; // syslog ID which is not shown anymore 00055 var $returnUrl; 00056 00057 // Internal 00058 var $changeLog; 00059 var $showMarked=FALSE; 00065 function recordHistory() { 00066 // GPvars: 00067 $this->element = t3lib_div::_GP('element'); 00068 $this->returnUrl = t3lib_div::_GP('returnUrl'); 00069 $this->lastSyslogId = t3lib_div::_GP('diff'); 00070 $this->rollbackFields = t3lib_div::_GP('rollbackFields'); 00071 // resolve sh_uid if set 00072 $this->resolveShUid(); 00073 } 00074 00081 function main() { 00082 $content = ''; 00083 00084 // single-click rollback 00085 if (t3lib_div::_GP('revert') && t3lib_div::_GP('sumUp')) { 00086 $this->rollbackFields = t3lib_div::_GP('revert'); 00087 $this->showInsertDelete = 0; 00088 $this->showSubElements = 0; 00089 00090 $element = explode(':',$this->element); 00091 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*','sys_history', 'tablename='.$GLOBALS['TYPO3_DB']->fullQuoteStr($element[0], 'sys_history').' AND recuid='.intval($element[1]), '', 'uid DESC', '1'); 00092 $record = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); 00093 $this->lastSyslogId = $record['sys_log_uid']; 00094 00095 $this->createChangeLog(); 00096 $completeDiff = $this->createMultipleDiff(); 00097 $this->performRollback($completeDiff); 00098 Header ('Location: '.t3lib_div::locationHeaderUrl($this->returnUrl)); 00099 exit; 00100 } 00101 00102 // save snapshot 00103 if (t3lib_div::_GP('highlight') && !t3lib_div::_GP('settings')) { 00104 $this->toggleHighlight(t3lib_div::_GP('highlight')); 00105 } 00106 00107 $content .= $this->displaySettings(); 00108 if ($this->createChangeLog()) { 00109 if ($this->rollbackFields) { 00110 $completeDiff = $this->createMultipleDiff(); 00111 $content .= $this->performRollback($completeDiff); 00112 00113 } 00114 if ($this->lastSyslogId) { 00115 $completeDiff = $this->createMultipleDiff(); 00116 $content .= $this->displayMultipleDiff($completeDiff); 00117 } 00118 if ($this->element) { 00119 $content .= $this->displayHistory(); 00120 } 00121 } 00122 return $content; 00123 } 00124 00125 /******************************* 00126 * 00127 * database actions 00128 * 00129 *******************************/ 00130 00137 function toggleHighlight($uid) { 00138 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('snapshot','sys_history','uid='.intval($uid)); 00139 $tmp = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); 00140 if ($tmp['snapshot']) { 00141 $tmp = 0; 00142 } else { 00143 $tmp = 1; 00144 } 00145 $updateFields = array('snapshot' => $tmp); 00146 $GLOBALS['TYPO3_DB']->exec_UPDATEquery('sys_history','uid='.intval($uid),$updateFields); 00147 } 00148 00156 function performRollback($diff) { 00157 if (!$this->rollbackFields) { 00158 return 0; 00159 } 00160 00161 $reloadPageFrame=0; 00162 $rollbackData = explode(':',$this->rollbackFields); 00163 00164 // PROCESS INSERTS AND DELETES 00165 // rewrite inserts and deletes 00166 $cmdmapArray = array(); 00167 if ($diff['insertsDeletes']) { 00168 00169 switch (count($rollbackData)) { 00170 case 1: // all tables 00171 $data = $diff['insertsDeletes']; 00172 break; 00173 case 2: // one record 00174 if ($diff['insertsDeletes'][$this->rollbackFields]) { 00175 $data[$this->rollbackFields] = $diff['insertsDeletes'][$this->rollbackFields]; 00176 } 00177 break; 00178 case 3: // one field in one record -- ignore! 00179 break; 00180 } 00181 if ($data) { 00182 foreach ($data as $key => $action) { 00183 $elParts = explode(':',$key); 00184 if ($action == 1) { // inserted records should be deleted 00185 $cmdmapArray[$elParts[0]][$elParts[1]]['delete'] = 1; 00186 // when the record is deleted, the contents of the record do not need to be updated 00187 unset($diff['oldData'][$key]); 00188 unset($diff['newData'][$key]); 00189 } elseif ($action == -1) { // deleted records should be inserted again 00190 $cmdmapArray[$elParts[0]][$elParts[1]]['undelete'] = 1; 00191 } 00192 } 00193 } 00194 } 00195 // Writes the data: 00196 if ($cmdmapArray) { 00197 $tce = t3lib_div::makeInstance('t3lib_TCEmain'); 00198 $tce->stripslashes_values=0; 00199 $tce->debug=0; 00200 $tce->dontProcessTransformations=1; 00201 $tce->start(array(),$cmdmapArray); 00202 $tce->process_cmdmap(); 00203 unset($tce); 00204 if (isset($cmdmapArray['pages'])) { 00205 $reloadPageFrame=1; 00206 } 00207 } 00208 00209 // PROCESS CHANGES 00210 // create an array for process_datamap 00211 $diff_modified = array(); 00212 foreach ($diff['oldData'] as $key => $value) { 00213 $splitKey = explode(':',$key); 00214 $diff_modified[$splitKey[0]][$splitKey[1]] = $value; 00215 } 00216 switch (count($rollbackData)) { 00217 case 1: // all tables 00218 $data = $diff_modified; 00219 break; 00220 case 2: // one record 00221 $data[$rollbackData[0]][$rollbackData[1]] = $diff_modified[$rollbackData[0]][$rollbackData[1]]; 00222 break; 00223 case 3: // one field in one record 00224 $data[$rollbackData[0]][$rollbackData[1]][$rollbackData[2]] = $diff_modified[$rollbackData[0]][$rollbackData[1]][$rollbackData[2]]; 00225 break; 00226 } 00227 // Removing fields: 00228 $data = $this->removeFilefields($rollbackData[0],$data); 00229 00230 // Writes the data: 00231 $tce = t3lib_div::makeInstance('t3lib_TCEmain'); 00232 $tce->stripslashes_values=0; 00233 $tce->debug=0; 00234 $tce->dontProcessTransformations=1; 00235 $tce->start($data,array()); 00236 $tce->process_datamap(); 00237 unset($tce); 00238 if (isset($data['pages'])) { 00239 $reloadPageFrame=1; 00240 } 00241 00242 // return to normal operation 00243 $this->lastSyslogId = FALSE; 00244 $this->rollbackFields = FALSE; 00245 $this->createChangeLog(); 00246 00247 // reload page frame if necessary 00248 if ($reloadPageFrame) { 00249 return '<script type="text/javascript"> 00250 /*<![CDATA[*/ 00251 if (top.content && top.content.nav_frame && top.content.nav_frame.refresh_nav) { 00252 top.content.nav_frame.refresh_nav(); 00253 } 00254 /*]]>*/ 00255 </script>'; 00256 } 00257 } 00258 00259 /******************************* 00260 * 00261 * Display functions 00262 * 00263 *******************************/ 00264 00270 function displaySettings() { 00271 global $BE_USER, $LANG, $SOBE; 00272 // get current selection from UC, merge data, write it back to UC 00273 $currentSelection = is_array($BE_USER->uc['moduleData']['history']) ? $BE_USER->uc['moduleData']['history'] : array('maxSteps' => '', 'showDiff' => 1, 'showSubElements' => 1, 'showInsertDelete' => 1); 00274 00275 $currentSelectionOverride = t3lib_div::_GP('settings'); 00276 if ($currentSelectionOverride) { 00277 $currentSelection = array_merge($currentSelection,$currentSelectionOverride); 00278 $BE_USER->uc['moduleData']['history'] = $currentSelection; 00279 $BE_USER->writeUC($BE_USER->uc); 00280 } 00281 00282 // display selector for number of history entries 00283 $selector['maxSteps'] = array( 00284 10 => 10, 00285 20 => 20, 00286 50 => 50, 00287 100 => 100, 00288 '' => 'maxSteps_all', 00289 'marked' => 'maxSteps_marked' 00290 ); 00291 $selector['showDiff'] = array( 00292 0 => 'showDiff_no', 00293 1 => 'showDiff_inline' 00294 ); 00295 $selector['showSubElements'] = array( 00296 0 => 'no', 00297 1 => 'yes', 00298 ); 00299 $selector['showInsertDelete'] = array( 00300 0 => 'no', 00301 1 => 'yes', 00302 ); 00303 // render selectors 00304 $displayCode = ''; 00305 foreach ($selector as $key => $values) { 00306 $displayCode .= '<tr><td>'.$LANG->getLL($key,1).'</td><td><select name="settings['.$key.']" onChange="document.settings.submit()" style="width:100px">'; 00307 foreach ($values as $singleKey => $singleVal) { 00308 $caption = $LANG->getLL($singleVal,1)?$LANG->getLL($singleVal,1):$singleVal; 00309 $displayCode .= '<option value="'.$singleKey.'" '.(($singleKey == $currentSelection[$key])?'selected':'').'> '.$caption.'</option>'; 00310 } 00311 $displayCode .= '</select></td></tr>'; 00312 } 00313 // set values correctly 00314 if ($currentSelection['maxSteps'] != 'marked') { 00315 $this->maxSteps = $currentSelection['maxSteps']?intval($currentSelection['maxSteps']):''; 00316 } else { 00317 $this->showMarked = TRUE; 00318 $this->maxSteps = FALSE; 00319 } 00320 $this->showDiff = intval($currentSelection['showDiff']); 00321 $this->showSubElements = intval($currentSelection['showSubElements']); 00322 $this->showInsertDelete = intval($currentSelection['showInsertDelete']); 00323 00324 $content = ''; 00325 // get link to page history if the element history is shown 00326 $elParts = explode(':',$this->element); 00327 if ($elParts[0] != 'pages') { 00328 $content .= '<b>'.$LANG->getLL('elementHistory',1).'</b><br />'; 00329 $pid = t3lib_BEfunc::getRecordRaw($elParts[0],'uid='.intval($elParts[1])); 00330 $content .= $this->linkPage($LANG->getLL('elementHistory_link',1),array('element' => 'pages:'.$pid['pid'])); 00331 } 00332 $content .= '<form name="settings" action="'.t3lib_div::getIndpEnv('TYPO3_REQUEST_URL').'" method="post"><table>'.$displayCode.'</table></form>'; 00333 return $SOBE->doc->section($LANG->getLL('settings',1),$content,0,1,0,0); 00334 00335 } 00336 00342 function displayHistory() { 00343 global $LANG; 00344 global $SOBE; 00345 global $TCA; 00346 00347 $lines=array(); 00348 00349 // Initialize: 00350 $lines[] = '<tr class="bgColor5 c-head"> 00351 <td> </td> 00352 <td>'.$LANG->getLL('time',1).'</td> 00353 <td>'.$LANG->getLL('age',1).'</td> 00354 <td>'.$LANG->getLL('user',1).'</td> 00355 <td>'.$LANG->getLL('tableUid',1).'</td> 00356 <td>'.$LANG->getLL('differences',1).'</td> 00357 <td> </td> 00358 </tr>'; 00359 00360 // get default page TSconfig expiration time 00361 $elParts = explode(':',$this->element); 00362 if ($elParts[0] != 'pages') { 00363 $tmp = t3lib_BEfunc::getRecordRaw($elParts[0],'uid='.intval($elParts[1])); 00364 $pid = $tmp['pid']; 00365 } else { 00366 $pid = $elParts[1]; 00367 } 00368 $tmpTsConfig = $GLOBALS['BE_USER']->getTSConfig('TCEMAIN',t3lib_BEfunc::getPagesTSconfig($pid)); 00369 $expirationTime = isset($tmpTsConfig['properties']['default.']['history.']['maxAgeDays']) ? $tmpTsConfig['properties']['default.']['history.']['maxAgeDays'] : 30; 00370 00371 $expirationTimestamp = $expirationTime ? (time() - 60*60*24*$expirationTime) : 0; 00372 $expirationWarning = 0; 00373 00374 $be_user_array = t3lib_BEfunc::getUserNames(); 00375 00376 // Traverse changelog array: 00377 if (!$this->changeLog) { 00378 return 0; 00379 } 00380 $i = 0; 00381 foreach ($this->changeLog as $sysLogUid => $entry) { 00382 // stop after maxSteps 00383 if ($i > $this->maxSteps && $this->maxSteps) { 00384 break; 00385 } 00386 00387 // display inconsistency warning 00388 if ($entry['tstamp'] < $expirationTimestamp && !$expirationWarning) { 00389 $expirationWarning = 1; 00390 00391 $lines[] = ' 00392 <tr class="bgColor4-20"> 00393 <td colspan="7"><b>'.$LANG->getLL('consistenceWarning',1).'</b></td> 00394 </tr>'; 00395 } 00396 00397 // show only marked states 00398 if (!$entry['snapshot'] && $this->showMarked) { 00399 continue; 00400 } 00401 $i++; 00402 // get user names 00403 $userName = ($entry['user']?$be_user_array[$entry['user']]['username']:$LANG->getLL('externalChange',1)); 00404 00405 // build up single line 00406 $singleLine = array(); 00407 00408 // diff link 00409 $image = '<img'.t3lib_iconWorks::skinImg('','gfx/button_top_right.gif').' align="top" alt="'.$LANG->getLL('sumUpChanges',1).'" title="'.$LANG->getLL('sumUpChanges',1).'" />'; 00410 $singleLine[] = '<span>'.$this->linkPage($image,array('diff' => $sysLogUid)).'</span>'; // remove first link 00411 00412 $singleLine[] = htmlspecialchars(t3lib_BEfunc::datetime($entry['tstamp'])); // add time 00413 $singleLine[] = htmlspecialchars(t3lib_BEfunc::calcAge(time()-$entry['tstamp'],$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.minutesHoursDaysYears'))); // add age 00414 $singleLine[] = htmlspecialchars($userName); // add user name 00415 $singleLine[] = $this->linkPage($this->generateTitle($entry['tablename'],$entry['recuid']),array('element' => $entry['tablename'].':'.$entry['recuid']),'',$LANG->getLL('linkRecordHistory',1)); // add record UID 00416 00417 // show insert/delete/diff/changed field names 00418 if ($entry['action']) { // insert or delete of element 00419 $singleLine[] = '<strong>'.htmlspecialchars($LANG->getLL($entry['action'],1)).'</strong>'; 00420 } else { 00421 if (!$this->showDiff) { // display field names instead of full diff 00422 // re-write field names with labels 00423 $tmpFieldList = explode(',',$entry['fieldlist']); 00424 foreach ($tmpFieldList as $key => $value) { 00425 $tmp = str_replace(':','',$LANG->sl(t3lib_BEfunc::getItemLabel($entry['tablename'],$value),1)); 00426 if($tmp) $tmpFieldList[$key] = $tmp; 00427 else unset($tmpFieldList[$key]); // remove fields if no label available 00428 } 00429 $singleLine[] = htmlspecialchars(implode(',',$tmpFieldList)); 00430 } else { // display diff 00431 $diff = $this->renderDiff($entry,$entry['tablename']); 00432 $singleLine[] = $diff; 00433 } 00434 } 00435 // show link to mark/unmark state 00436 if (!$entry['action']) { 00437 if ($entry['snapshot']) { 00438 $image = '<img'.t3lib_iconWorks::skinImg('','gfx/unmarkstate.gif').' align="top" alt="'.$LANG->getLL('unmarkState',1).'" title="'.$LANG->getLL('unmarkState',1).'" />'; 00439 } else { 00440 $image = '<img'.t3lib_iconWorks::skinImg('','gfx/markstate.gif').' align="top" alt="'.$LANG->getLL('markState',1).'" title="'.$LANG->getLL('markState',1).'" />'; 00441 } 00442 $singleLine[] = $this->linkPage($image,array('highlight' => $entry['uid'])); 00443 } else { 00444 $singleLine[] = ''; 00445 } 00446 00447 $bgColorClass = $entry['snapshot'] ? 'bgColor2' : 'bgColor4-20'; 00448 // put line together 00449 $lines[] = ' 00450 <tr class="'.$bgColorClass.'"> 00451 <td>'.implode('</td><td>',$singleLine).'</td> 00452 </tr>'; 00453 } 00454 00455 // Finally, put it all together: 00456 $theCode = ' 00457 <!-- 00458 History (list): 00459 --> 00460 <table border="0" cellpadding="2" cellspacing="2" id="typo3-history"> 00461 '.implode('',$lines).' 00462 </table>'; 00463 00464 if ($this->lastSyslogId) { 00465 $theCode .= '<br />' . $this->linkPage('<img'.t3lib_iconWorks::skinImg('','gfx/group_tobottom.gif').' alt="'.$LANG->getLL('fullView',1).'" title="'.$LANG->getLL('fullView',1).'" />',array('diff' => '')); 00466 } 00467 // Add message about the difference view. 00468 $theCode .= '<br /><img'.t3lib_iconWorks::skinImg('','gfx/icon_note.gif','width="18" height="16"').' align="top" alt="" />'.$LANG->getLL('differenceMsg').'<br /><br />'; 00469 00470 // Add CSH: 00471 $theCode .= t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'history_'.($this->sumUp ? 'sum' : 'log'), $GLOBALS['BACK_PATH'],''); 00472 00473 // Add the whole content as a module section: 00474 return $SOBE->doc->section($LANG->getLL('changes'),$theCode,0,1); 00475 } 00476 00483 function displayMultipleDiff($diff) { 00484 global $SOBE, $LANG; 00485 $content = ''; 00486 00487 // get all array keys needed 00488 $arrayKeys = array_merge(array_keys($diff['newData']),array_keys($diff['insertsDeletes']),array_keys($diff['oldData'])); 00489 $arrayKeys = array_unique($arrayKeys); 00490 00491 if ($arrayKeys) { 00492 foreach ($arrayKeys as $key) { 00493 $record = ''; 00494 $elParts = explode(':',$key); 00495 // turn around diff because it should be a "rollback preview" 00496 if ($diff['insertsDeletes'][$key] == 1) { // insert 00497 $record .= '<b>'.$LANG->getLL('delete',1).'</b>'; 00498 $record .= '<br />'; 00499 } elseif ($diff['insertsDeletes'][$key] == -1) { 00500 $record .= '<b>'.$LANG->getLL('insert',1).'</b>'; 00501 $record .= '<br />'; 00502 } 00503 // build up temporary diff array 00504 // turn around diff because it should be a "rollback preview" 00505 if ($diff['newData'][$key]) { 00506 $tmpArr['newRecord'] = $diff['oldData'][$key]; 00507 $tmpArr['oldRecord'] = $diff['newData'][$key]; 00508 $record .= $this->renderDiff($tmpArr, $elParts[0],$elParts[1]); 00509 } 00510 00511 $elParts = explode(':',$key); 00512 $titleLine = $this->createRollbackLink($key, $LANG->getLL('revertRecord',1),1) . $this->generateTitle($elParts[0],$elParts[1]); 00513 $record = '<div style="margin-left:10px;padding-left:5px;border-left:1px solid black;border-bottom:1px dotted black;padding-bottom:2px;">'.$record.'</div>'; 00514 00515 $content .= $SOBE->doc->section($titleLine,$record,0,0,0,1); 00516 } 00517 $content = $this->createRollbackLink('ALL', $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>'; 00518 } else { 00519 $content = $LANG->getLL('noDifferences',1); 00520 } 00521 return $SOBE->doc->section($LANG->getLL('mergedDifferences',1),$content,0,1,0,1); 00522 } 00523 00533 function renderDiff($entry,$table,$rollbackUid=0) { 00534 global $SOBE, $LANG, $TCA; 00535 $lines=array(); 00536 if (is_array($entry['newRecord'])) { 00537 00538 $t3lib_diff_Obj = t3lib_div::makeInstance('t3lib_diff'); 00539 00540 $fieldsToDisplay = array_keys($entry['newRecord']); 00541 foreach($fieldsToDisplay as $fN) { 00542 t3lib_div::loadTCA($table); 00543 if (is_array($TCA[$table]['columns'][$fN]) && $TCA[$table]['columns'][$fN]['config']['type']!='passthrough') { 00544 00545 // Create diff-result: 00546 $diffres = $t3lib_diff_Obj->makeDiffDisplay( 00547 t3lib_BEfunc::getProcessedValue($table,$fN,$entry['oldRecord'][$fN],0,1), 00548 t3lib_BEfunc::getProcessedValue($table,$fN,$entry['newRecord'][$fN],0,1) 00549 ); 00550 $lines[]=' 00551 <tr class="bgColor4"> 00552 '.($rollbackUid?'<td style="width:33px">'.$this->createRollbackLink($table.':'.$rollbackUid.':'.$fN, $LANG->getLL('revertField',1),2).'</td>':'').' 00553 <td style="width:90px"><em>'.$LANG->sl(t3lib_BEfunc::getItemLabel($table,$fN),1).'</em></td> 00554 <td style="width:300px">'.nl2br($diffres).'</td> 00555 </tr>'; 00556 } 00557 } 00558 } 00559 if ($lines) { 00560 $content = '<table border="0" cellpadding="2" cellspacing="2" id="typo3-history-item"> 00561 '.implode('',$lines).' 00562 </table>'; 00563 return $content; 00564 } 00565 return NULL; // error fallback 00566 } 00567 00568 /******************************* 00569 * 00570 * build up history 00571 * 00572 *******************************/ 00573 00579 function createMultipleDiff() { 00580 $insertsDeletes = array(); 00581 $newArr = array(); 00582 $differences = array(); 00583 if (!$this->changeLog) { 00584 return 0; 00585 } 00586 00587 // traverse changelog array 00588 foreach ($this->changeLog as $key => $value) { 00589 $field = $value['tablename'].':'.$value['recuid']; 00590 // inserts / deletes 00591 if ($value['action']) { 00592 if (!$insertsDeletes[$field]) { 00593 $insertsDeletes[$field] = 0; 00594 } 00595 if ($value['action'] == 'insert') { 00596 $insertsDeletes[$field]++; 00597 } else { 00598 $insertsDeletes[$field]--; 00599 } 00600 // unset not needed fields 00601 if ($insertsDeletes[$field] == 0) { 00602 unset($insertsDeletes[$field]); 00603 } 00604 } else { 00605 // update fields 00606 if (!isset($newArr[$field])) { // first row of field 00607 $newArr[$field] = $value['newRecord']; 00608 $differences[$field] = $value['oldRecord']; 00609 } else { // standard 00610 $differences[$field] = array_merge($differences[$field],$value['oldRecord']); 00611 } 00612 } 00613 } 00614 00615 // remove entries where there were no changes effectively 00616 foreach ($newArr as $record => $value) { 00617 foreach ($value as $key => $innerVal) { 00618 if ($newArr[$record][$key] == $differences[$record][$key]) { 00619 unset($newArr[$record][$key]); 00620 unset($differences[$record][$key]); 00621 } 00622 } 00623 if (empty($newArr[$record]) && empty($differences[$record])) { 00624 unset($newArr[$record]); 00625 unset($differences[$record]); 00626 } 00627 } 00628 return array( 00629 'newData' => $newArr, 00630 'oldData' => $differences, 00631 'insertsDeletes' => $insertsDeletes 00632 ); 00633 } 00634 00640 function createChangeLog() { 00641 00642 global $TCA; 00643 $elParts = explode(':',$this->element); 00644 $changeLog = $this->getHistoryData($elParts[0],$elParts[1]); 00645 00646 // get history of tables of this page and merge it into changelog 00647 if ($elParts[0] == 'pages' && $this->showSubElements) { 00648 foreach ($TCA as $tablename => $value) { 00649 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid',$tablename,'pid='.intval($elParts[1])); // check if there are records on the page 00650 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 00651 if ($newChangeLog = $this->getHistoryData($tablename, $row['uid'])) { // if there is history data available, merge it into changelog 00652 foreach ($newChangeLog as $key => $value) { 00653 $changeLog[$key] = $value; 00654 } 00655 } 00656 } 00657 } 00658 } 00659 if(!$changeLog) { 00660 return 0; 00661 } 00662 00663 krsort($changeLog); 00664 $this->changeLog = $changeLog; 00665 00666 return 1; 00667 } 00668 00676 function getHistoryData($table,$uid) { 00677 global $TCA; 00678 $uid = $this->resolveElement($table,$uid); 00679 // If table is found in $TCA: 00680 if ($TCA[$table]) { 00681 // Selecting the $this->maxSteps most recent states: 00682 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 00683 'sys_history.*,sys_log.userid', 00684 'sys_history,sys_log', 00685 'sys_history.sys_log_uid=sys_log.uid 00686 AND sys_history.tablename='.$GLOBALS['TYPO3_DB']->fullQuoteStr($table, 'sys_history').' 00687 AND sys_history.recuid='.intval($uid), 00688 '', 00689 'sys_log.uid DESC', 00690 $this->maxSteps 00691 ); 00692 00693 // Traversing the result, building up changesArray / changeLog: 00694 #$changesArray=array(); // used temporarily to track intermedia changes 00695 $changeLog=array(); 00696 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 00697 // only history until a certain syslog ID needed 00698 if ($row['sys_log_uid'] < $this->lastSyslogId && $this->lastSyslogId) { 00699 continue; 00700 } 00701 $hisDat = unserialize($row['history_data']); 00702 if (is_array($hisDat['newRecord']) && is_array($hisDat['oldRecord'])) { 00703 00704 // Add hisDat to the changeLog 00705 $hisDat['uid']=$row['uid']; 00706 $hisDat['tstamp']=$row['tstamp']; 00707 $hisDat['user']=$row['userid']; 00708 $hisDat['snapshot']=$row['snapshot']; 00709 $hisDat['fieldlist']=$row['fieldlist']; 00710 $hisDat['tablename']=$row['tablename']; 00711 $hisDat['recuid']=$row['recuid']; 00712 00713 $changeLog[$row['sys_log_uid']]=$hisDat; 00714 00715 // Update change array 00716 // This is used to detect if any intermedia changes have been made. 00717 #$changesArray = array_merge($changesArray,$hisDat['oldRecord']); 00718 } else { 00719 debug('ERROR: [getHistoryData]'); 00720 return 0; // error fallback 00721 } 00722 } 00723 // SELECT INSERTS/DELETES 00724 if ($this->showInsertDelete) { 00725 // Select most recent inserts and deletes // WITHOUT snapshots 00726 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 00727 'uid,userid,action,tstamp', 00728 'sys_log', 00729 'type=1 00730 AND ( action=1 OR action=3 ) 00731 AND tablename='.$GLOBALS['TYPO3_DB']->fullQuoteStr($table, 'sys_log').' 00732 AND recuid='.intval($uid), 00733 '', 00734 'uid DESC', 00735 $this->maxSteps 00736 ); 00737 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 00738 00739 if ($row['uid'] < $this->lastSyslogId && $this->lastSyslogId) { 00740 continue; 00741 } 00742 $hisDat = array(); 00743 00744 switch ($row['action']) { 00745 case 1: // Insert 00746 $hisDat['action'] = 'insert'; 00747 break; 00748 case 3: // Delete 00749 $hisDat['action'] = 'delete'; 00750 break; 00751 } 00752 $hisDat['tstamp']=$row['tstamp']; 00753 $hisDat['user']=$row['userid']; 00754 $hisDat['tablename'] = $table; 00755 $hisDat['recuid'] = $uid; 00756 $changeLog[$row['uid']] = $hisDat; 00757 } 00758 } 00759 return $changeLog; 00760 } 00761 return 0; // error fallback 00762 } 00763 00764 00765 /******************************* 00766 * 00767 * Various helper functions 00768 * 00769 *******************************/ 00770 00778 function generateTitle($table, $uid) { 00779 global $TCA; 00780 00781 $out = $table.':'.$uid; 00782 if ($labelField = $TCA[$table]['ctrl']['label']) { 00783 $record = t3lib_BEfunc::getRecordRaw($table, 'uid='.intval($uid)); 00784 $out .= ' ('.t3lib_BEfunc::getRecordTitle($table, $record, TRUE).')'; 00785 } 00786 return $out; 00787 } 00796 function createRollbackLink($key, $alt='', $type=0) { 00797 global $LANG; 00798 00799 return $this->linkPage('<img '.t3lib_iconWorks::skinImg('','gfx/revert_'.$type.'.gif','width="33" height="33"').' alt="'.$alt.'" title="'.$alt.'" align="middle" />',array('rollbackFields'=>$key)); 00800 } 00801 00812 function linkPage($str,$inparams=array(),$anchor='',$title='') { 00813 00814 // Setting default values based on GET parameters: 00815 $params['element']=$this->element; 00816 $params['returnUrl']=$this->returnUrl; 00817 $params['diff']=$this->lastSyslogId; 00818 // Mergin overriding values: 00819 $params = array_merge($params,$inparams); 00820 00821 // Make the link: 00822 $Ahref = 'show_rechis.php?'.t3lib_div::implodeArrayForUrl('',$params).($anchor?'#'.$anchor:''); 00823 $link = '<a href="'.htmlspecialchars($Ahref).'"'.($title?' title="'.$title.'"':'').'>'.$str.'</a>'; 00824 00825 // Return link: 00826 return $link; 00827 } 00828 00837 function removeFilefields($table,$dataArray) { 00838 global $TCA; 00839 00840 if ($TCA[$table]) { 00841 t3lib_div::loadTCA($table); 00842 00843 foreach($TCA[$table]['columns'] as $field => $config) { 00844 if ($config['config']['type']=='group' && $config['config']['internal_type']=='file') { 00845 unset($dataArray[$field]); 00846 } 00847 } 00848 } 00849 return $dataArray; 00850 } 00851 00859 function resolveElement($table,$uid) { 00860 if (isset($GLOBALS['TCA'][$table])) { 00861 if ($workspaceVersion = t3lib_BEfunc::getWorkspaceVersionOfRecord($GLOBALS['BE_USER']->workspace, $table, $uid, 'uid')) { 00862 $uid = $workspaceVersion['uid']; 00863 } 00864 } 00865 return $uid; 00866 } 00867 00873 function resolveShUid() { 00874 if (t3lib_div::_GP('sh_uid')) { 00875 $sh_uid = t3lib_div::_GP('sh_uid'); 00876 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*','sys_history', 'uid='.intval($sh_uid)); 00877 $record = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); 00878 $this->element = $record['tablename'].':'.$record['recuid']; 00879 $this->lastSyslogId = $record['sys_log_uid']-1; 00880 } 00881 } 00882 } 00883 ?>