|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 2004-2011 Kasper Skårhøj (kasperYYYY@typo3.com) 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * 00017 * This script is distributed in the hope that it will be useful, 00018 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 * GNU General Public License for more details. 00021 * 00022 * This copyright notice MUST APPEAR in all copies of the script! 00023 ***************************************************************/ 00024 /** 00025 * Versioning module 00026 * 00027 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00028 */ 00029 /** 00030 * [CLASS/FUNCTION INDEX of SCRIPT] 00031 * 00032 * 00033 * 00034 * 102: class tx_version_cm1 extends t3lib_SCbase 00035 * 00036 * SECTION: Standard module initialization 00037 * 138: function menuConfig() 00038 * 175: function main() 00039 * 236: function jumpToUrl(URL) 00040 * 296: function printContent() 00041 * 00042 * SECTION: Versioning management 00043 * 322: function versioningMgm() 00044 * 485: function pageSubContent($pid,$c=0) 00045 * 539: function lookForOwnVersions($table,$uid) 00046 * 556: function adminLinks($table,$row) 00047 * 00048 * SECTION: Workspace management 00049 * 628: function workspaceMgm() 00050 * 688: function displayWorkspaceOverview() 00051 * 758: function displayWorkspaceOverview_list($pArray) 00052 * 923: function displayWorkspaceOverview_setInPageArray(&$pArray,$table,$row) 00053 * 936: function displayWorkspaceOverview_allStageCmd() 00054 * 00055 * SECTION: Helper functions (REDUNDANT FROM user/ws/index.php - someone could refactor this...) 00056 * 986: function formatVerId($verId) 00057 * 996: function formatWorkspace($wsid) 00058 * 1023: function formatCount($count) 00059 * 1050: function versionsInOtherWS($table,$uid) 00060 * 1080: function showStageChangeLog($table,$id,$stageCommands) 00061 * 1129: function subElements($uid,$treeLevel,$origId=0) 00062 * 1232: function subElements_getNonPageRecords($tN, $uid, &$recList) 00063 * 1262: function subElements_renderItem(&$tCell,$tN,$uid,$rec,$origId,$iconMode,$HTMLdata) 00064 * 1331: function markupNewOriginals() 00065 * 1353: function createDiffView($table, $diff_1_record, $diff_2_record) 00066 * 1470: function displayWorkspaceOverview_stageCmd($table,&$rec_off) 00067 * 1557: function displayWorkspaceOverview_commandLinks($table,&$rec_on,&$rec_off,$vType) 00068 * 1627: function displayWorkspaceOverview_commandLinksSub($table,$rec,$origId) 00069 * 00070 * SECTION: Processing 00071 * 1683: function publishAction() 00072 * 00073 * TOTAL FUNCTIONS: 27 00074 * (This index is automatically created/updated by the extension "extdeveval") 00075 * 00076 */ 00077 00078 00079 // DEFAULT initialization of a module [BEGIN] 00080 unset($MCONF); 00081 require ('conf.php'); 00082 require ($BACK_PATH.'init.php'); 00083 require ($BACK_PATH.'template.php'); 00084 $LANG->includeLLFile('EXT:version/locallang.xml'); 00085 // DEFAULT initialization of a module [END] 00086 00087 require_once('../ws/class.wslib.php'); 00088 00089 00090 00091 /** 00092 * Versioning module, including workspace management 00093 * 00094 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00095 * @package TYPO3 00096 * @subpackage core 00097 */ 00098 class tx_version_cm1 extends t3lib_SCbase { 00099 00100 // Default variables for backend modules 00101 var $MCONF = array(); // Module configuration 00102 var $MOD_MENU = array(); // Module menu items 00103 var $MOD_SETTINGS = array(); // Module session settings 00104 00105 /** 00106 * document template object 00107 * 00108 * @var mediumDoc 00109 */ 00110 var $doc; 00111 var $content; // Accumulated content 00112 00113 00114 // Internal: 00115 var $showWorkspaceCol = 0; 00116 var $formatWorkspace_cache = array(); 00117 var $formatCount_cache = array(); 00118 var $targets = array(); // Accumulation of online targets. 00119 var $pageModule = ''; // Name of page module 00120 var $publishAccess = FALSE; 00121 var $be_user_Array = array(); 00122 var $stageIndex = array(); 00123 var $recIndex = array(); 00124 protected $showDraftWorkspace = FALSE; // Determines whether to show the dummy draft workspace 00125 00126 00127 00128 00129 00130 00131 /********************************* 00132 * 00133 * Standard module initialization 00134 * 00135 *********************************/ 00136 00137 /** 00138 * Initialize menu configuration 00139 * 00140 * @return void 00141 */ 00142 function menuConfig() { 00143 00144 // fetches the configuration of the version extension 00145 $versionExtconf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['version']); 00146 // show draft workspace only if enabled in the version extensions config 00147 if($versionExtconf['showDraftWorkspace']) { 00148 $this->showDraftWorkspace = TRUE; 00149 } 00150 00151 // Menu items: 00152 $this->MOD_MENU = array( 00153 'filter' => array( 00154 1 => $GLOBALS['LANG']->getLL('filter_drafts'), 00155 2 => $GLOBALS['LANG']->getLL('filter_archive'), 00156 0 => $GLOBALS['LANG']->getLL('filter_all'), 00157 ), 00158 'display' => array( 00159 0 => $GLOBALS['LANG']->getLL('liveWorkspace'), 00160 -98 => $GLOBALS['LANG']->getLL('draftWorkspaces'), 00161 -99 => $GLOBALS['LANG']->getLL('filter_all'), 00162 ), 00163 'diff' => '' 00164 ); 00165 00166 if($this->showDraftWorkspace === TRUE) { 00167 $this->MOD_MENU['display'][-1] = $GLOBALS['LANG']->getLL('defaultDraft'); 00168 } 00169 00170 // Add workspaces: 00171 if ($GLOBALS['BE_USER']->workspace===0) { // Spend time on this only in online workspace because it might take time: 00172 $workspaces = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,title,adminusers,members,reviewers','sys_workspace','pid=0'.t3lib_BEfunc::deleteClause('sys_workspace'),'','title'); 00173 foreach($workspaces as $rec) { 00174 if ($GLOBALS['BE_USER']->checkWorkspace($rec)) { 00175 $this->MOD_MENU['display'][$rec['uid']] = '['.$rec['uid'].'] '.$rec['title']; 00176 } 00177 } 00178 } 00179 00180 // CLEANSE SETTINGS 00181 $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name'], 'ses'); 00182 } 00183 00184 /** 00185 * Main function of the module. Write the content to $this->content 00186 * 00187 * @return void 00188 */ 00189 function main() { 00190 global $BE_USER,$LANG,$BACK_PATH,$TCA_DESCR,$TCA,$CLIENT,$TYPO3_CONF_VARS; 00191 00192 // Template markers 00193 $markers = array( 00194 'CSH' => '', 00195 'FUNC_MENU' => '', 00196 'WS_MENU' => '', 00197 'CONTENT' => '' 00198 ); 00199 00200 // Setting module configuration: 00201 $this->MCONF = $GLOBALS['MCONF']; 00202 00203 $this->REQUEST_URI = str_replace('&sendToReview=1','',t3lib_div::getIndpEnv('REQUEST_URI')); 00204 00205 // Draw the header. 00206 $this->doc = t3lib_div::makeInstance('template'); 00207 $this->doc->backPath = $BACK_PATH; 00208 $this->doc->setModuleTemplate('templates/version.html'); 00209 00210 // Add styles 00211 $this->doc->inDocStylesArray[$GLOBALS['MCONF']['name']] = ' 00212 .version-diff-1 { background-color: green; } 00213 .version-diff-2 { background-color: red; } 00214 '; 00215 00216 // Setting up the context sensitive menu: 00217 $this->doc->getContextMenuCode(); 00218 00219 // Getting input data: 00220 $this->id = intval(t3lib_div::_GP('id')); // Page id. If set, indicates activation from Web>Versioning module 00221 if (!$this->id) { 00222 $this->uid = intval(t3lib_div::_GP('uid')); // Record uid. Goes with table name to indicate specific record 00223 $this->table = t3lib_div::_GP('table'); // Record table. Goes with uid to indicate specific record 00224 } else { 00225 $this->uid = $this->id; 00226 $this->table = 'pages'; 00227 } 00228 $this->details = t3lib_div::_GP('details'); // Page id. If set, indicates activation from Web>Versioning module 00229 $this->diffOnly = t3lib_div::_GP('diffOnly'); // Flag. If set, shows only the offline version and with diff-view 00230 00231 // Force this setting: 00232 $this->MOD_SETTINGS['expandSubElements'] = TRUE; 00233 $this->MOD_SETTINGS['diff'] = $this->details || $this->MOD_SETTINGS['diff']?1:0; 00234 00235 // Reading the record: 00236 $record = t3lib_BEfunc::getRecord($this->table,$this->uid); 00237 if ($record['pid']==-1) { 00238 $record = t3lib_BEfunc::getRecord($this->table,$record['t3ver_oid']); 00239 } 00240 00241 $this->recordFound = is_array($record); 00242 00243 $pidValue = $this->table==='pages' ? $this->uid : $record['pid']; 00244 00245 // Checking access etc. 00246 if ($this->recordFound && $TCA[$this->table]['ctrl']['versioningWS']) { 00247 $this->doc->form='<form action="" method="post">'; 00248 $this->uid = $record['uid']; // Might have changed if new live record was found! 00249 00250 // Access check! 00251 // The page will show only if there is a valid page and if this page may be viewed by the user 00252 $this->pageinfo = t3lib_BEfunc::readPageAccess($pidValue,$this->perms_clause); 00253 $access = is_array($this->pageinfo) ? 1 : 0; 00254 00255 if (($pidValue && $access) || ($BE_USER->user['admin'] && !$pidValue)) { 00256 00257 // JavaScript 00258 $this->doc->JScode.= ' 00259 <script language="javascript" type="text/javascript"> 00260 script_ended = 0; 00261 function jumpToUrl(URL) { 00262 window.location.href = URL; 00263 } 00264 00265 function hlSubelements(origId, verId, over, diffLayer) { // 00266 if (over) { 00267 document.getElementById(\'orig_\'+origId).attributes.getNamedItem("class").nodeValue = \'typo3-ver-hl\'; 00268 document.getElementById(\'ver_\'+verId).attributes.getNamedItem("class").nodeValue = \'typo3-ver-hl\'; 00269 if (diffLayer) { 00270 document.getElementById(\'diff_\'+verId).style.visibility = \'visible\'; 00271 } 00272 } else { 00273 document.getElementById(\'orig_\'+origId).attributes.getNamedItem("class").nodeValue = \'typo3-ver\'; 00274 document.getElementById(\'ver_\'+verId).attributes.getNamedItem("class").nodeValue = \'typo3-ver\'; 00275 if (diffLayer) { 00276 document.getElementById(\'diff_\'+verId).style.visibility = \'hidden\'; 00277 } 00278 } 00279 } 00280 </script> 00281 '; 00282 00283 // If another page module was specified, replace the default Page module with the new one 00284 $newPageModule = trim($BE_USER->getTSConfigVal('options.overridePageModule')); 00285 $this->pageModule = t3lib_BEfunc::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout'; 00286 00287 // Setting publish access permission for workspace: 00288 $this->publishAccess = $BE_USER->workspacePublishAccess($BE_USER->workspace); 00289 00290 // Render content: 00291 if ($this->id) { 00292 $this->workspaceMgm(); 00293 } else { 00294 $this->versioningMgm(); 00295 } 00296 } 00297 00298 $this->content.=$this->doc->spacer(10); 00299 00300 // Setting up the buttons and markers for docheader 00301 $docHeaderButtons = $this->getButtons(); 00302 $markers['CSH'] = $docHeaderButtons['csh']; 00303 $markers['FUNC_MENU'] = t3lib_BEfunc::getFuncMenu($this->id, 'SET[function]', $this->MOD_SETTINGS['function'], $this->MOD_MENU['function']); 00304 $markers['WS_MENU'] = $this->workspaceMenu(); 00305 $markers['CONTENT'] = $this->content; 00306 } else { 00307 // If no access or id value, create empty document 00308 $this->content = $this->doc->section($LANG->getLL('clickAPage_header'), $LANG->getLL('clickAPage_content'), 0, 1); 00309 00310 // Setting up the buttons and markers for docheader 00311 $docHeaderButtons = $this->getButtons(); 00312 $markers['CONTENT'] = $this->content; 00313 } 00314 // Build the <body> for the module 00315 $this->content = $this->doc->startPage($LANG->getLL('title')); 00316 $this->content.= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers); 00317 $this->content.= $this->doc->endPage(); 00318 $this->content = $this->doc->insertStylesAndJS($this->content); 00319 } 00320 00321 /** 00322 * Outputs accumulated module content to browser. 00323 * 00324 * @return void 00325 */ 00326 function printContent() { 00327 echo $this->content; 00328 } 00329 00330 /** 00331 * Create the panel of buttons for submitting the form or otherwise perform operations. 00332 * 00333 * @return array all available buttons as an assoc. array 00334 */ 00335 protected function getButtons() { 00336 global $TCA, $LANG, $BACK_PATH, $BE_USER; 00337 00338 $buttons = array( 00339 'csh' => '', 00340 'view' => '', 00341 'record_list' => '', 00342 'shortcut' => '', 00343 ); 00344 // CSH 00345 //$buttons['csh'] = t3lib_BEfunc::cshItem('_MOD_web_txversionM1', '', $GLOBALS['BACK_PATH']); 00346 00347 if ($this->recordFound && $TCA[$this->table]['ctrl']['versioningWS']) { 00348 // View page 00349 $buttons['view'] = '<a href="#" onclick="' . htmlspecialchars(t3lib_BEfunc::viewOnClick($this->pageinfo['uid'], $BACK_PATH, t3lib_BEfunc::BEgetRootLine($this->pageinfo['uid']))) . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showPage', TRUE) . '">' . 00350 t3lib_iconWorks::getSpriteIcon('actions-document-view') . 00351 '</a>'; 00352 00353 // Shortcut 00354 if ($BE_USER->mayMakeShortcut()) { 00355 $buttons['shortcut'] = $this->doc->makeShortcutIcon('id, edit_record, pointer, new_unique_uid, search_field, search_levels, showLimit', implode(',', array_keys($this->MOD_MENU)), $this->MCONF['name']); 00356 } 00357 00358 // If access to Web>List for user, then link to that module. 00359 $buttons['record_list'] = t3lib_BEfunc::getListViewLink( 00360 array( 00361 'id' => $this->pageinfo['uid'], 00362 'returnUrl' => t3lib_div::getIndpEnv('REQUEST_URI'), 00363 ), 00364 '', 00365 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showList') 00366 ); 00367 } 00368 return $buttons; 00369 } 00370 00371 00372 00373 00374 00375 00376 00377 00378 /****************************** 00379 * 00380 * Versioning management 00381 * 00382 ******************************/ 00383 00384 /** 00385 * Management of versions for record 00386 * 00387 * @return void 00388 */ 00389 function versioningMgm() { 00390 global $TCA; 00391 00392 // Diffing: 00393 $diff_1 = t3lib_div::_POST('diff_1'); 00394 $diff_2 = t3lib_div::_POST('diff_2'); 00395 if (t3lib_div::_POST('do_diff')) { 00396 $content=''; 00397 $content.='<h3>' . $GLOBALS['LANG']->getLL('diffing') . ':</h3>'; 00398 if ($diff_1 && $diff_2) { 00399 $diff_1_record = t3lib_BEfunc::getRecord($this->table, $diff_1); 00400 $diff_2_record = t3lib_BEfunc::getRecord($this->table, $diff_2); 00401 00402 if (is_array($diff_1_record) && is_array($diff_2_record)) { 00403 t3lib_div::loadTCA($this->table); 00404 $t3lib_diff_Obj = t3lib_div::makeInstance('t3lib_diff'); 00405 00406 $tRows=array(); 00407 $tRows[] = ' 00408 <tr class="bgColor5 tableheader"> 00409 <td>' . $GLOBALS['LANG']->getLL('fieldname') . '</td> 00410 <td width="98%">' . $GLOBALS['LANG']->getLL('coloredDiffView') . ':</td> 00411 </tr> 00412 '; 00413 foreach($diff_1_record as $fN => $fV) { 00414 if ($TCA[$this->table]['columns'][$fN] && $TCA[$this->table]['columns'][$fN]['config']['type']!='passthrough' && !t3lib_div::inList('t3ver_label',$fN)) { 00415 if (strcmp($diff_1_record[$fN],$diff_2_record[$fN])) { 00416 00417 $diffres = $t3lib_diff_Obj->makeDiffDisplay( 00418 t3lib_BEfunc::getProcessedValue($this->table,$fN,$diff_2_record[$fN],0,1), 00419 t3lib_BEfunc::getProcessedValue($this->table,$fN,$diff_1_record[$fN],0,1) 00420 ); 00421 00422 $tRows[] = ' 00423 <tr class="bgColor4"> 00424 <td>'.$fN.'</td> 00425 <td width="98%">'.$diffres.'</td> 00426 </tr> 00427 '; 00428 } 00429 } 00430 } 00431 00432 if (count($tRows)>1) { 00433 $content .= '<table border="0" cellpadding="1" cellspacing="1" width="100%">' . implode('', $tRows) . '</table><br /><br />'; 00434 } else { 00435 $content .= $GLOBALS['LANG']->getLL('recordsMatchesCompletely'); 00436 } 00437 } else $content .= $GLOBALS['LANG']->getLL('errorRecordsNotFound'); 00438 } else { 00439 $content .= $GLOBALS['LANG']->getLL('errorDiffSources'); 00440 } 00441 } 00442 00443 // Element: 00444 $record = t3lib_BEfunc::getRecord($this->table,$this->uid); 00445 $recordIcon = t3lib_iconWorks::getSpriteIconForRecord($this->table, $record); 00446 $recTitle = t3lib_BEfunc::getRecordTitle($this->table,$record,TRUE); 00447 00448 // Display versions: 00449 $content.=' 00450 '.$recordIcon.$recTitle.' 00451 <form name="theform" action="'.str_replace('&sendToReview=1','',$this->REQUEST_URI).'" method="post"> 00452 <table border="0" cellspacing="1" cellpadding="1">'; 00453 $content.=' 00454 <tr class="bgColor5 tableheader"> 00455 <td> </td> 00456 <td> </td> 00457 <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_title') . '">' . $GLOBALS['LANG']->getLL('tblHeader_title') . '</td> 00458 <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_uid') . '">' . $GLOBALS['LANG']->getLL('tblHeader_uid') . '</td> 00459 <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_oid') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_oid') . '</td> 00460 <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_id') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_id') . '</td> 00461 <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_wsid') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_wsid') . '</td> 00462 <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_state') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_state') . '</td> 00463 <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_stage') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_stage') . '</td> 00464 <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_count') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_count') . '</td> 00465 <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_pid') . '">' . $GLOBALS['LANG']->getLL('tblHeader_pid') . '</td> 00466 <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_label') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_label') . '</td> 00467 <td colspan="2"><input type="submit" name="do_diff" value="' . $GLOBALS['LANG']->getLL('diff') . '" /></td> 00468 </tr>'; 00469 00470 $versions = t3lib_BEfunc::selectVersionsOfRecord($this->table, $this->uid, '*', $GLOBALS['BE_USER']->workspace); 00471 foreach($versions as $row) { 00472 $adminLinks = $this->adminLinks($this->table,$row); 00473 00474 $content.=' 00475 <tr class="' . ($row['uid'] != $this->uid ? 'bgColor4' : 'bgColor2 tableheader') . '"> 00476 <td>'.($row['uid']!=$this->uid ? '<a href="'.$this->doc->issueCommand('&cmd['.$this->table.']['.$this->uid.'][version][swapWith]='.$row['uid'].'&cmd['.$this->table.']['.$this->uid.'][version][action]=swap').'" title="' . $GLOBALS['LANG']->getLL('swapWithCurrent', TRUE) . '">'. 00477 t3lib_iconWorks::getSpriteIcon('actions-version-swap-version') . 00478 '</a>' /* ( 00479 $this->table == 'pages' ? 00480 '<a href="'.$this->doc->issueCommand('&cmd['.$this->table.']['.$this->uid.'][version][action]=swap&cmd['.$this->table.']['.$this->uid.'][version][swapWith]='.$row['uid'].'&cmd['.$this->table.']['.$this->uid.'][version][swapContent]=1').'">'. 00481 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert2.gif','width="14" height="14"').' alt="" title="Publish page AND content!" />'. 00482 '</a>'. 00483 '<a href="'.$this->doc->issueCommand('&cmd['.$this->table.']['.$this->uid.'][version][action]=swap&cmd['.$this->table.']['.$this->uid.'][version][swapWith]='.$row['uid'].'&cmd['.$this->table.']['.$this->uid.'][version][swapContent]=ALL').'">'. 00484 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert4.gif','width="14" height="14"').' alt="" title="Publish page AND content! - AND ALL SUBPAGES!" />'. 00485 '</a>' : '') */ : t3lib_iconWorks::getSpriteIcon('status-status-current', array('title' => $GLOBALS['LANG']->getLL('currentOnlineVersion', TRUE)))) . '</td> 00486 <td nowrap="nowrap">'.$adminLinks.'</td> 00487 <td nowrap="nowrap">'.t3lib_BEfunc::getRecordTitle($this->table,$row,TRUE).'</td> 00488 <td>'.$row['uid'].'</td> 00489 <td>'.$row['t3ver_oid'].'</td> 00490 <td>'.$row['t3ver_id'].'</td> 00491 <td>'.$row['t3ver_wsid'].'</td> 00492 <td>'.$row['t3ver_state'].'</td> 00493 <td>'.$row['t3ver_stage'].'</td> 00494 <td>'.$row['t3ver_count'].'</td> 00495 <td>'.$row['pid'].'</td> 00496 <td nowrap="nowrap"><a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick('&edit['.$this->table.']['.$row['uid'].']=edit&columnsOnly=t3ver_label',$this->doc->backPath)).'" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:cm.edit', TRUE) . '">' . 00497 t3lib_iconWorks::getSpriteIcon('actions-document-open') . 00498 '</a>' . htmlspecialchars($row['t3ver_label']) . '</td> 00499 <td class="version-diff-1"><input type="radio" name="diff_1" value="'.$row['uid'].'"'.($diff_1==$row['uid'] ? ' checked="checked"':'').'/></td> 00500 <td class="version-diff-2"><input type="radio" name="diff_2" value="'.$row['uid'].'"'.($diff_2==$row['uid'] ? ' checked="checked"':'').'/></td> 00501 </tr>'; 00502 00503 // Show sub-content if the table is pages AND it is not the online branch (because that will mostly render the WHOLE tree below - not smart;) 00504 if ($this->table == 'pages' && $row['uid']!=$this->uid) { 00505 $sub = $this->pageSubContent($row['uid']); 00506 00507 if ($sub) { 00508 $content.=' 00509 <tr> 00510 <td></td> 00511 <td></td> 00512 <td colspan="10">'.$sub.'</td> 00513 <td colspan="2"></td> 00514 </tr>'; 00515 } 00516 } 00517 } 00518 $content.='</table></form>'; 00519 00520 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('title'), $content, 0, 1); 00521 00522 00523 // Create new: 00524 $content=' 00525 00526 <form action="'.$this->doc->backPath.'tce_db.php" method="post"> 00527 ' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_label') . ': <input type="text" name="cmd[' . $this->table . '][' . $this->uid . '][version][label]" /><br /> 00528 '.(($this->table == 'pages' && $GLOBALS['TYPO3_CONF_VARS']['BE']['elementVersioningOnly'] == FALSE)? '<select name="cmd['.$this->table.']['.$this->uid.'][version][treeLevels]"> 00529 '.($GLOBALS['BE_USER']->workspaceVersioningTypeAccess(0) ? '<option value="0">' . $GLOBALS['LANG']->getLL('cmdPid0') . '</option>' : '').' 00530 '.($GLOBALS['BE_USER']->workspaceVersioningTypeAccess(1) ? '<option value="100">' . $GLOBALS['LANG']->getLL('cmdPid100') . '</option>' : '').' 00531 '.($GLOBALS['BE_USER']->workspaceVersioningTypeAccess(-1) ? '<option value="-1">' . $GLOBALS['LANG']->getLL('cmdPid1') . '</option>' : '').' 00532 </select>' : '').' 00533 <br /><input type="hidden" name="cmd[' . $this->table . '][' . $this->uid . '][version][action]" value="new" /> 00534 <input type="hidden" name="prErr" value="1" /> 00535 <input type="hidden" name="redirect" value="'.htmlspecialchars($this->REQUEST_URI).'" /> 00536 <input type="submit" name="_" value="' . $GLOBALS['LANG']->getLL('createNewVersion') . '" /> 00537 ' . t3lib_TCEforms::getHiddenTokenField('tceAction') . ' 00538 </form> 00539 00540 '; 00541 00542 $this->content.=$this->doc->spacer(15); 00543 $this->content.=$this->doc->section($GLOBALS['LANG']->getLL('createNewVersion'), $content,0,1); 00544 00545 } 00546 00547 /** 00548 * Recursively look for children for page version with $pid 00549 * 00550 * @param integer UID of page record for which to look up sub-elements following that version 00551 * @param integer Counter, do not set (limits to 100 levels) 00552 * @return string Table with content if any 00553 */ 00554 function pageSubContent($pid,$c=0) { 00555 global $TCA; 00556 00557 $tableNames = t3lib_div::removeArrayEntryByValue(array_keys($TCA),'pages'); 00558 $tableNames[] = 'pages'; 00559 00560 foreach($tableNames as $tN) { 00561 // Basically list ALL tables - not only those being copied might be found! 00562 #if ($TCA[$tN]['ctrl']['versioning_followPages'] || $tN=='pages') { 00563 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $tN, 'pid='.intval($pid).t3lib_BEfunc::deleteClause($tN), '', ($TCA[$tN]['ctrl']['sortby'] ? $TCA[$tN]['ctrl']['sortby'] : '')); 00564 00565 if ($GLOBALS['TYPO3_DB']->sql_num_rows($mres)) { 00566 $content.=' 00567 <tr> 00568 <td colspan="4" class="'.($TCA[$tN]['ctrl']['versioning_followPages'] ? 'bgColor6' : ($tN=='pages' ? 'bgColor5' : 'bgColor-10')).'"'.(!$TCA[$tN]['ctrl']['versioning_followPages'] && $tN!='pages' ? ' style="color: #666666; font-style:italic;"':'').'>'.$tN.'</td> 00569 </tr>'; 00570 while ($subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) { 00571 $ownVer = $this->lookForOwnVersions($tN,$subrow['uid']); 00572 $content.=' 00573 <tr> 00574 <td>'.$this->adminLinks($tN,$subrow).'</td> 00575 <td>'.$subrow['uid'].'</td> 00576 '.($ownVer>1 ? '<td style="font-weight: bold; background-color: yellow;"><a href="index.php?table='.rawurlencode($tN).'&uid='.$subrow['uid'].'">'.($ownVer-1).'</a></td>' : '<td></td>').' 00577 <td width="98%">'.t3lib_BEfunc::getRecordTitle($tN,$subrow,TRUE).'</td> 00578 </tr>'; 00579 00580 if ($tN == 'pages' && $c<100) { 00581 $sub = $this->pageSubContent($subrow['uid'],$c+1); 00582 00583 if ($sub) { 00584 $content.=' 00585 <tr> 00586 <td></td> 00587 <td></td> 00588 <td></td> 00589 <td width="98%">'.$sub.'</td> 00590 </tr>'; 00591 } 00592 } 00593 } 00594 } 00595 #} 00596 } 00597 00598 return $content ? '<table border="1" cellpadding="1" cellspacing="0" width="100%">'.$content.'</table>' : ''; 00599 } 00600 00601 /** 00602 * Look for number of versions of a record 00603 * 00604 * @param string Table name 00605 * @param integer Record uid 00606 * @return integer Number of versions for record, false if none. 00607 */ 00608 function lookForOwnVersions($table,$uid) { 00609 global $TCA; 00610 00611 $versions = t3lib_BEfunc::selectVersionsOfRecord($table, $uid, 'uid'); 00612 if (is_array($versions)) { 00613 return count($versions); 00614 } 00615 return FALSE; 00616 } 00617 00618 /** 00619 * Administrative links for a table / record 00620 * 00621 * @param string Table name 00622 * @param array Record for which administrative links are generated. 00623 * @return string HTML link tags. 00624 */ 00625 function adminLinks($table,$row) { 00626 global $BE_USER; 00627 00628 // Edit link: 00629 $adminLink = '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick('&edit['.$table.']['.$row['uid'].']=edit',$this->doc->backPath)).'" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:cm.edit', TRUE) . '">'. 00630 t3lib_iconWorks::getSpriteIcon('actions-document-open') . 00631 '</a>'; 00632 00633 // Delete link: 00634 $adminLink.= '<a href="'.htmlspecialchars($this->doc->issueCommand('&cmd['.$table.']['.$row['uid'].'][delete]=1')).'" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:cm.delete', TRUE) . '">' . 00635 t3lib_iconWorks::getSpriteIcon('actions-edit-delete') . 00636 '</a>'; 00637 00638 00639 00640 if ($table == 'pages') { 00641 00642 // If another page module was specified, replace the default Page module with the new one 00643 $newPageModule = trim($BE_USER->getTSConfigVal('options.overridePageModule')); 00644 $pageModule = t3lib_BEfunc::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout'; 00645 00646 // Perform some acccess checks: 00647 $a_wl = $BE_USER->check('modules','web_list'); 00648 $a_wp = t3lib_extMgm::isLoaded('cms') && $BE_USER->check('modules',$pageModule); 00649 00650 $adminLink.='<a href="#" onclick="top.loadEditId('.$row['uid'].');top.goToModule(\''.$pageModule.'\'); return false;">'. 00651 t3lib_iconWorks::getSpriteIcon('actions-page-open') . 00652 '</a>'; 00653 $adminLink.='<a href="#" onclick="top.loadEditId('.$row['uid'].');top.goToModule(\'web_list\'); return false;">'. 00654 t3lib_iconWorks::getSpriteIcon('actions-system-list-open') . 00655 '</a>'; 00656 00657 // "View page" icon is added: 00658 $adminLink.='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($row['uid'],$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($row['uid']))).'">'. 00659 t3lib_iconWorks::getSpriteIcon('actions-document-view') . 00660 '</a>'; 00661 } else { 00662 if ($row['pid']==-1) { 00663 $getVars = '&ADMCMD_vPrev['.rawurlencode($table.':'.$row['t3ver_oid']).']='.$row['uid']; 00664 00665 // "View page" icon is added: 00666 $adminLink.='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($row['_REAL_PID'],$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($row['_REAL_PID']),'','',$getVars)).'">'. 00667 t3lib_iconWorks::getSpriteIcon('actions-document-view') . 00668 '</a>'; 00669 } 00670 } 00671 00672 return $adminLink; 00673 } 00674 00675 00676 00677 00678 00679 00680 00681 00682 00683 00684 00685 /****************************** 00686 * 00687 * Workspace management 00688 * 00689 ******************************/ 00690 00691 /** 00692 * Management of workspace for page ID 00693 * Called when $this->id is set. 00694 * 00695 * @return void 00696 */ 00697 function workspaceMgm() { 00698 00699 // Perform workspace publishing action if buttons are pressed: 00700 $errors = $this->publishAction(); 00701 00702 // Generate workspace overview: 00703 $WSoverview = $this->displayWorkspaceOverview(); 00704 00705 // Buttons for publish / swap: 00706 $actionLinks = '<br />'; 00707 if ($GLOBALS['BE_USER']->workspace!==0) { 00708 if ($this->publishAccess) { 00709 $actionLinks.= '<input type="submit" name="_publish" value="' . $GLOBALS['LANG']->getLL('publishPage') . '" onclick="return confirm(\'' . sprintf($GLOBALS['LANG']->getLL('publishPageQuestion'), $GLOBALS['BE_USER']->workspaceRec['publish_access'] & 1 ? $GLOBALS['LANG']->getLL('publishPageQuestionStage') : '') . '\');"/>'; 00710 if ($GLOBALS['BE_USER']->workspaceSwapAccess()) { 00711 $actionLinks.= '<input type="submit" name="_swap" value="' . $GLOBALS['LANG']->getLL('swapPage') . '" onclick="return confirm(\'' . sprintf($GLOBALS['LANG']->getLL('swapPageQuestion'), $GLOBALS['BE_USER']->workspaceRec['publish_access'] & 1 ? $GLOBALS['LANG']->getLL('publishPageQuestionStage') : '') . '\');" />'; 00712 } 00713 } else { 00714 $actionLinks.= $this->doc->icons(1) . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_user_ws.xml:no_publish_permission'); 00715 } 00716 } 00717 00718 $actionLinks.= '<input type="submit" name="_" value="' . $GLOBALS['LANG']->getLL('refresh') . '" />'; 00719 $actionLinks.= '<input type="submit" name="_previewLink" value="' . $GLOBALS['LANG']->getLL('previewLink') . '" />'; 00720 $actionLinks.= '<input type="checkbox" class="checkbox" name="_previewLink_wholeWorkspace" id="_previewLink_wholeWorkspace" value="1" /><label for="_previewLink_wholeWorkspace">' . $GLOBALS['LANG']->getLL('allowPreviewOfWholeWorkspace') . '</label>'; 00721 $actionLinks.= $this->displayWorkspaceOverview_allStageCmd(); 00722 00723 if ($actionLinks || count($errors)) { 00724 $this->content .= $this->doc->section('', $actionLinks . (count($errors) ? '<h3>' . $GLOABLS['LANG']->getLL('errors') . '</h3><br />' . implode('<br />', $errors) . '<hr />' : ''), 0, 1); 00725 } 00726 00727 if (t3lib_div::_POST('_previewLink')) { 00728 $ttlHours = intval($GLOBALS['BE_USER']->getTSConfigVal('options.workspaces.previewLinkTTLHours')); 00729 $ttlHours = ($ttlHours ? $ttlHours : 24*2); 00730 00731 if (t3lib_div::_POST('_previewLink_wholeWorkspace')) { 00732 $previewUrl = t3lib_BEfunc::getViewDomain($this->id) . '/index.php?ADMCMD_prev=' . t3lib_BEfunc::compilePreviewKeyword('', $GLOBALS['BE_USER']->user['uid'], 60*60*$ttlHours, $GLOBALS['BE_USER']->workspace) . '&id=' . intval($this->id); 00733 } else { 00734 $params = 'id='.$this->id.'&ADMCMD_previewWS='.$GLOBALS['BE_USER']->workspace; 00735 $previewUrl = t3lib_BEfunc::getViewDomain($this->id) . '/index.php?ADMCMD_prev=' . t3lib_BEfunc::compilePreviewKeyword($params, $GLOBALS['BE_USER']->user['uid'], 60*60*$ttlHours); 00736 } 00737 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('previewUrl'), sprintf($GLOBALS['LANG']->getLL('previewInstruction'), $ttlHours) . '<br /><br /><a target="_blank" href="' . htmlspecialchars($previewUrl) . '">' . $previewUrl . '</a>', 0, 1); 00738 } 00739 00740 // Output overview content: 00741 $this->content.= $this->doc->spacer(15); 00742 $this->content.= $this->doc->section($this->details ? $GLOBALS['LANG']->getLL('versionDetails') : $GLOBALS['LANG']->getLL('wsManagement'), $WSoverview,0,1); 00743 00744 } 00745 00746 function workspaceMenu() { 00747 if($this->id) { 00748 $menu = ''; 00749 if ($GLOBALS['BE_USER']->workspace===0) { 00750 $menu.= t3lib_BEfunc::getFuncMenu($this->id,'SET[filter]',$this->MOD_SETTINGS['filter'],$this->MOD_MENU['filter']); 00751 $menu.= t3lib_BEfunc::getFuncMenu($this->id,'SET[display]',$this->MOD_SETTINGS['display'],$this->MOD_MENU['display']); 00752 } 00753 if (!$this->details && $GLOBALS['BE_USER']->workspace && !$this->diffOnly) { 00754 $menu.= t3lib_BEfunc::getFuncCheck($this->id,'SET[diff]',$this->MOD_SETTINGS['diff'],'','','id="checkDiff"').' <label for="checkDiff">' . $GLOBALS['LANG']->getLL('showDiffView') . '</label>'; 00755 } 00756 00757 if ($menu) { 00758 return $menu; 00759 } 00760 } 00761 } 00762 00763 /** 00764 * Rendering the overview of versions in the current workspace 00765 * 00766 * @return string HTML (table) 00767 * @see ws/index.php for sister function! 00768 */ 00769 function displayWorkspaceOverview() { 00770 00771 // Initialize variables: 00772 $this->showWorkspaceCol = $GLOBALS['BE_USER']->workspace===0 && $this->MOD_SETTINGS['display']<=-98; 00773 00774 // Get usernames and groupnames 00775 $be_group_Array = t3lib_BEfunc::getListGroupNames('title,uid'); 00776 $groupArray = array_keys($be_group_Array); 00777 $this->be_user_Array = t3lib_BEfunc::getUserNames(); 00778 if (!$GLOBALS['BE_USER']->isAdmin()) $this->be_user_Array = t3lib_BEfunc::blindUserNames($this->be_user_Array,$groupArray,1); 00779 00780 // Initialize Workspace ID and filter-value: 00781 if ($GLOBALS['BE_USER']->workspace===0) { 00782 $wsid = $this->details ? -99 : $this->MOD_SETTINGS['display']; // Set wsid to the value from the menu (displaying content of other workspaces) 00783 $filter = $this->details ? 0 : $this->MOD_SETTINGS['filter']; 00784 } else { 00785 $wsid = $GLOBALS['BE_USER']->workspace; 00786 $filter = 0; 00787 } 00788 00789 // Initialize workspace object and request all pending versions: 00790 $wslibObj = t3lib_div::makeInstance('wslib'); 00791 00792 // Selecting ALL versions belonging to the workspace: 00793 $versions = $wslibObj->selectVersionsInWorkspace($wsid, $filter, -99, $this->uid); // $this->uid is the page id of LIVE record. 00794 00795 // Traverse versions and build page-display array: 00796 $pArray = array(); 00797 foreach($versions as $table => $records) { 00798 foreach($records as $rec) { 00799 $pageIdField = $table==='pages' ? 't3ver_oid' : 'realpid'; 00800 $this->displayWorkspaceOverview_setInPageArray( 00801 $pArray, 00802 $table, 00803 $rec 00804 ); 00805 } 00806 } 00807 00808 // Make header of overview: 00809 $tableRows = array(); 00810 if (count($pArray)) { 00811 $tableRows[] = ' 00812 <tr class="bgColor5 tableheader"> 00813 '.($this->diffOnly?'':'<td nowrap="nowrap" colspan="2">' . $GLOBALS['LANG']->getLL('liveVersion') . '</td>').' 00814 <td nowrap="nowrap" colspan="2">' . $GLOBALS['LANG']->getLL('wsVersions') . '</td> 00815 <td nowrap="nowrap"'.($this->diffOnly?' colspan="2"':' colspan="4"').'>' . $GLOBALS['LANG']->getLL('controls') . '</td> 00816 </tr>'; 00817 00818 // Add lines from overview: 00819 $tableRows = array_merge($tableRows, $this->displayWorkspaceOverview_list($pArray)); 00820 00821 $table = '<table border="0" cellpadding="0" cellspacing="1" class="lrPadding workspace-overview">'.implode('',$tableRows).'</table>'; 00822 } else $table = ''; 00823 00824 $returnUrl = t3lib_div::sanitizeLocalUrl(t3lib_div::_GP('returnUrl')); 00825 $linkBack = t3lib_div::_GP('returnUrl') ? '<a href="' . htmlspecialchars($returnUrl) . '" class="typo3-goBack">' . 00826 t3lib_iconWorks::getSpriteIcon('actions-view-go-back') . $GLOBALS['LANG']->getLL('goBack', TRUE) . 00827 '</a><br /><br />' : ''; 00828 $resetDiffOnly = $this->diffOnly ? '<a href="index.php?id=' . intval($this->id) . '" class="typo3-goBack">' . $GLOBALS['LANG']->getLL('showAllInformation') . '</a><br /><br />' : ''; 00829 00830 $versionSelector = $GLOBALS['BE_USER']->workspace ? $this->doc->getVersionSelector($this->id) : ''; 00831 00832 return $versionSelector.$linkBack.$resetDiffOnly.$table.$this->markupNewOriginals(); 00833 } 00834 00835 /** 00836 * Rendering the content for the publish / review overview: 00837 * (Made for internal recursive calling) 00838 * 00839 * @param array Storage of the elements to display (see displayWorkspaceOverview() / displayWorkspaceOverview_setInPageArray()) 00840 * @return array Table rows, see displayWorkspaceOverview() 00841 */ 00842 function displayWorkspaceOverview_list($pArray) { 00843 global $TCA; 00844 00845 // If there ARE elements on this level, print them: 00846 $warnAboutVersions_nonPages = FALSE; 00847 $warnAboutVersions_page = FALSE; 00848 if (is_array($pArray)) { 00849 foreach($pArray as $table => $oidArray) { 00850 foreach($oidArray as $oid => $recs) { 00851 00852 // Get CURRENT online record and icon based on "t3ver_oid": 00853 $rec_on = t3lib_BEfunc::getRecord($table,$oid); 00854 $icon = t3lib_iconWorks::getSpriteIconForRecord($table, $rec_on, array('title' => t3lib_BEfunc::getRecordIconAltText($rec_on,$table))); 00855 if ($GLOBALS['BE_USER']->workspace===0) { // Only edit online records if in ONLINE workspace: 00856 $icon = $this->doc->wrapClickMenuOnIcon($icon, $table, $rec_on['uid'], 1, '', '+edit,view,info,delete'); 00857 } 00858 00859 // Online version display: 00860 // Create the main cells which will span over the number of versions there is. 00861 $verLinkUrl = $TCA[$table]['ctrl']['versioningWS']; 00862 $origElement = $icon. 00863 ($verLinkUrl ? '<a href="'.htmlspecialchars('index.php?table='.$table.'&uid='.$rec_on['uid']).'">' : ''). 00864 t3lib_BEfunc::getRecordTitle($table,$rec_on,TRUE). 00865 ($verLinkUrl ? '</a>' : ''); 00866 $mainCell_rowSpan = count($recs)>1 ? ' rowspan="'.count($recs).'"' : ''; 00867 $mainCell = ' 00868 <td align="center"'.$mainCell_rowSpan.'>'.$this->formatVerId($rec_on['t3ver_id']).'</td> 00869 <td nowrap="nowrap"'.$mainCell_rowSpan.'>'. 00870 $origElement. 00871 '###SUB_ELEMENTS###'. // For substitution with sub-elements, if any. 00872 '</td>'; 00873 00874 // Offline versions display: 00875 // Traverse the versions of the element 00876 foreach($recs as $rec) { 00877 00878 // Get the offline version record and icon: 00879 $rec_off = t3lib_BEfunc::getRecord($table,$rec['uid']); 00880 00881 // Prepare swap-mode values: 00882 if ($table==='pages' && $rec_off['t3ver_swapmode']!=-1) { 00883 if ($rec_off['t3ver_swapmode']>0) { 00884 $vType = 'branch'; 00885 } else { 00886 $vType = 'page'; 00887 } 00888 } else { 00889 $vType = 'element'; 00890 } 00891 00892 // Get icon 00893 $icon = t3lib_iconWorks::getSpriteIconForRecord($table, $rec_off, array('title' => t3lib_BEfunc::getRecordIconAltText($rec_off, $table))); 00894 $tempUid = ($table != 'pages' || $vType==='branch' || $GLOBALS['BE_USER']->workspace===0 ? $rec_off['uid'] : $rec_on['uid']); 00895 $icon = $this->doc->wrapClickMenuOnIcon($icon, $table, $tempUid, 1, '', '+edit,' . ($table == 'pages' ? 'view,info,' : '') . 'delete'); 00896 00897 // Prepare diff-code: 00898 if ($this->MOD_SETTINGS['diff'] || $this->diffOnly) { 00899 $diffCode = ''; 00900 list($diffHTML,$diffPct) = $this->createDiffView($table, $rec_off, $rec_on); 00901 if ($rec_on['t3ver_state']==1) { // New record: 00902 $diffCode.= $this->doc->icons(1) . $GLOBALS['LANG']->getLL('newElement') . '<br />'; 00903 $diffCode.= $diffHTML; 00904 } elseif ($rec_off['t3ver_state']==2) { 00905 $diffCode.= $this->doc->icons(2) . $GLOBALS['LANG']->getLL('deletedElement') . '<br />'; 00906 } elseif ($rec_on['t3ver_state']==3) { 00907 $diffCode.= $this->doc->icons(1) . $GLOBALS['LANG']->getLL('moveToPlaceholder') . '<br />'; 00908 } elseif ($rec_off['t3ver_state']==4) { 00909 $diffCode.= $this->doc->icons(1) . $GLOBALS['LANG']->getLL('moveToPointer') . '<br />'; 00910 } else { 00911 $diffCode.= ($diffPct<0 ? $GLOBALS['LANG']->getLL('notAvailable') : ($diffPct ? $diffPct . '% ' . $GLOBALS['LANG']->getLL('change') : '')); 00912 $diffCode.= $diffHTML; 00913 } 00914 } else $diffCode = ''; 00915 00916 switch($vType) { 00917 case 'element': 00918 $swapLabel = $GLOBALS['LANG']->getLL('element'); 00919 $swapClass = 'ver-element'; 00920 $warnAboutVersions_nonPages = $warnAboutVersions_page; // Setting this if sub elements are found with a page+content (must be rendered prior to this of course!) 00921 break; 00922 case 'page': 00923 $swapLabel = $GLOBALS['LANG']->getLL('page'); 00924 $swapClass = 'ver-page'; 00925 $warnAboutVersions_page = !$this->showWorkspaceCol; // This value is true only if multiple workspaces are shown and we need the opposite here. 00926 break; 00927 case 'branch': 00928 $swapLabel = $GLOBALS['LANG']->getLL('branch'); 00929 $swapClass = 'ver-branch'; 00930 break; 00931 } 00932 00933 // Modify main cell based on first version shown: 00934 $subElements = array(); 00935 if ($table==='pages' && $rec_off['t3ver_swapmode']!=-1 && $mainCell) { // For "Page" and "Branch" swap modes where $mainCell is still carrying content (only first version) 00936 $subElements['on'] = $this->subElements($rec_on['uid'], $rec_off['t3ver_swapmode']); 00937 $subElements['off'] = $this->subElements($rec_off['uid'],$rec_off['t3ver_swapmode'],$rec_on['uid']); 00938 } 00939 $mainCell = str_replace('###SUB_ELEMENTS###', $subElements['on'], $mainCell); 00940 00941 // Create version element: 00942 $versionsInOtherWS = $this->versionsInOtherWS($table, $rec_on['uid']); 00943 $versionsInOtherWSWarning = $versionsInOtherWS && $GLOBALS['BE_USER']->workspace !== 0 ? '<br />' . $this->doc->icons(2) . $GLOBALS['LANG']->getLL('otherVersions') . $versionsInOtherWS : ''; 00944 $multipleWarning = (!$mainCell && $GLOBALS['BE_USER']->workspace !== 0 ? '<br />' . $this->doc->icons(3) . '<strong>' . $GLOBALS['LANG']->getLL('multipleVersions') . '</strong>' : ''); 00945 $verWarning = $warnAboutVersions || ($warnAboutVersions_nonPages && $GLOBALS['TCA'][$table]['ctrl']['versioning_followPages']) ? '<br />' . $this->doc->icons(3) . '<strong>' . $GLOBALS['LANG']->getLL('versionInVersion') . '</strong>' : ''; 00946 $verElement = $icon. 00947 (!$this->details ? '<a href="'.htmlspecialchars($this->doc->backPath.t3lib_extMgm::extRelPath('version').'cm1/index.php?id='.($table==='pages'?$rec_on['uid']:$rec_on['pid']).'&details='.rawurlencode($table.':'.$rec_off['uid']).'&returnUrl='.rawurlencode($this->REQUEST_URI)).'">' : ''). 00948 t3lib_BEfunc::getRecordTitle($table,$rec_off,TRUE). 00949 (!$this->details ? '</a>' : ''). 00950 $versionsInOtherWSWarning. 00951 $multipleWarning. 00952 $verWarning; 00953 00954 $ctrlTable = ' 00955 <td nowrap="nowrap">'.$this->showStageChangeLog($table,$rec_off['uid'],$this->displayWorkspaceOverview_stageCmd($table,$rec_off)).'</td> 00956 <td nowrap="nowrap" class="'.$swapClass.'">'. 00957 $this->displayWorkspaceOverview_commandLinks($table,$rec_on,$rec_off,$vType). 00958 htmlspecialchars($swapLabel). 00959 ' </td> 00960 '.(!$this->diffOnly?'<td nowrap="nowrap"><strong>' . $GLOBALS['LANG']->getLL('lifecycle') . ':</strong> '.htmlspecialchars($this->formatCount($rec_off['t3ver_count'])).'</td>'. // Lifecycle 00961 ($this->showWorkspaceCol ? ' 00962 <td nowrap="nowrap"> <strong>' . $GLOBALS['LANG']->getLL('workspace') . ':</strong> '.htmlspecialchars($this->formatWorkspace($rec_off['t3ver_wsid'])).'</td>' : ''):''); 00963 00964 if ($diffCode) { 00965 $verElement = $verElement.' 00966 <br /><strong>' . $GLOBALS['LANG']->getLL('diffToLiveElement') . '</strong> 00967 <table border="0" cellpadding="0" cellspacing="0" class="ver-verElement"> 00968 <tr> 00969 <td class="c-diffCell">'.$diffCode.'</td> 00970 </tr> 00971 </table>'; 00972 } 00973 00974 00975 // Create version cell: 00976 $verCell = ' 00977 <td align="center">'.$this->formatVerId($rec_off['t3ver_id']).'</td> 00978 <td nowrap="nowrap">'. 00979 $verElement. 00980 $subElements['off']. 00981 '</td> 00982 '; 00983 00984 // Compile table row: 00985 $tableRows[] = ' 00986 <tr class="bgColor4"> 00987 '. 00988 ($this->diffOnly?'':$mainCell). 00989 $verCell. 00990 $ctrlTable. 00991 ' 00992 </tr>'; 00993 00994 // Reset the main cell: 00995 $mainCell = ''; 00996 00997 } 00998 } 00999 } 01000 } 01001 01002 return $tableRows; 01003 } 01004 01005 /** 01006 * Building up of the $pArray 01007 * (Internal) 01008 * 01009 * @param array Array that is built up with the page tree structure 01010 * @param string Table name 01011 * @param array Table row 01012 * @return void $pArray is passed by reference and modified internally 01013 */ 01014 function displayWorkspaceOverview_setInPageArray(&$pArray,$table,$row) { 01015 if (!$this->details || $this->details==$table.':'.$row['uid']) { 01016 $pArray[$table][$row['t3ver_oid']][] = $row; 01017 } 01018 } 01019 01020 /** 01021 * Links to stage change of a version 01022 * 01023 * @param string Table name 01024 * @param array Offline record (version) 01025 * @return string HTML content, mainly link tags and images. 01026 */ 01027 function displayWorkspaceOverview_allStageCmd() { 01028 01029 $table = t3lib_div::_GP('table'); 01030 if ($table && $table!='pages') { 01031 $uid = t3lib_div::_GP('uid'); 01032 if ($rec_off = t3lib_BEfunc::getRecordWSOL($table,$uid)) { 01033 $uid = $rec_off['_ORIG_uid']; 01034 } 01035 } else $table = ''; 01036 01037 if ($table) { 01038 if ($uid && $this->recIndex[$table][$uid]) { 01039 $sId = $this->recIndex[$table][$uid]; 01040 switch($sId) { 01041 case 1: 01042 $label = $GLOBALS['LANG']->getLL('commentForReviewer'); 01043 break; 01044 case 10: 01045 $label = $GLOBALS['LANG']->getLL('commentForPublisher'); 01046 break; 01047 } 01048 } else $sId = 0; 01049 } else { 01050 if (count($this->stageIndex[1])) { // Review: 01051 $sId = 1; 01052 $color = '#666666'; 01053 $label = $GLOBALS['LANG']->getLL('sendItemsToReview') . $GLOBALS['LANG']->getLL('commentForReviewer'); 01054 $titleAttrib = $GLOBALS['LANG']->getLL('sendAllToReview'); 01055 } elseif(count($this->stageIndex[10])) { // Publish: 01056 $sId = 10; 01057 $color = '#6666cc'; 01058 $label = $GLOBALS['LANG']->getLL('approveToPublish') . $GLOBALS['LANG']->getLL('commentForPublisher'); 01059 $titleAttrib = $GLOBALS['LANG']->getLL('approveAllToPublish'); 01060 } else { 01061 $sId = 0; 01062 } 01063 } 01064 01065 if ($sId>0) { 01066 $issueCmd = ''; 01067 $itemCount = 0; 01068 01069 if ($table && $uid && $this->recIndex[$table][$uid]) { 01070 $issueCmd.='&cmd['.$table.']['.$uid.'][version][action]=setStage'; 01071 $issueCmd.='&cmd['.$table.']['.$uid.'][version][stageId]='.$this->recIndex[$table][$uid]; 01072 } else { 01073 foreach($this->stageIndex[$sId] as $table => $uidArray) { 01074 $issueCmd.='&cmd['.$table.']['.implode(',',$uidArray).'][version][action]=setStage'; 01075 $issueCmd.='&cmd['.$table.']['.implode(',',$uidArray).'][version][stageId]='.$sId; 01076 $itemCount+=count($uidArray); 01077 } 01078 } 01079 01080 $onClick = 'var commentTxt=window.prompt("'.sprintf($label,$itemCount).'",""); 01081 if (commentTxt!=null) {window.location.href="'.$this->doc->issueCommand($issueCmd,$this->REQUEST_URI).'&generalComment="+escape(commentTxt);}'; 01082 01083 if (t3lib_div::_GP('sendToReview')) { 01084 $onClick.= ' else {window.location.href = "'.$this->REQUEST_URI.'"}'; 01085 $actionLinks.= 01086 $this->doc->wrapScriptTags($onClick); 01087 } else { 01088 $onClick.= ' return false;'; 01089 $actionLinks.= 01090 '<input type="submit" name="_" value="'.htmlspecialchars($titleAttrib).'" onclick="'.htmlspecialchars($onClick).'" />'; 01091 } 01092 } elseif (t3lib_div::_GP('sendToReview')) { 01093 $onClick = 'window.location.href = "'.$this->REQUEST_URI.'";'; 01094 $actionLinks.= 01095 $this->doc->wrapScriptTags($onClick); 01096 } else $actionLinks = ''; 01097 01098 return $actionLinks; 01099 } 01100 01101 01102 01103 01104 01105 01106 /************************************** 01107 * 01108 * Helper functions (REDUNDANT FROM user/ws/index.php - someone could refactor this...) 01109 * 01110 *************************************/ 01111 01112 /** 01113 * Formatting the version number for HTML output 01114 * 01115 * @param integer Version number 01116 * @return string Version number for output 01117 */ 01118 function formatVerId($verId) { 01119 return '1.'.$verId; 01120 } 01121 01122 /** 01123 * Formatting workspace ID into a visual label 01124 * 01125 * @param integer Workspace ID 01126 * @return string Workspace title 01127 */ 01128 function formatWorkspace($wsid) { 01129 01130 // Render, if not cached: 01131 if (!isset($this->formatWorkspace_cache[$wsid])) { 01132 switch($wsid) { 01133 case -1: 01134 $this->formatWorkspace_cache[$wsid] = $GLOBALS['LANG']->getLL('offline'); 01135 break; 01136 case 0: 01137 $this->formatWorkspace_cache[$wsid] = ''; // Does not output anything for ONLINE because it might confuse people to think that the elemnet IS online which is not the case - only that it exists as an offline version in the online workspace... 01138 break; 01139 default: 01140 $titleRec = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('title', 'sys_workspace', 'uid=' . intval($wsid) . t3lib_BEfunc::deleteClause('sys_workspace')); 01141 $this->formatWorkspace_cache[$wsid] = '['.$wsid.'] '.$titleRec['title']; 01142 break; 01143 } 01144 } 01145 01146 return $this->formatWorkspace_cache[$wsid]; 01147 } 01148 01149 /** 01150 * Format publishing count for version (lifecycle state) 01151 * 01152 * @param integer t3ver_count value (number of times it has been online) 01153 * @return string String translation of count. 01154 */ 01155 function formatCount($count) { 01156 01157 // Render, if not cached: 01158 if (!isset($this->formatCount_cache[$count])) { 01159 switch($count) { 01160 case 0: 01161 $this->formatCount_cache[$count] = $GLOBALS['LANG']->getLL('draft'); 01162 break; 01163 case 1: 01164 $this->formatCount_cache[$count] = $GLOBALS['LANG']->getLL('archive'); 01165 break; 01166 default: 01167 $this->formatCount_cache[$count] = sprintf($GLOBALS['LANG']->getLL('publishedXTimes'), $count); 01168 break; 01169 } 01170 } 01171 01172 return $this->formatCount_cache[$count]; 01173 } 01174 01175 /** 01176 * Looking for versions of a record in other workspaces than the current 01177 * 01178 * @param string Table name 01179 * @param integer Record uid 01180 * @return string List of other workspace IDs 01181 */ 01182 function versionsInOtherWS($table,$uid) { 01183 01184 // Check for duplicates: 01185 // Select all versions of record NOT in this workspace: 01186 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows( 01187 't3ver_wsid', 01188 $table, 01189 'pid=-1 01190 AND t3ver_oid='.intval($uid).' 01191 AND t3ver_wsid!='.intval($GLOBALS['BE_USER']->workspace).' 01192 AND (t3ver_wsid=-1 OR t3ver_wsid>0)'. 01193 t3lib_BEfunc::deleteClause($table), 01194 '', 01195 't3ver_wsid', 01196 '', 01197 't3ver_wsid' 01198 ); 01199 if (count($rows)) { 01200 return implode(',',array_keys($rows)); 01201 } 01202 } 01203 01204 /** 01205 * Looks up stage changes for version and displays a formatted view on mouseover. 01206 * 01207 * @param string Table name 01208 * @param integer Record ID 01209 * @param string HTML string to wrap the mouseover around (should be stage change links) 01210 * @return string HTML code. 01211 */ 01212 function showStageChangeLog($table,$id,$stageCommands) { 01213 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows( 01214 'log_data,tstamp,userid', 01215 'sys_log', 01216 'action=6 and details_nr=30 01217 AND tablename='.$GLOBALS['TYPO3_DB']->fullQuoteStr($table,'sys_log').' 01218 AND recuid='.intval($id) 01219 ); 01220 01221 $entry = array(); 01222 foreach($rows as $dat) { 01223 $data = unserialize($dat['log_data']); 01224 $username = $this->be_user_Array[$dat['userid']] ? $this->be_user_Array[$dat['userid']]['username'] : '['.$dat['userid'].']'; 01225 01226 switch($data['stage']) { 01227 case 1: 01228 $text = $GLOBALS['LANG']->getLL('stage.sentToReview'); 01229 break; 01230 case 10: 01231 $text = $GLOBALS['LANG']->getLL('stage.approvedForPublish'); 01232 break; 01233 case -1: 01234 $text = $GLOBALS['LANG']->getLL('stage.rejectedElement'); 01235 break; 01236 case 0: 01237 $text = $GLOBALS['LANG']->getLL('stage.resetToEdit'); 01238 break; 01239 default: 01240 $text = $GLOBALS['LANG']->getLL('stage.undefined'); 01241 break; 01242 } 01243 $text = t3lib_BEfunc::dateTime($dat['tstamp']).': "'.$username.'" '.$text; 01244 $text.= ($data['comment'] ? '<br />' . $GLOBALS['LANG']->getLL('userComment') . ': <em>' . htmlspecialchars($data['comment']) . '</em>' : ''); 01245 01246 $entry[] = $text; 01247 } 01248 01249 return count($entry) ? '<span onmouseover="document.getElementById(\'log_' . $table . $id . '\').style.visibility = \'visible\';" onmouseout="document.getElementById(\'log_' . $table . $id . '\').style.visibility = \'hidden\';">' . $stageCommands . ' (' . count($entry) . ')</span>' . 01250 '<div class="t3-version-infolayer logLayer" id="log_' . $table . $id . '">' . implode('<hr/>', array_reverse($entry)) . '</div>' : $stageCommands; 01251 } 01252 01253 /** 01254 * Creates display of sub elements of a page when the swap mode is either "Page" or "Branch" (0 / ALL) 01255 * 01256 * @param integer Page uid (for either online or offline version, but it MUST have swapmode/treeLevel set to >0 (not -1 indicating element versioning) 01257 * @param integer The treeLevel value, >0 indicates "branch" while 0 means page+content. (-1 would have meant element versioning, but that should never happen for a call to this function!) 01258 * @param integer For offline versions; This is t3ver_oid, the original ID of the online page. 01259 * @return string HTML content. 01260 */ 01261 function subElements($uid,$treeLevel,$origId=0) { 01262 global $TCA; 01263 01264 if (!$this->details && ($GLOBALS['BE_USER']->workspace===0 || !$this->MOD_SETTINGS['expandSubElements'])) { // In online workspace we have a reduced view because otherwise it will bloat the listing: 01265 return '<br /> 01266 <img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/ol/joinbottom.gif','width="18" height="16"').' align="top" alt="" title="" />'. 01267 ($origId ? 01268 '<a href="'.htmlspecialchars($this->doc->backPath.t3lib_extMgm::extRelPath('version').'cm1/index.php?id='.$uid.'&details='.rawurlencode('pages:'.$uid).'&returnUrl='.rawurlencode($this->REQUEST_URI)).'">'. 01269 '<span class="typo3-dimmed"><em>' . $GLOBALS['LANG']->getLL('subElementsClick') . '</em><span></a>' : 01270 '<span class="typo3-dimmed"><em>' . $GLOBALS['LANG']->getLL('subElements') . '</em><span>'); 01271 } else { // For an offline workspace, show sub elements: 01272 01273 $tCell = array(); 01274 01275 // Find records that follow pages when swapping versions: 01276 $recList = array(); 01277 foreach($TCA as $tN => $tCfg) { 01278 if ($tN!='pages' && ($treeLevel>0 || $TCA[$tN]['ctrl']['versioning_followPages'])) { 01279 $this->subElements_getNonPageRecords($tN, $uid, $recList); 01280 } 01281 } 01282 01283 // Render records collected above: 01284 $elCount = count($recList)-1; 01285 foreach($recList as $c => $comb) { 01286 list($tN,$rec) = $comb; 01287 01288 $this->subElements_renderItem( 01289 $tCell, 01290 $tN, 01291 $uid, 01292 $rec, 01293 $origId, 01294 $c==$elCount && $treeLevel==0 ? 1 : 0, // If true, will show bottom-join icon. 01295 '' 01296 ); 01297 } 01298 01299 // For branch, dive into the subtree: 01300 if ($treeLevel>0) { 01301 01302 // Drawing tree: 01303 $tree = t3lib_div::makeInstance('t3lib_pageTree'); 01304 $tree->init('AND '.$GLOBALS['BE_USER']->getPagePermsClause(1)); 01305 $tree->makeHTML = 2; // 2=Also rendering depth-data into the result array 01306 $tree->getTree($uid, 99, ''); 01307 01308 // Traverse page tree: 01309 foreach($tree->tree as $data) { 01310 01311 // Render page in table cell: 01312 $this->subElements_renderItem( 01313 $tCell, 01314 'pages', 01315 $uid, 01316 t3lib_BEfunc::getRecord('pages',$data['row']['uid']), // Needs all fields, at least more than what is given in $data['row']... 01317 $origId, 01318 2, // 2=the join icon and icon for the record is not rendered for pages (where all is in $data['HTML'] 01319 $data['HTML'] 01320 ); 01321 01322 // Find all records from page and collect in $recList: 01323 $recList = array(); 01324 foreach($TCA as $tN => $tCfg) { 01325 if ($tN!=='pages') { 01326 $this->subElements_getNonPageRecords($tN, $data['row']['uid'], $recList); 01327 } 01328 } 01329 01330 // Render records collected above: 01331 $elCount = count($recList)-1; 01332 foreach($recList as $c => $comb) { 01333 list($tN,$rec) = $comb; 01334 01335 $this->subElements_renderItem( 01336 $tCell, 01337 $tN, 01338 $uid, 01339 $rec, 01340 $origId, 01341 $c==$elCount?1:0, // If true, will show bottom-join icon. 01342 $data['HTML_depthData'] 01343 ); 01344 } 01345 } 01346 } 01347 01348 return ' 01349 <!-- Sub-element tree for versions --> 01350 <table border="0" cellpadding="0" cellspacing="1" class="ver-subtree"> 01351 '.implode('',$tCell).' 01352 </table>'; 01353 } 01354 } 01355 01356 /** 01357 * Select records from a table and add them to recList 01358 * 01359 * @param string Table name (from TCA) 01360 * @param integer PID to select records from 01361 * @param array Array where records are accumulated, passed by reference 01362 * @return void 01363 */ 01364 function subElements_getNonPageRecords($tN, $uid, &$recList) { 01365 global $TCA; 01366 01367 $records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows( 01368 '*', 01369 $tN, 01370 'pid='.intval($uid). 01371 ($TCA[$tN]['ctrl']['versioningWS'] ? ' AND t3ver_state=0' : ''). 01372 t3lib_BEfunc::deleteClause($tN), 01373 '', 01374 $TCA[$tN]['ctrl']['sortby'] ? $TCA[$tN]['ctrl']['sortby'] : $GLOBALS['TYPO3_DB']->stripOrderBy($TCA[$tN]['ctrl']['default_sortby']) 01375 ); 01376 01377 foreach($records as $rec) { 01378 $recList[] = array($tN,$rec); 01379 } 01380 } 01381 01382 /** 01383 * Render a single item in a subelement list into a table row: 01384 * 01385 * @param array Table rows, passed by reference 01386 * @param string Table name 01387 * @param integer Page uid for which the subelements are selected/shown 01388 * @param array Row of element in list 01389 * @param integer The uid of the online version of $uid. If zero it means we are drawing a row for the online version itself while a value means we are drawing display for an offline version. 01390 * @param integer Mode of icon display: 0=not the last, 1= is the last in list (make joinbottom icon then), 2=do not shown icons are all (for pages from the page tree already rendered) 01391 * @param string Prefix HTML data (icons for tree rendering) 01392 * @return void (Content accumulated in $tCell!) 01393 */ 01394 function subElements_renderItem(&$tCell,$tN,$uid,$rec,$origId,$iconMode,$HTMLdata) { 01395 global $TCA; 01396 01397 // Initialize: 01398 $origUidFields = $TCA[$tN]['ctrl']['origUid']; 01399 $diffCode = ''; 01400 01401 if ($origUidFields) { // If there is a field for this table with original uids we will use that to connect records: 01402 if (!$origId) { // In case we are displaying the online originals: 01403 $this->targets['orig_'.$uid.'_'.$tN.'_'.$rec['uid']] = $rec; // Build up target array (important that 01404 $tdParams = ' id="orig_'.$uid.'_'.$tN.'_'.$rec['uid'].'" class="typo3-ver"'; // Setting ID of the table row 01405 } else { // Version branch: 01406 if ($this->targets['orig_'.$origId.'_'.$tN.'_'.$rec[$origUidFields]]) { // If there IS a corresponding original record...: 01407 01408 // Prepare Table row parameters: 01409 $tdParams = ' onmouseover="hlSubelements(\''.$origId.'_'.$tN.'_'.$rec[$origUidFields].'\', \''.$uid.'_'.$tN.'_'.$rec[$origUidFields].'\', 1, '.($this->MOD_SETTINGS['diff']==2?1:0).');"'. 01410 ' onmouseout="hlSubelements(\''.$origId.'_'.$tN.'_'.$rec[$origUidFields].'\', \''.$uid.'_'.$tN.'_'.$rec[$origUidFields].'\', 0, '.($this->MOD_SETTINGS['diff']==2?1:0).');"'. 01411 ' id="ver_'.$uid.'_'.$tN.'_'.$rec[$origUidFields].'" class="typo3-ver"'; 01412 01413 // Create diff view: 01414 if ($this->MOD_SETTINGS['diff']) { 01415 list($diffHTML,$diffPct) = $this->createDiffView($tN, $rec, $this->targets['orig_'.$origId.'_'.$tN.'_'.$rec[$origUidFields]]); 01416 01417 if ($this->MOD_SETTINGS['diff']==2) { 01418 $diffCode = 01419 ($diffPct ? '<span class="nobr">'.$diffPct.'% change</span>' : '-'). 01420 '<div style="visibility: hidden; position: absolute;" id="diff_'.$uid.'_'.$tN.'_'.$rec[$origUidFields].'" class="diffLayer">'. 01421 $diffHTML. 01422 '</div>'; 01423 } else { 01424 $diffCode = 01425 ($diffPct<0 ? $GLOBALS['LANG']->getLL('notAvailable') : ($diffPct ? $diffPct . '% ' . $GLOBALS['LANG']->getLL('change') : '')). 01426 $diffHTML; 01427 } 01428 } 01429 01430 // Unsetting the target fields allows us to mark all originals without a version in the subtree (see ->markupNewOriginals()) 01431 unset($this->targets['orig_'.$origId.'_'.$tN.'_'.$rec[$origUidFields]]); 01432 } else { // No original record, so must be new: 01433 $tdParams = ' class="typo3-ver-new"'; 01434 } 01435 } 01436 } else { // If no original uid column is supported for this table we are forced NOT to display any diff or highlighting. 01437 $tdParams = ' class="typo3-ver-noComp"'; 01438 } 01439 01440 // Compile the cell: 01441 $tCell[] = ' 01442 <tr'.$tdParams.'> 01443 <td class="iconTitle">'. 01444 $HTMLdata. 01445 ($iconMode < 2 ? 01446 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/ol/join'.($iconMode ? 'bottom' : '').'.gif','width="18" height="16"').' alt="" />'. 01447 t3lib_iconWorks::getSpriteIconForRecord($tN, $rec) : ''). 01448 t3lib_BEfunc::getRecordTitle($tN, $rec, TRUE). 01449 '</td> 01450 <td class="cmdCell">'. 01451 $this->displayWorkspaceOverview_commandLinksSub($tN,$rec,$origId). 01452 '</td>'.($origId ? '<td class="diffCell">'. 01453 $diffCode. 01454 '</td>':'').' 01455 </tr>'; 01456 } 01457 01458 /** 01459 * JavaScript code to mark up new records that are online (in sub element lists) 01460 * 01461 * @return string HTML javascript section 01462 */ 01463 function markupNewOriginals() { 01464 01465 if (count($this->targets)) { 01466 $scriptCode = ''; 01467 foreach($this->targets as $key => $rec) { 01468 $scriptCode.=' 01469 document.getElementById(\''.$key.'\').attributes.getNamedItem("class").nodeValue = \'typo3-ver-new\'; 01470 '; 01471 } 01472 01473 return $this->doc->wrapScriptTags($scriptCode); 01474 } 01475 } 01476 01477 /** 01478 * Create visual difference view of two records. Using t3lib_diff library 01479 * 01480 * @param string Table name 01481 * @param array New version record (green) 01482 * @param array Old version record (red) 01483 * @return array Array with two keys (0/1) with HTML content / percentage integer (if -1, then it means N/A) indicating amount of change 01484 */ 01485 function createDiffView($table, $diff_1_record, $diff_2_record) { 01486 global $TCA; 01487 01488 // Initialize: 01489 $pctChange = 'N/A'; 01490 01491 // Check that records are arrays: 01492 if (is_array($diff_1_record) && is_array($diff_2_record)) { 01493 01494 // Load full table description and initialize diff-object: 01495 t3lib_div::loadTCA($table); 01496 $t3lib_diff_Obj = t3lib_div::makeInstance('t3lib_diff'); 01497 01498 // Add header row: 01499 $tRows = array(); 01500 $tRows[] = ' 01501 <tr class="bgColor5 tableheader"> 01502 <td>' . $GLOBALS['LANG']->getLL('fieldname') . ':</td> 01503 <td width="98%" nowrap="nowrap">' . $GLOBALS['LANG']->getLL('coloredDiffView') . ':</td> 01504 </tr> 01505 '; 01506 01507 // Initialize variables to pick up string lengths in: 01508 $allStrLen = 0; 01509 $diffStrLen = 0; 01510 01511 // Traversing the first record and process all fields which are editable: 01512 foreach($diff_1_record as $fN => $fV) { 01513 if ($TCA[$table]['columns'][$fN] && $TCA[$table]['columns'][$fN]['config']['type']!='passthrough' && !t3lib_div::inList('t3ver_label',$fN)) { 01514 01515 // Check if it is files: 01516 $isFiles = FALSE; 01517 if (strcmp(trim($diff_1_record[$fN]),trim($diff_2_record[$fN])) && 01518 $TCA[$table]['columns'][$fN]['config']['type']=='group' && 01519 $TCA[$table]['columns'][$fN]['config']['internal_type']=='file') { 01520 01521 // Initialize: 01522 $uploadFolder = $TCA[$table]['columns'][$fN]['config']['uploadfolder']; 01523 $files1 = array_flip(t3lib_div::trimExplode(',', $diff_1_record[$fN],1)); 01524 $files2 = array_flip(t3lib_div::trimExplode(',', $diff_2_record[$fN],1)); 01525 01526 // Traverse filenames and read their md5 sum: 01527 foreach($files1 as $filename => $tmp) { 01528 $files1[$filename] = @is_file(PATH_site.$uploadFolder.'/'.$filename) ? md5(t3lib_div::getUrl(PATH_site.$uploadFolder.'/'.$filename)) : $filename; 01529 } 01530 foreach($files2 as $filename => $tmp) { 01531 $files2[$filename] = @is_file(PATH_site.$uploadFolder.'/'.$filename) ? md5(t3lib_div::getUrl(PATH_site.$uploadFolder.'/'.$filename)) : $filename; 01532 } 01533 01534 // Implode MD5 sums and set flag: 01535 $diff_1_record[$fN] = implode(' ',$files1); 01536 $diff_2_record[$fN] = implode(' ',$files2); 01537 $isFiles = TRUE; 01538 } 01539 01540 // If there is a change of value: 01541 if (strcmp(trim($diff_1_record[$fN]),trim($diff_2_record[$fN]))) { 01542 01543 01544 // Get the best visual presentation of the value and present that: 01545 $val1 = t3lib_BEfunc::getProcessedValue($table,$fN,$diff_2_record[$fN],0,1); 01546 $val2 = t3lib_BEfunc::getProcessedValue($table,$fN,$diff_1_record[$fN],0,1); 01547 01548 // Make diff result and record string lenghts: 01549 $diffres = $t3lib_diff_Obj->makeDiffDisplay($val1,$val2,$isFiles?'div':'span'); 01550 $diffStrLen+= $t3lib_diff_Obj->differenceLgd; 01551 $allStrLen+= strlen($val1.$val2); 01552 01553 // If the compared values were files, substituted MD5 hashes: 01554 if ($isFiles) { 01555 $allFiles = array_merge($files1,$files2); 01556 foreach($allFiles as $filename => $token) { 01557 if (strlen($token)==32 && strstr($diffres,$token)) { 01558 $filename = 01559 t3lib_BEfunc::thumbCode(array($fN=>$filename),$table,$fN,$this->doc->backPath). 01560 $filename; 01561 $diffres = str_replace($token,$filename,$diffres); 01562 } 01563 } 01564 } 01565 01566 // Add table row with result: 01567 $tRows[] = ' 01568 <tr class="bgColor4"> 01569 <td>'.htmlspecialchars($GLOBALS['LANG']->sL(t3lib_BEfunc::getItemLabel($table,$fN))).'</td> 01570 <td width="98%">'.$diffres.'</td> 01571 </tr> 01572 '; 01573 } else { 01574 // Add string lengths even if value matched - in this was the change percentage is not high if only a single field is changed: 01575 $allStrLen+=strlen($diff_1_record[$fN].$diff_2_record[$fN]); 01576 } 01577 } 01578 } 01579 01580 // Calculate final change percentage: 01581 $pctChange = $allStrLen ? ceil($diffStrLen*100/$allStrLen) : -1; 01582 01583 // Create visual representation of result: 01584 if (count($tRows)>1) { 01585 $content.= '<table border="0" cellpadding="1" cellspacing="1" class="diffTable">'.implode('',$tRows).'</table>'; 01586 } else { 01587 $content.= '<span class="nobr">'.$this->doc->icons(1) . $GLOBALS['LANG']->getLL('completeMatch') . '</span>'; 01588 } 01589 } else $content.= $this->doc->icons(3) . $GLOBALS['LANG']->getLL('errorRecordsNotFound'); 01590 01591 // Return value: 01592 return array($content,$pctChange); 01593 } 01594 01595 /** 01596 * Links to stage change of a version 01597 * 01598 * @param string Table name 01599 * @param array Offline record (version) 01600 * @return string HTML content, mainly link tags and images. 01601 */ 01602 function displayWorkspaceOverview_stageCmd($table,&$rec_off) { 01603 #debug($rec_off['t3ver_stage']); 01604 switch((int)$rec_off['t3ver_stage']) { 01605 case 0: 01606 $sId = 1; 01607 $sLabel = $GLOBALS['LANG']->getLL('editing'); 01608 $color = '#666666'; 01609 $label = $GLOBALS['LANG']->getLL('commentForReviewer'); 01610 $titleAttrib = $GLOBALS['LANG']->getLL('sendToReview'); 01611 break; 01612 case 1: 01613 $sId = 10; 01614 $sLabel = $GLOBALS['LANG']->getLL('review'); 01615 $color = '#6666cc'; 01616 $label = $GLOBALS['LANG']->getLL('commentForPublisher'); 01617 $titleAttrib = $GLOBALS['LANG']->getLL('approveForPublishing'); 01618 break; 01619 case 10: 01620 $sLabel = $GLOBALS['LANG']->getLL('publish'); 01621 $color = '#66cc66'; 01622 break; 01623 case -1: 01624 $sLabel = $this->doc->icons(2) . $GLOBALS['LANG']->getLL('rejected'); 01625 $sId = 0; 01626 $color = '#ff0000'; 01627 $label = $GLOBALS['LANG']->getLL('comment'); 01628 $titleAttrib = $GLOBALS['LANG']->getLL('resetStage'); 01629 break; 01630 default: 01631 $sLabel = $GLOBALS['LANG']->getLL('undefined'); 01632 $sId = 0; 01633 $color = ''; 01634 break; 01635 } 01636 #debug($sId); 01637 01638 $raiseOk = !$GLOBALS['BE_USER']->workspaceCannotEditOfflineVersion($table,$rec_off); 01639 01640 if ($raiseOk && $rec_off['t3ver_stage']!=-1) { 01641 $onClick = 'var commentTxt=window.prompt("' . $GLOBALS['LANG']->getLL('rejectExplain') . '",""); 01642 if (commentTxt!=null) {window.location.href="'.$this->doc->issueCommand( 01643 '&cmd['.$table.']['.$rec_off['uid'].'][version][action]=setStage'. 01644 '&cmd['.$table.']['.$rec_off['uid'].'][version][stageId]=-1' 01645 ).'&cmd['.$table.']['.$rec_off['uid'].'][version][comment]="+escape(commentTxt);}'. 01646 ' return false;'; 01647 // Reject: 01648 $actionLinks.= 01649 '<a href="#" onclick="'.htmlspecialchars($onClick).'" title="' . $GLOBALS['LANG']->getLL('reject', TRUE) . '">'. 01650 t3lib_iconWorks::getSpriteIcon('actions-move-down') . 01651 '</a>'; 01652 } else { 01653 // Reject: 01654 $actionLinks.= 01655 '<img src="'.$this->doc->backPath.'gfx/clear.gif" width="14" height="14" alt="" align="top" title="" />'; 01656 } 01657 01658 $actionLinks.= '<span style="background-color: '.$color.'; color: white;">'.$sLabel.'</span>'; 01659 01660 // Raise 01661 if ($raiseOk) { 01662 $onClick = 'var commentTxt=window.prompt("'.$label.'",""); 01663 if (commentTxt!=null) {window.location.href="'.$this->doc->issueCommand( 01664 '&cmd['.$table.']['.$rec_off['uid'].'][version][action]=setStage'. 01665 '&cmd['.$table.']['.$rec_off['uid'].'][version][stageId]='.$sId 01666 ).'&cmd['.$table.']['.$rec_off['uid'].'][version][comment]="+escape(commentTxt);}'. 01667 ' return false;'; 01668 if ($rec_off['t3ver_stage']!=10) { 01669 $actionLinks.= 01670 '<a href="#" onclick="'.htmlspecialchars($onClick).'" title="' . htmlspecialchars($titleAttrib) . '">' . 01671 t3lib_iconWorks::getSpriteIcon('actions-move-up') . 01672 '</a>'; 01673 01674 $this->stageIndex[$sId][$table][] = $rec_off['uid']; 01675 $this->recIndex[$table][$rec_off['uid']] = $sId; 01676 } 01677 } 01678 return $actionLinks; 01679 } 01680 01681 /** 01682 * Links to publishing etc of a version 01683 * 01684 * @param string Table name 01685 * @param array Online record 01686 * @param array Offline record (version) 01687 * @param string Swap type, "branch", "page" or "element" 01688 * @return string HTML content, mainly link tags and images. 01689 */ 01690 function displayWorkspaceOverview_commandLinks($table,&$rec_on,&$rec_off,$vType) { 01691 if ($this->publishAccess && (!($GLOBALS['BE_USER']->workspaceRec['publish_access']&1) || (int)$rec_off['t3ver_stage']===-10)) { 01692 $actionLinks = 01693 '<a href="'.htmlspecialchars($this->doc->issueCommand( 01694 '&cmd['.$table.']['.$rec_on['uid'].'][version][action]=swap'. 01695 '&cmd['.$table.']['.$rec_on['uid'].'][version][swapWith]='.$rec_off['uid'] 01696 )).'" title="' . $GLOBALS['LANG']->getLL('publish', TRUE) . '">'. 01697 t3lib_iconWorks::getSpriteIcon('actions-version-swap-version') . 01698 '</a>'; 01699 if ($GLOBALS['BE_USER']->workspaceSwapAccess()) { 01700 $actionLinks.= 01701 '<a href="'.htmlspecialchars($this->doc->issueCommand( 01702 '&cmd['.$table.']['.$rec_on['uid'].'][version][action]=swap'. 01703 '&cmd['.$table.']['.$rec_on['uid'].'][version][swapWith]='.$rec_off['uid']. 01704 '&cmd['.$table.']['.$rec_on['uid'].'][version][swapIntoWS]=1' 01705 )).'" title="' . $GLOBALS['LANG']->getLL('swap', TRUE) . '">'. 01706 t3lib_iconWorks::getSpriteIcon('actions-version-swap-workspace') . 01707 '</a>'; 01708 } 01709 } 01710 01711 if (!$GLOBALS['BE_USER']->workspaceCannotEditOfflineVersion($table,$rec_off)) { 01712 // Release 01713 $actionLinks.= 01714 '<a href="'.htmlspecialchars($this->doc->issueCommand('&cmd['.$table.']['.$rec_off['uid'].'][version][action]=clearWSID')).'" onclick="return confirm(\'' . $GLOBALS['LANG']->getLL('removeFromWorkspace', TRUE) . '?\');" title="' . $GLOBALS['LANG']->getLL('removeFromWorkspace', TRUE) . '">'. 01715 t3lib_iconWorks::getSpriteIcon('actions-version-document-remove') . 01716 '</a>'; 01717 01718 // Edit 01719 if ($table==='pages' && $vType!=='element') { 01720 $tempUid = ($vType==='branch' || $GLOBALS['BE_USER']->workspace===0 ? $rec_off['uid'] : $rec_on['uid']); 01721 $actionLinks.= 01722 '<a href="#" onclick="top.loadEditId('.$tempUid.');top.goToModule(\''.$this->pageModule.'\'); return false;" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_user_ws.xml:img_title_edit_page', TRUE) . '">'. 01723 t3lib_iconWorks::getSpriteIcon('actions-version-page-open') . 01724 '</a>'; 01725 } else { 01726 $params = '&edit['.$table.']['.$rec_off['uid'].']=edit'; 01727 $actionLinks.= 01728 '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->doc->backPath)).'" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_user_ws.xml:img_title_edit_element', TRUE). '">'. 01729 t3lib_iconWorks::getSpriteIcon('actions-document-open') . 01730 '</a>'; 01731 } 01732 } 01733 01734 // History/Log 01735 $actionLinks.= 01736 '<a href="'.htmlspecialchars($this->doc->backPath.'show_rechis.php?element='.rawurlencode($table.':'.$rec_off['uid']).'&returnUrl='.rawurlencode($this->REQUEST_URI)).'" title="' . $GLOBALS['LANG']->getLL('showLog', TRUE) . '">'. 01737 t3lib_iconWorks::getSpriteIcon('actions-document-history-open') . 01738 '</a>'; 01739 01740 // View 01741 if ($table==='pages') { 01742 $tempUid = ($vType==='branch' || $GLOBALS['BE_USER']->workspace===0 ? $rec_off['uid'] : $rec_on['uid']); 01743 $actionLinks.= 01744 '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($tempUid,$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($tempUid))).'">'. 01745 t3lib_iconWorks::getSpriteIcon('actions-document-view') . 01746 '</a>'; 01747 } 01748 01749 return $actionLinks; 01750 } 01751 01752 /** 01753 * Links to publishing etc of a version 01754 * 01755 * @param string Table name 01756 * @param array Record 01757 * @param integer The uid of the online version of $uid. If zero it means we are drawing a row for the online version itself while a value means we are drawing display for an offline version. 01758 * @return string HTML content, mainly link tags and images. 01759 */ 01760 function displayWorkspaceOverview_commandLinksSub($table,$rec,$origId) { 01761 $uid = $rec['uid']; 01762 if ($origId || $GLOBALS['BE_USER']->workspace===0) { 01763 if (!$GLOBALS['BE_USER']->workspaceCannotEditRecord($table,$rec)) { 01764 // Edit 01765 if ($table==='pages') { 01766 $actionLinks.= 01767 '<a href="#" onclick="top.loadEditId('.$uid.');top.goToModule(\''.$this->pageModule.'\'); return false;" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_user_ws.xml:img_title_edit_page', TRUE) . '">'. 01768 t3lib_iconWorks::getSpriteIcon('apps-version-page-open') . 01769 '</a>'; 01770 } else { 01771 $params = '&edit['.$table.']['.$uid.']=edit'; 01772 $actionLinks.= 01773 '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->doc->backPath)).'" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_user_ws.xml:img_title_edit_element', TRUE) . '">'. 01774 t3lib_iconWorks::getSpriteIcon('actions-document-open') . 01775 '</a>'; 01776 } 01777 } 01778 01779 // History/Log 01780 $actionLinks.= 01781 '<a href="'.htmlspecialchars($this->doc->backPath.'show_rechis.php?element='.rawurlencode($table.':'.$uid).'&returnUrl='.rawurlencode($this->REQUEST_URI)).'" title="' . $GLOBALS['LANG']->getLL('showLog', TRUE) . '">'. 01782 t3lib_iconWorks::getSpriteIcon('actions-document-history-open') . 01783 '</a>'; 01784 } 01785 01786 // View 01787 if ($table==='pages') { 01788 $actionLinks.= 01789 '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($uid,$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($uid))).'">'. 01790 t3lib_iconWorks::getSpriteIcon('actions-document-view') . 01791 '</a>'; 01792 } 01793 01794 return $actionLinks; 01795 } 01796 01797 01798 01799 01800 01801 01802 01803 01804 01805 /********************************** 01806 * 01807 * Processing 01808 * 01809 **********************************/ 01810 01811 /** 01812 * Will publish workspace if buttons are pressed 01813 * 01814 * @return void 01815 */ 01816 function publishAction() { 01817 01818 // If "Publish" or "Swap" buttons are pressed: 01819 if (t3lib_div::_POST('_publish') || t3lib_div::_POST('_swap')) { 01820 01821 if ($this->table==='pages') { // Making sure ->uid is a page ID! 01822 // Initialize workspace object and request all pending versions: 01823 $wslibObj = t3lib_div::makeInstance('wslib'); 01824 $cmd = $wslibObj->getCmdArrayForPublishWS($GLOBALS['BE_USER']->workspace, t3lib_div::_POST('_swap'),$this->uid); 01825 01826 // Execute the commands: 01827 $tce = t3lib_div::makeInstance('t3lib_TCEmain'); 01828 $tce->stripslashes_values = 0; 01829 $tce->start(array(), $cmd); 01830 $tce->process_cmdmap(); 01831 01832 t3lib_BEfunc::setUpdateSignal('updatePageTree'); 01833 01834 return $tce->errorLog; 01835 } 01836 } 01837 } 01838 } 01839 01840 01841 01842 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/version/cm1/index.php'])) { 01843 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/version/cm1/index.php']); 01844 } 01845 01846 01847 01848 01849 // Make instance: 01850 $SOBE = t3lib_div::makeInstance('tx_version_cm1'); 01851 $SOBE->init(); 01852 01853 01854 $SOBE->main(); 01855 $SOBE->printContent(); 01856 01857 ?>
1.8.0