PageRenderTime 126ms CodeModel.GetById 32ms app.highlight 72ms RepoModel.GetById 1ms app.codeStats 1ms

/typo3/sysext/version/cm1/index.php

https://bitbucket.org/linxpinx/mercurial
PHP | 1855 lines | 1156 code | 271 blank | 428 comment | 185 complexity | f91265a1a19e7fa5f7fc45f6337d3c15 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2/***************************************************************
   3*  Copyright notice
   4*
   5*  (c) 2004-2010 Kasper Skaarhoj (kasperYYYY@typo3.com)
   6*  All rights reserved
   7*
   8*  This script is part of the TYPO3 project. The TYPO3 project is
   9*  free software; you can redistribute it and/or modify
  10*  it under the terms of the GNU General Public License as published by
  11*  the Free Software Foundation; either version 2 of the License, or
  12*  (at your option) any later version.
  13*
  14*  The GNU General Public License can be found at
  15*  http://www.gnu.org/copyleft/gpl.html.
  16*
  17*  This script is distributed in the hope that it will be useful,
  18*  but WITHOUT ANY WARRANTY; without even the implied warranty of
  19*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20*  GNU General Public License for more details.
  21*
  22*  This copyright notice MUST APPEAR in all copies of the script!
  23***************************************************************/
  24/**
  25 * Versioning module
  26 *
  27 * @author	Kasper Skaarhoj <kasperYYYY@typo3.com>
  28 */
  29/**
  30 * [CLASS/FUNCTION INDEX of SCRIPT]
  31 *
  32 *
  33 *
  34 *  102: class tx_version_cm1 extends t3lib_SCbase
  35 *
  36 *              SECTION: Standard module initialization
  37 *  138:     function menuConfig()
  38 *  175:     function main()
  39 *  236:     function jumpToUrl(URL)
  40 *  296:     function printContent()
  41 *
  42 *              SECTION: Versioning management
  43 *  322:     function versioningMgm()
  44 *  485:     function pageSubContent($pid,$c=0)
  45 *  539:     function lookForOwnVersions($table,$uid)
  46 *  556:     function adminLinks($table,$row)
  47 *
  48 *              SECTION: Workspace management
  49 *  628:     function workspaceMgm()
  50 *  688:     function displayWorkspaceOverview()
  51 *  758:     function displayWorkspaceOverview_list($pArray)
  52 *  923:     function displayWorkspaceOverview_setInPageArray(&$pArray,$table,$row)
  53 *  936:     function displayWorkspaceOverview_allStageCmd()
  54 *
  55 *              SECTION: Helper functions (REDUNDANT FROM user/ws/index.php - someone could refactor this...)
  56 *  986:     function formatVerId($verId)
  57 *  996:     function formatWorkspace($wsid)
  58 * 1023:     function formatCount($count)
  59 * 1050:     function versionsInOtherWS($table,$uid)
  60 * 1080:     function showStageChangeLog($table,$id,$stageCommands)
  61 * 1129:     function subElements($uid,$treeLevel,$origId=0)
  62 * 1232:     function subElements_getNonPageRecords($tN, $uid, &$recList)
  63 * 1262:     function subElements_renderItem(&$tCell,$tN,$uid,$rec,$origId,$iconMode,$HTMLdata)
  64 * 1331:     function markupNewOriginals()
  65 * 1353:     function createDiffView($table, $diff_1_record, $diff_2_record)
  66 * 1470:     function displayWorkspaceOverview_stageCmd($table,&$rec_off)
  67 * 1557:     function displayWorkspaceOverview_commandLinks($table,&$rec_on,&$rec_off,$vType)
  68 * 1627:     function displayWorkspaceOverview_commandLinksSub($table,$rec,$origId)
  69 *
  70 *              SECTION: Processing
  71 * 1683:     function publishAction()
  72 *
  73 * TOTAL FUNCTIONS: 27
  74 * (This index is automatically created/updated by the extension "extdeveval")
  75 *
  76 */
  77
  78
  79	// DEFAULT initialization of a module [BEGIN]
  80unset($MCONF);
  81require ('conf.php');
  82require ($BACK_PATH.'init.php');
  83require ($BACK_PATH.'template.php');
  84$LANG->includeLLFile('EXT:version/locallang.xml');
  85	// DEFAULT initialization of a module [END]
  86
  87require_once(PATH_typo3.'mod/user/ws/class.wslib.php');
  88
  89
  90
  91/**
  92 * Versioning module, including workspace management
  93 *
  94 * @author	Kasper Skaarhoj <kasperYYYY@typo3.com>
  95 * @package TYPO3
  96 * @subpackage core
  97 */
  98class tx_version_cm1 extends t3lib_SCbase {
  99
 100		// Default variables for backend modules
 101	var $MCONF = array();				// Module configuration
 102	var $MOD_MENU = array();			// Module menu items
 103	var $MOD_SETTINGS = array();		// Module session settings
 104
 105	/**
 106	 * document template object
 107	 *
 108	 * @var mediumDoc
 109	 */
 110	var $doc;
 111	var $content;						// Accumulated content
 112
 113
 114		// Internal:
 115	var $showWorkspaceCol = 0;
 116	var $formatWorkspace_cache = array();
 117	var $formatCount_cache = array();
 118	var $targets = array();		// Accumulation of online targets.
 119	var $pageModule = '';			// Name of page module
 120	var $publishAccess = FALSE;
 121	var $be_user_Array = array();
 122	var $stageIndex = array();
 123	var $recIndex = array();
 124	protected $showDraftWorkspace = FALSE; // Determines whether to show the dummy draft workspace
 125
 126
 127
 128
 129
 130
 131	/*********************************
 132	 *
 133	 * Standard module initialization
 134	 *
 135	 *********************************/
 136
 137	/**
 138	 * Initialize menu configuration
 139	 *
 140	 * @return	void
 141	 */
 142	function menuConfig()	{
 143
 144			// fetches the configuration of the version extension
 145		$versionExtconf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['version']);
 146			// show draft workspace only if enabled in the version extensions config
 147		if($versionExtconf['showDraftWorkspace']) {
 148			$this->showDraftWorkspace = TRUE;
 149		}
 150
 151			// Menu items:
 152		$this->MOD_MENU = array(
 153			'filter' => array(
 154				1 => $GLOBALS['LANG']->getLL('filter_drafts'),
 155				2 => $GLOBALS['LANG']->getLL('filter_archive'),
 156				0 => $GLOBALS['LANG']->getLL('filter_all'),
 157			),
 158			'display' => array(
 159				0 => $GLOBALS['LANG']->getLL('liveWorkspace'),
 160				-98 => $GLOBALS['LANG']->getLL('draftWorkspaces'),
 161				-99 => $GLOBALS['LANG']->getLL('filter_all'),
 162			),
 163			'diff' => ''
 164		);
 165		
 166		if($this->showDraftWorkspace === TRUE) {
 167			$this->MOD_MENU['display'][-1] = $GLOBALS['LANG']->getLL('defaultDraft');
 168		}
 169
 170			// Add workspaces:
 171		if ($GLOBALS['BE_USER']->workspace===0)	{	// Spend time on this only in online workspace because it might take time:
 172			$workspaces = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,title,adminusers,members,reviewers','sys_workspace','pid=0'.t3lib_BEfunc::deleteClause('sys_workspace'),'','title');
 173			foreach($workspaces as $rec)	{
 174				if ($GLOBALS['BE_USER']->checkWorkspace($rec))	{
 175					$this->MOD_MENU['display'][$rec['uid']] = '['.$rec['uid'].'] '.$rec['title'];
 176				}
 177			}
 178		}
 179
 180			// CLEANSE SETTINGS
 181		$this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name'], 'ses');
 182	}
 183
 184	/**
 185	 * Main function of the module. Write the content to $this->content
 186	 *
 187	 * @return	void
 188	 */
 189	function main()	{
 190		global $BE_USER,$LANG,$BACK_PATH,$TCA_DESCR,$TCA,$CLIENT,$TYPO3_CONF_VARS;
 191		
 192			// Template markers
 193		$markers = array(
 194			'CSH' => '',
 195			'FUNC_MENU' => '',
 196			'WS_MENU' => '',
 197			'CONTENT' => ''
 198		);
 199
 200			// Setting module configuration:
 201		$this->MCONF = $GLOBALS['MCONF'];
 202
 203		$this->REQUEST_URI = str_replace('&sendToReview=1','',t3lib_div::getIndpEnv('REQUEST_URI'));
 204
 205			// Draw the header.
 206		$this->doc = t3lib_div::makeInstance('template');
 207		$this->doc->backPath = $BACK_PATH;
 208		$this->doc->setModuleTemplate('templates/version.html');
 209
 210	        // Add styles
 211		$this->doc->inDocStylesArray[$GLOBALS['MCONF']['name']] = '
 212.version-diff-1 { background-color: green; }
 213.version-diff-2 { background-color: red; }
 214';
 215
 216			// Setting up the context sensitive menu:
 217		$this->doc->getContextMenuCode();
 218
 219			// Getting input data:
 220		$this->id = intval(t3lib_div::_GP('id'));		// Page id. If set, indicates activation from Web>Versioning module
 221		if (!$this->id)	{
 222			$this->uid = intval(t3lib_div::_GP('uid'));		// Record uid. Goes with table name to indicate specific record
 223			$this->table = t3lib_div::_GP('table');			// Record table. Goes with uid to indicate specific record
 224		} else {
 225			$this->uid = $this->id;
 226			$this->table = 'pages';
 227		}
 228		$this->details = t3lib_div::_GP('details');		// Page id. If set, indicates activation from Web>Versioning module
 229		$this->diffOnly = t3lib_div::_GP('diffOnly');		// Flag. If set, shows only the offline version and with diff-view
 230
 231			// Force this setting:
 232		$this->MOD_SETTINGS['expandSubElements'] = TRUE;
 233		$this->MOD_SETTINGS['diff'] = $this->details || $this->MOD_SETTINGS['diff']?1:0;
 234
 235			// Reading the record:
 236		$record = t3lib_BEfunc::getRecord($this->table,$this->uid);
 237		if ($record['pid']==-1)	{
 238			$record = t3lib_BEfunc::getRecord($this->table,$record['t3ver_oid']);
 239		}
 240
 241		$this->recordFound = is_array($record);
 242
 243		$pidValue = $this->table==='pages' ? $this->uid : $record['pid'];
 244
 245			// Checking access etc.
 246		if ($this->recordFound && $TCA[$this->table]['ctrl']['versioningWS'])	{
 247			$this->doc->form='<form action="" method="post">';
 248			$this->uid = $record['uid']; 	// Might have changed if new live record was found!
 249
 250				// Access check!
 251				// The page will show only if there is a valid page and if this page may be viewed by the user
 252			$this->pageinfo = t3lib_BEfunc::readPageAccess($pidValue,$this->perms_clause);
 253			$access = is_array($this->pageinfo) ? 1 : 0;
 254
 255			if (($pidValue && $access) || ($BE_USER->user['admin'] && !$pidValue))	{
 256
 257					// JavaScript
 258				$this->doc->JScode.= '
 259					<script language="javascript" type="text/javascript">
 260						script_ended = 0;
 261						function jumpToUrl(URL)	{
 262							window.location.href = URL;
 263						}
 264
 265						function hlSubelements(origId, verId, over, diffLayer)	{	//
 266							if (over)	{
 267								document.getElementById(\'orig_\'+origId).attributes.getNamedItem("class").nodeValue = \'typo3-ver-hl\';
 268								document.getElementById(\'ver_\'+verId).attributes.getNamedItem("class").nodeValue = \'typo3-ver-hl\';
 269								if (diffLayer)	{
 270									document.getElementById(\'diff_\'+verId).style.visibility = \'visible\';
 271								}
 272							} else {
 273								document.getElementById(\'orig_\'+origId).attributes.getNamedItem("class").nodeValue = \'typo3-ver\';
 274								document.getElementById(\'ver_\'+verId).attributes.getNamedItem("class").nodeValue = \'typo3-ver\';
 275								if (diffLayer)	{
 276									document.getElementById(\'diff_\'+verId).style.visibility = \'hidden\';
 277								}
 278							}
 279						}
 280					</script>
 281				';
 282
 283					// If another page module was specified, replace the default Page module with the new one
 284				$newPageModule = trim($BE_USER->getTSConfigVal('options.overridePageModule'));
 285				$this->pageModule = t3lib_BEfunc::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
 286
 287					// Setting publish access permission for workspace:
 288				$this->publishAccess = $BE_USER->workspacePublishAccess($BE_USER->workspace);
 289
 290					// Render content:
 291				if ($this->id)	{
 292					$this->workspaceMgm();
 293				} else {
 294					$this->versioningMgm();
 295				}
 296			}
 297
 298			$this->content.=$this->doc->spacer(10);
 299
 300				// Setting up the buttons and markers for docheader
 301			$docHeaderButtons = $this->getButtons();
 302			$markers['CSH'] = $docHeaderButtons['csh'];
 303			$markers['FUNC_MENU'] = t3lib_BEfunc::getFuncMenu($this->id, 'SET[function]', $this->MOD_SETTINGS['function'], $this->MOD_MENU['function']);
 304			$markers['WS_MENU'] = $this->workspaceMenu();
 305			$markers['CONTENT'] = $this->content;
 306		} else {
 307				// If no access or id value, create empty document
 308			$this->content = $this->doc->section($LANG->getLL('clickAPage_header'), $LANG->getLL('clickAPage_content'), 0, 1);
 309
 310				// Setting up the buttons and markers for docheader
 311			$docHeaderButtons = $this->getButtons();
 312			$markers['CONTENT'] = $this->content;
 313		}
 314			// Build the <body> for the module
 315		$this->content = $this->doc->startPage($LANG->getLL('title'));
 316		$this->content.= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
 317		$this->content.= $this->doc->endPage();
 318		$this->content = $this->doc->insertStylesAndJS($this->content);
 319	}
 320
 321	/**
 322	 * Outputs accumulated module content to browser.
 323	 *
 324	 * @return	void
 325	 */
 326	function printContent()	{
 327		echo $this->content;
 328	}
 329
 330	/**
 331	 * Create the panel of buttons for submitting the form or otherwise perform operations.
 332	 *
 333	 * @return	array	all available buttons as an assoc. array
 334	 */
 335	protected function getButtons()	{
 336		global $TCA, $LANG, $BACK_PATH, $BE_USER;
 337
 338		$buttons = array(
 339			'csh' => '',
 340			'view' => '',
 341			'record_list' => '',
 342			'shortcut' => '',
 343		);
 344			// CSH
 345		//$buttons['csh'] = t3lib_BEfunc::cshItem('_MOD_web_txversionM1', '', $GLOBALS['BACK_PATH']);
 346
 347		if ($this->recordFound && $TCA[$this->table]['ctrl']['versioningWS']) {
 348				// View page
 349			$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) . '">' .
 350						t3lib_iconWorks::getSpriteIcon('actions-document-view') .
 351					'</a>';
 352
 353				// Shortcut
 354			if ($BE_USER->mayMakeShortcut())	{
 355				$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']);
 356			}
 357
 358				// If access to Web>List for user, then link to that module.
 359			if ($BE_USER->check('modules','web_list'))	{
 360				$href = $BACK_PATH . 'db_list.php?id=' . $this->pageinfo['uid'] . '&returnUrl=' . rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'));
 361				$buttons['record_list'] = '<a href="' . htmlspecialchars($href) . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showList', TRUE) . '">' .
 362							t3lib_iconWorks::getSpriteIcon('actions-system-list-open') .
 363						'</a>';
 364			}
 365		}
 366		return $buttons;
 367	}
 368
 369
 370
 371
 372
 373
 374
 375
 376	/******************************
 377	 *
 378	 * Versioning management
 379	 *
 380	 ******************************/
 381
 382	/**
 383	 * Management of versions for record
 384	 *
 385	 * @return	void
 386	 */
 387	function versioningMgm()	{
 388		global $TCA;
 389
 390			// Diffing:
 391		$diff_1 = t3lib_div::_POST('diff_1');
 392		$diff_2 = t3lib_div::_POST('diff_2');
 393		if (t3lib_div::_POST('do_diff'))	{
 394			$content='';
 395			$content.='<h3>' . $GLOBALS['LANG']->getLL('diffing') . ':</h3>';
 396			if ($diff_1 && $diff_2)	{
 397				$diff_1_record = t3lib_BEfunc::getRecord($this->table, $diff_1);
 398				$diff_2_record = t3lib_BEfunc::getRecord($this->table, $diff_2);
 399
 400				if (is_array($diff_1_record) && is_array($diff_2_record))	{
 401					t3lib_div::loadTCA($this->table);
 402					$t3lib_diff_Obj = t3lib_div::makeInstance('t3lib_diff');
 403
 404					$tRows=array();
 405								$tRows[] = '
 406									<tr class="bgColor5 tableheader">
 407										<td>' . $GLOBALS['LANG']->getLL('fieldname') . '</td>
 408										<td width="98%">' . $GLOBALS['LANG']->getLL('coloredDiffView') . ':</td>
 409									</tr>
 410								';
 411					foreach($diff_1_record as $fN => $fV)	{
 412						if ($TCA[$this->table]['columns'][$fN] && $TCA[$this->table]['columns'][$fN]['config']['type']!='passthrough' && !t3lib_div::inList('t3ver_label',$fN))	{
 413							if (strcmp($diff_1_record[$fN],$diff_2_record[$fN]))	{
 414
 415								$diffres = $t3lib_diff_Obj->makeDiffDisplay(
 416									t3lib_BEfunc::getProcessedValue($this->table,$fN,$diff_2_record[$fN],0,1),
 417									t3lib_BEfunc::getProcessedValue($this->table,$fN,$diff_1_record[$fN],0,1)
 418								);
 419
 420								$tRows[] = '
 421									<tr class="bgColor4">
 422										<td>'.$fN.'</td>
 423										<td width="98%">'.$diffres.'</td>
 424									</tr>
 425								';
 426							}
 427						}
 428					}
 429
 430					if (count($tRows)>1)	{
 431						$content .= '<table border="0" cellpadding="1" cellspacing="1" width="100%">' . implode('', $tRows) . '</table><br /><br />';
 432					} else {
 433						$content .= $GLOBALS['LANG']->getLL('recordsMatchesCompletely');
 434					}
 435				} else $content .= $GLOBALS['LANG']->getLL('errorRecordsNotFound');
 436			} else {
 437				$content .= $GLOBALS['LANG']->getLL('errorDiffSources');
 438			}
 439		}
 440
 441			// Element:
 442		$record = t3lib_BEfunc::getRecord($this->table,$this->uid);
 443		$recordIcon = t3lib_iconWorks::getSpriteIconForRecord($this->table, $record);
 444		$recTitle = t3lib_BEfunc::getRecordTitle($this->table,$record,TRUE);
 445
 446			// Display versions:
 447		$content.='
 448			'.$recordIcon.$recTitle.'
 449			<form name="theform" action="'.str_replace('&sendToReview=1','',$this->REQUEST_URI).'" method="post">
 450			<table border="0" cellspacing="1" cellpadding="1">';
 451			$content.='
 452				<tr class="bgColor5 tableheader">
 453					<td>&nbsp;</td>
 454					<td>&nbsp;</td>
 455					<td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_title') . '">' . $GLOBALS['LANG']->getLL('tblHeader_title') . '</td>
 456					<td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_uid') . '">' . $GLOBALS['LANG']->getLL('tblHeader_uid') . '</td>
 457					<td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_oid') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_oid') . '</td>
 458					<td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_id') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_id') . '</td>
 459					<td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_wsid') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_wsid') . '</td>
 460					<td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_state') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_state') . '</td>
 461					<td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_stage') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_stage') . '</td>
 462					<td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_count') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_count') . '</td>
 463					<td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_pid') . '">' . $GLOBALS['LANG']->getLL('tblHeader_pid') . '</td>
 464					<td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_label') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_label') . '</td>
 465					<td colspan="2"><input type="submit" name="do_diff" value="' . $GLOBALS['LANG']->getLL('diff') . '" /></td>
 466				</tr>';
 467
 468		$versions = t3lib_BEfunc::selectVersionsOfRecord($this->table, $this->uid, '*', $GLOBALS['BE_USER']->workspace);
 469		foreach($versions as $row)	{
 470			$adminLinks = $this->adminLinks($this->table,$row);
 471
 472			$content.='
 473				<tr class="' . ($row['uid'] != $this->uid ? 'bgColor4' : 'bgColor2 tableheader') . '">
 474					<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) . '">'.
 475						t3lib_iconWorks::getSpriteIcon('actions-version-swap-version') .
 476						'</a>' /* (
 477							$this->table == 'pages' ?
 478							'<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').'">'.
 479						'<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert2.gif','width="14" height="14"').' alt="" title="Publish page AND content!" />'.
 480						'</a>'.
 481							'<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').'">'.
 482						'<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert4.gif','width="14" height="14"').' alt="" title="Publish page AND content! - AND ALL SUBPAGES!" />'.
 483						'</a>' : '') */ : t3lib_iconWorks::getSpriteIcon('status-status-current', array('title' =>  $GLOBALS['LANG']->getLL('currentOnlineVersion', TRUE)))) . '</td>
 484					<td nowrap="nowrap">'.$adminLinks.'</td>
 485					<td nowrap="nowrap">'.t3lib_BEfunc::getRecordTitle($this->table,$row,TRUE).'</td>
 486					<td>'.$row['uid'].'</td>
 487					<td>'.$row['t3ver_oid'].'</td>
 488					<td>'.$row['t3ver_id'].'</td>
 489					<td>'.$row['t3ver_wsid'].'</td>
 490					<td>'.$row['t3ver_state'].'</td>
 491					<td>'.$row['t3ver_stage'].'</td>
 492					<td>'.$row['t3ver_count'].'</td>
 493					<td>'.$row['pid'].'</td>
 494					<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) . '">' .
 495							t3lib_iconWorks::getSpriteIcon('actions-document-open') .
 496						'</a>' . htmlspecialchars($row['t3ver_label']) . '</td>
 497					<td class="version-diff-1"><input type="radio" name="diff_1" value="'.$row['uid'].'"'.($diff_1==$row['uid'] ? ' checked="checked"':'').'/></td>
 498					<td class="version-diff-2"><input type="radio" name="diff_2" value="'.$row['uid'].'"'.($diff_2==$row['uid'] ? ' checked="checked"':'').'/></td>
 499				</tr>';
 500
 501				// 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;)
 502			if ($this->table == 'pages' && $row['uid']!=$this->uid)	{
 503				$sub = $this->pageSubContent($row['uid']);
 504
 505				if ($sub)	{
 506					$content.='
 507						<tr>
 508							<td></td>
 509							<td></td>
 510							<td colspan="10">'.$sub.'</td>
 511							<td colspan="2"></td>
 512						</tr>';
 513				}
 514			}
 515		}
 516		$content.='</table></form>';
 517
 518		$this->content .= $this->doc->section($GLOBALS['LANG']->getLL('title'), $content, 0, 1);
 519
 520
 521			// Create new:
 522		$content='
 523
 524			<form action="'.$this->doc->backPath.'tce_db.php" method="post">
 525			' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_label') . ': <input type="text" name="cmd[' . $this->table . '][' . $this->uid . '][version][label]" /><br />
 526			'.(($this->table == 'pages' && $GLOBALS['TYPO3_CONF_VARS']['BE']['elementVersioningOnly'] == FALSE)? '<select name="cmd['.$this->table.']['.$this->uid.'][version][treeLevels]">
 527				'.($GLOBALS['BE_USER']->workspaceVersioningTypeAccess(0) ? '<option value="0">' . $GLOBALS['LANG']->getLL('cmdPid0') . '</option>' : '').'
 528				'.($GLOBALS['BE_USER']->workspaceVersioningTypeAccess(1) ? '<option value="100">' . $GLOBALS['LANG']->getLL('cmdPid100') . '</option>' : '').'
 529				'.($GLOBALS['BE_USER']->workspaceVersioningTypeAccess(-1) ? '<option value="-1">' . $GLOBALS['LANG']->getLL('cmdPid1') . '</option>' : '').'
 530			</select>' : '').'
 531			<br /><input type="hidden" name="cmd[' . $this->table . '][' . $this->uid . '][version][action]" value="new" />
 532			<input type="hidden" name="prErr" value="1" />
 533			<input type="hidden" name="redirect" value="'.htmlspecialchars($this->REQUEST_URI).'" />
 534			<input type="submit" name="_" value="' . $GLOBALS['LANG']->getLL('createNewVersion') . '" />
 535
 536			</form>
 537
 538		';
 539
 540		$this->content.=$this->doc->spacer(15);
 541		$this->content.=$this->doc->section($GLOBALS['LANG']->getLL('createNewVersion'), $content,0,1);
 542
 543	}
 544
 545	/**
 546	 * Recursively look for children for page version with $pid
 547	 *
 548	 * @param	integer		UID of page record for which to look up sub-elements following that version
 549	 * @param	integer		Counter, do not set (limits to 100 levels)
 550	 * @return	string		Table with content if any
 551	 */
 552	function pageSubContent($pid,$c=0)	{
 553		global $TCA;
 554
 555		$tableNames = t3lib_div::removeArrayEntryByValue(array_keys($TCA),'pages');
 556		$tableNames[] = 'pages';
 557
 558		foreach($tableNames as $tN)	{
 559				// Basically list ALL tables - not only those being copied might be found!
 560			#if ($TCA[$tN]['ctrl']['versioning_followPages'] || $tN=='pages')	{
 561				$mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $tN, 'pid='.intval($pid).t3lib_BEfunc::deleteClause($tN), '', ($TCA[$tN]['ctrl']['sortby'] ? $TCA[$tN]['ctrl']['sortby'] : ''));
 562
 563				if ($GLOBALS['TYPO3_DB']->sql_num_rows($mres))	{
 564					$content.='
 565						<tr>
 566							<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>
 567						</tr>';
 568					while ($subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres))	{
 569						$ownVer = $this->lookForOwnVersions($tN,$subrow['uid']);
 570						$content.='
 571							<tr>
 572								<td>'.$this->adminLinks($tN,$subrow).'</td>
 573								<td>'.$subrow['uid'].'</td>
 574								'.($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>').'
 575								<td width="98%">'.t3lib_BEfunc::getRecordTitle($tN,$subrow,TRUE).'</td>
 576							</tr>';
 577
 578						if ($tN == 'pages' && $c<100)	{
 579							$sub = $this->pageSubContent($subrow['uid'],$c+1);
 580
 581							if ($sub)	{
 582								$content.='
 583									<tr>
 584										<td></td>
 585										<td></td>
 586										<td></td>
 587										<td width="98%">'.$sub.'</td>
 588									</tr>';
 589							}
 590						}
 591					}
 592				}
 593			#}
 594		}
 595
 596		return $content ? '<table border="1" cellpadding="1" cellspacing="0" width="100%">'.$content.'</table>' : '';
 597	}
 598
 599	/**
 600	 * Look for number of versions of a record
 601	 *
 602	 * @param	string		Table name
 603	 * @param	integer		Record uid
 604	 * @return	integer		Number of versions for record, false if none.
 605	 */
 606	function lookForOwnVersions($table,$uid)	{
 607		global $TCA;
 608
 609		$versions = t3lib_BEfunc::selectVersionsOfRecord($table, $uid, 'uid');
 610		if (is_array($versions))	{
 611			return count($versions);
 612		}
 613		return FALSE;
 614	}
 615
 616	/**
 617	 * Administrative links for a table / record
 618	 *
 619	 * @param	string		Table name
 620	 * @param	array		Record for which administrative links are generated.
 621	 * @return	string		HTML link tags.
 622	 */
 623	function adminLinks($table,$row)	{
 624		global $BE_USER;
 625
 626			// Edit link:
 627		$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) . '">'.
 628							t3lib_iconWorks::getSpriteIcon('actions-document-open') .
 629						'</a>';
 630
 631			// Delete link:
 632		$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) . '">' .
 633							t3lib_iconWorks::getSpriteIcon('actions-edit-delete') .
 634						'</a>';
 635
 636
 637
 638		if ($table == 'pages')	{
 639
 640				// If another page module was specified, replace the default Page module with the new one
 641			$newPageModule = trim($BE_USER->getTSConfigVal('options.overridePageModule'));
 642			$pageModule = t3lib_BEfunc::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
 643
 644				// Perform some acccess checks:
 645			$a_wl = $BE_USER->check('modules','web_list');
 646			$a_wp = t3lib_extMgm::isLoaded('cms') && $BE_USER->check('modules',$pageModule);
 647
 648			$adminLink.='<a href="#" onclick="top.loadEditId('.$row['uid'].');top.goToModule(\''.$pageModule.'\'); return false;">'.
 649							t3lib_iconWorks::getSpriteIcon('actions-page-open') .
 650						'</a>';
 651			$adminLink.='<a href="#" onclick="top.loadEditId('.$row['uid'].');top.goToModule(\'web_list\'); return false;">'.
 652							t3lib_iconWorks::getSpriteIcon('actions-system-list-open') .
 653						'</a>';
 654
 655				// "View page" icon is added:
 656			$adminLink.='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($row['uid'],$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($row['uid']))).'">'.
 657					t3lib_iconWorks::getSpriteIcon('actions-document-view') .
 658				'</a>';
 659		} else {
 660			if ($row['pid']==-1)	{
 661				$getVars = '&ADMCMD_vPrev['.rawurlencode($table.':'.$row['t3ver_oid']).']='.$row['uid'];
 662
 663					// "View page" icon is added:
 664				$adminLink.='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($row['_REAL_PID'],$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($row['_REAL_PID']),'','',$getVars)).'">'.
 665						t3lib_iconWorks::getSpriteIcon('actions-document-view') .
 666					'</a>';
 667			}
 668		}
 669
 670		return $adminLink;
 671	}
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683	/******************************
 684	 *
 685	 * Workspace management
 686	 *
 687	 ******************************/
 688
 689	/**
 690	 * Management of workspace for page ID
 691	 * Called when $this->id is set.
 692	 *
 693	 * @return	void
 694	 */
 695	function workspaceMgm()	{
 696
 697			// Perform workspace publishing action if buttons are pressed:
 698		$errors = $this->publishAction();
 699
 700			// Generate workspace overview:
 701		$WSoverview = $this->displayWorkspaceOverview();
 702
 703			// Buttons for publish / swap:
 704		$actionLinks = '<br />';
 705		if ($GLOBALS['BE_USER']->workspace!==0)	{
 706			if ($this->publishAccess)	{
 707				$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') : '') . '\');"/>';
 708				if ($GLOBALS['BE_USER']->workspaceSwapAccess())	{
 709					$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') : '') . '\');" />';
 710				}
 711			} else {
 712				$actionLinks.= $this->doc->icons(1) . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_user_ws.xml:no_publish_permission');
 713			}
 714		}
 715
 716		$actionLinks.= '<input type="submit" name="_" value="' . $GLOBALS['LANG']->getLL('refresh') . '" />';
 717		$actionLinks.= '<input type="submit" name="_previewLink" value="' . $GLOBALS['LANG']->getLL('previewLink') . '" />';
 718		$actionLinks.= '<input type="checkbox" class="checkbox" name="_previewLink_wholeWorkspace" id="_previewLink_wholeWorkspace" value="1" /><label for="_previewLink_wholeWorkspace">' . $GLOBALS['LANG']->getLL('allowPreviewOfWholeWorkspace') . '</label>';
 719		$actionLinks.= $this->displayWorkspaceOverview_allStageCmd();
 720
 721		if ($actionLinks || count($errors))	{
 722			$this->content .= $this->doc->section('', $actionLinks . (count($errors) ? '<h3>' . $GLOABLS['LANG']->getLL('errors') . '</h3><br />' . implode('<br />', $errors) . '<hr />' : ''), 0, 1);
 723		}
 724
 725		if (t3lib_div::_POST('_previewLink'))	{
 726			$ttlHours = intval($GLOBALS['BE_USER']->getTSConfigVal('options.workspaces.previewLinkTTLHours'));
 727			$ttlHours = ($ttlHours ? $ttlHours : 24*2);
 728
 729			if (t3lib_div::_POST('_previewLink_wholeWorkspace'))	{
 730				$previewUrl = t3lib_div::getIndpEnv('TYPO3_SITE_URL').'index.php?ADMCMD_prev='.t3lib_BEfunc::compilePreviewKeyword('', $GLOBALS['BE_USER']->user['uid'],60*60*$ttlHours,$GLOBALS['BE_USER']->workspace).'&id='.intval($this->id);
 731			} else {
 732				$params = 'id='.$this->id.'&ADMCMD_previewWS='.$GLOBALS['BE_USER']->workspace;
 733				$previewUrl = t3lib_div::getIndpEnv('TYPO3_SITE_URL').'index.php?ADMCMD_prev='.t3lib_BEfunc::compilePreviewKeyword($params, $GLOBALS['BE_USER']->user['uid'],60*60*$ttlHours);
 734			}
 735			$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);
 736		}
 737
 738			// Output overview content:
 739		$this->content.= $this->doc->spacer(15);
 740		$this->content.= $this->doc->section($this->details ? $GLOBALS['LANG']->getLL('versionDetails') : $GLOBALS['LANG']->getLL('wsManagement'), $WSoverview,0,1);
 741
 742	}
 743
 744	function workspaceMenu() {
 745		if($this->id) {
 746			$menu = '';
 747			if ($GLOBALS['BE_USER']->workspace===0)	{
 748				$menu.= t3lib_BEfunc::getFuncMenu($this->id,'SET[filter]',$this->MOD_SETTINGS['filter'],$this->MOD_MENU['filter']);
 749				$menu.= t3lib_BEfunc::getFuncMenu($this->id,'SET[display]',$this->MOD_SETTINGS['display'],$this->MOD_MENU['display']);
 750			}
 751			if (!$this->details && $GLOBALS['BE_USER']->workspace && !$this->diffOnly)	{
 752				$menu.= t3lib_BEfunc::getFuncCheck($this->id,'SET[diff]',$this->MOD_SETTINGS['diff'],'','','id="checkDiff"').' <label for="checkDiff">' . $GLOBALS['LANG']->getLL('showDiffView') . '</label>';
 753			}
 754
 755			if ($menu)	{
 756				return $menu;
 757			}
 758		}
 759	}
 760
 761	/**
 762	 * Rendering the overview of versions in the current workspace
 763	 *
 764	 * @return	string		HTML (table)
 765	 * @see typo3/mod/user/ws/index.php for sister function!
 766	 */
 767	function displayWorkspaceOverview()	{
 768
 769			// Initialize variables:
 770		$this->showWorkspaceCol = $GLOBALS['BE_USER']->workspace===0 && $this->MOD_SETTINGS['display']<=-98;
 771
 772			// Get usernames and groupnames
 773		$be_group_Array = t3lib_BEfunc::getListGroupNames('title,uid');
 774		$groupArray = array_keys($be_group_Array);
 775		$this->be_user_Array = t3lib_BEfunc::getUserNames();
 776		if (!$GLOBALS['BE_USER']->isAdmin())		$this->be_user_Array = t3lib_BEfunc::blindUserNames($this->be_user_Array,$groupArray,1);
 777
 778			// Initialize Workspace ID and filter-value:
 779		if ($GLOBALS['BE_USER']->workspace===0)	{
 780			$wsid = $this->details ? -99 : $this->MOD_SETTINGS['display'];		// Set wsid to the value from the menu (displaying content of other workspaces)
 781			$filter = $this->details ? 0 : $this->MOD_SETTINGS['filter'];
 782		} else {
 783			$wsid = $GLOBALS['BE_USER']->workspace;
 784			$filter = 0;
 785		}
 786
 787			// Initialize workspace object and request all pending versions:
 788		$wslibObj = t3lib_div::makeInstance('wslib');
 789
 790			// Selecting ALL versions belonging to the workspace:
 791		$versions = $wslibObj->selectVersionsInWorkspace($wsid, $filter, -99, $this->uid);	// $this->uid is the page id of LIVE record.
 792
 793			// Traverse versions and build page-display array:
 794		$pArray = array();
 795		foreach($versions as $table => $records)	{
 796			foreach($records as $rec)	{
 797				$pageIdField = $table==='pages' ? 't3ver_oid' : 'realpid';
 798				$this->displayWorkspaceOverview_setInPageArray(
 799					$pArray,
 800					$table,
 801					$rec
 802				);
 803			}
 804		}
 805
 806			// Make header of overview:
 807		$tableRows = array();
 808		if (count($pArray))	{
 809			$tableRows[] = '
 810				<tr class="bgColor5 tableheader">
 811					'.($this->diffOnly?'':'<td nowrap="nowrap" colspan="2">' . $GLOBALS['LANG']->getLL('liveVersion') . '</td>').'
 812					<td nowrap="nowrap" colspan="2">' . $GLOBALS['LANG']->getLL('wsVersions') . '</td>
 813					<td nowrap="nowrap"'.($this->diffOnly?' colspan="2"':' colspan="4"').'>' . $GLOBALS['LANG']->getLL('controls') . '</td>
 814				</tr>';
 815
 816				// Add lines from overview:
 817			$tableRows = array_merge($tableRows, $this->displayWorkspaceOverview_list($pArray));
 818
 819			$table = '<table border="0" cellpadding="0" cellspacing="1" class="lrPadding workspace-overview">'.implode('',$tableRows).'</table>';
 820		} else $table = '';
 821
 822		$returnUrl = t3lib_div::sanitizeLocalUrl(t3lib_div::_GP('returnUrl'));
 823		$linkBack = t3lib_div::_GP('returnUrl') ? '<a href="' . htmlspecialchars($returnUrl) . '" class="typo3-goBack">' .
 824				t3lib_iconWorks::getSpriteIcon('actions-view-go-back') . $GLOBALS['LANG']->getLL('goBack', TRUE) .
 825			'</a><br /><br />' : '';
 826		$resetDiffOnly = $this->diffOnly ? '<a href="index.php?id=' . intval($this->id) . '" class="typo3-goBack">' . $GLOBALS['LANG']->getLL('showAllInformation') . '</a><br /><br />' : '';
 827
 828		$versionSelector = $GLOBALS['BE_USER']->workspace ? $this->doc->getVersionSelector($this->id) : '';
 829
 830		return $versionSelector.$linkBack.$resetDiffOnly.$table.$this->markupNewOriginals();
 831	}
 832
 833	/**
 834	 * Rendering the content for the publish / review overview:
 835	 * (Made for internal recursive calling)
 836	 *
 837	 * @param	array		Storage of the elements to display (see displayWorkspaceOverview() / displayWorkspaceOverview_setInPageArray())
 838	 * @return	array		Table rows, see displayWorkspaceOverview()
 839	 */
 840	function displayWorkspaceOverview_list($pArray)	{
 841		global $TCA;
 842
 843			// If there ARE elements on this level, print them:
 844		$warnAboutVersions_nonPages = FALSE;
 845		$warnAboutVersions_page = FALSE;
 846		if (is_array($pArray))	{
 847			foreach($pArray as $table => $oidArray)	{
 848				foreach($oidArray as $oid => $recs)	{
 849
 850						// Get CURRENT online record and icon based on "t3ver_oid":
 851					$rec_on = t3lib_BEfunc::getRecord($table,$oid);
 852					$icon = t3lib_iconWorks::getSpriteIconForRecord($table, $rec_on, array('title' => t3lib_BEfunc::getRecordIconAltText($rec_on,$table)));
 853					if ($GLOBALS['BE_USER']->workspace===0) {	// Only edit online records if in ONLINE workspace:
 854						$icon = $this->doc->wrapClickMenuOnIcon($icon, $table, $rec_on['uid'], 1, '', '+edit,view,info,delete');
 855					}
 856
 857						// Online version display:
 858						// Create the main cells which will span over the number of versions there is.
 859					$verLinkUrl = $TCA[$table]['ctrl']['versioningWS'];
 860					$origElement = $icon.
 861						($verLinkUrl ? '<a href="'.htmlspecialchars('index.php?table='.$table.'&uid='.$rec_on['uid']).'">' : '').
 862						t3lib_BEfunc::getRecordTitle($table,$rec_on,TRUE).
 863						($verLinkUrl ? '</a>' : '');
 864					$mainCell_rowSpan = count($recs)>1 ? ' rowspan="'.count($recs).'"' : '';
 865					$mainCell = '
 866								<td align="center"'.$mainCell_rowSpan.'>'.$this->formatVerId($rec_on['t3ver_id']).'</td>
 867								<td nowrap="nowrap"'.$mainCell_rowSpan.'>'.
 868									$origElement.
 869									'###SUB_ELEMENTS###'.	// For substitution with sub-elements, if any.
 870								'</td>';
 871
 872						// Offline versions display:
 873						// Traverse the versions of the element
 874					foreach($recs as $rec)	{
 875
 876							// Get the offline version record and icon:
 877						$rec_off = t3lib_BEfunc::getRecord($table,$rec['uid']);
 878
 879						// Prepare swap-mode values:
 880						if ($table==='pages' && $rec_off['t3ver_swapmode']!=-1)	{
 881							if ($rec_off['t3ver_swapmode']>0)	{
 882								$vType = 'branch';
 883							} else {
 884								$vType = 'page';
 885							}
 886						} else {
 887							$vType = 'element';
 888						}
 889
 890						// Get icon
 891						$icon = t3lib_iconWorks::getSpriteIconForRecord($table, $rec_off, array('title' => t3lib_BEfunc::getRecordIconAltText($rec_off, $table)));
 892						$tempUid = ($table != 'pages' || $vType==='branch' || $GLOBALS['BE_USER']->workspace===0 ? $rec_off['uid'] : $rec_on['uid']);
 893						$icon = $this->doc->wrapClickMenuOnIcon($icon, $table, $tempUid, 1, '', '+edit,' . ($table == 'pages' ? 'view,info,' : '') . 'delete');
 894
 895							// Prepare diff-code:
 896						if ($this->MOD_SETTINGS['diff'] || $this->diffOnly)	{
 897							$diffCode = '';
 898							list($diffHTML,$diffPct) = $this->createDiffView($table, $rec_off, $rec_on);
 899							if ($rec_on['t3ver_state']==1)	{	// New record:
 900								$diffCode.= $this->doc->icons(1) . $GLOBALS['LANG']->getLL('newElement') . '<br />';
 901								$diffCode.= $diffHTML;
 902							} elseif ($rec_off['t3ver_state']==2)	{
 903								$diffCode.= $this->doc->icons(2) . $GLOBALS['LANG']->getLL('deletedElement') . '<br />';
 904							} elseif ($rec_on['t3ver_state']==3)	{
 905								$diffCode.= $this->doc->icons(1) . $GLOBALS['LANG']->getLL('moveToPlaceholder') . '<br />';
 906							} elseif ($rec_off['t3ver_state']==4)	{
 907								$diffCode.= $this->doc->icons(1) . $GLOBALS['LANG']->getLL('moveToPointer') . '<br />';
 908							} else {
 909								$diffCode.= ($diffPct<0 ? $GLOBALS['LANG']->getLL('notAvailable') : ($diffPct ? $diffPct . '% ' . $GLOBALS['LANG']->getLL('change') : ''));
 910								$diffCode.= $diffHTML;
 911							}
 912						} else $diffCode = '';
 913
 914						switch($vType) {
 915							case 'element':
 916								$swapLabel = $GLOBALS['LANG']->getLL('element');
 917								$swapClass = 'ver-element';
 918								$warnAboutVersions_nonPages = $warnAboutVersions_page;	// Setting this if sub elements are found with a page+content (must be rendered prior to this of course!)
 919							break;
 920							case 'page':
 921								$swapLabel = $GLOBALS['LANG']->getLL('page');
 922								$swapClass = 'ver-page';
 923								$warnAboutVersions_page = !$this->showWorkspaceCol;		// This value is true only if multiple workspaces are shown and we need the opposite here.
 924							break;
 925							case 'branch':
 926								$swapLabel = $GLOBALS['LANG']->getLL('branch');
 927								$swapClass = 'ver-branch';
 928							break;
 929						}
 930
 931							// Modify main cell based on first version shown:
 932						$subElements = array();
 933						if ($table==='pages' && $rec_off['t3ver_swapmode']!=-1 && $mainCell)	{	// For "Page" and "Branch" swap modes where $mainCell is still carrying content (only first version)
 934							$subElements['on'] = $this->subElements($rec_on['uid'], $rec_off['t3ver_swapmode']);
 935							$subElements['off'] = $this->subElements($rec_off['uid'],$rec_off['t3ver_swapmode'],$rec_on['uid']);
 936						}
 937						$mainCell = str_replace('###SUB_ELEMENTS###', $subElements['on'], $mainCell);
 938
 939							// Create version element:
 940						$versionsInOtherWS = $this->versionsInOtherWS($table, $rec_on['uid']);
 941						$versionsInOtherWSWarning = $versionsInOtherWS && $GLOBALS['BE_USER']->workspace !== 0 ? '<br />' . $this->doc->icons(2) . $GLOBALS['LANG']->getLL('otherVersions') . $versionsInOtherWS : '';
 942						$multipleWarning = (!$mainCell && $GLOBALS['BE_USER']->workspace !== 0 ? '<br />' . $this->doc->icons(3) . '<strong>' . $GLOBALS['LANG']->getLL('multipleVersions') . '</strong>' : '');
 943						$verWarning = $warnAboutVersions || ($warnAboutVersions_nonPages && $GLOBALS['TCA'][$table]['ctrl']['versioning_followPages']) ? '<br />' . $this->doc->icons(3) . '<strong>' . $GLOBALS['LANG']->getLL('versionInVersion') . '</strong>' : '';
 944						$verElement = $icon.
 945							(!$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)).'">' : '').
 946							t3lib_BEfunc::getRecordTitle($table,$rec_off,TRUE).
 947							(!$this->details ? '</a>' : '').
 948							$versionsInOtherWSWarning.
 949							$multipleWarning.
 950							$verWarning;
 951
 952						$ctrlTable = '
 953								<td nowrap="nowrap">'.$this->showStageChangeLog($table,$rec_off['uid'],$this->displayWorkspaceOverview_stageCmd($table,$rec_off)).'</td>
 954								<td nowrap="nowrap" class="'.$swapClass.'">'.
 955									$this->displayWorkspaceOverview_commandLinks($table,$rec_on,$rec_off,$vType).
 956									htmlspecialchars($swapLabel).
 957									'&nbsp;&nbsp;</td>
 958								'.(!$this->diffOnly?'<td nowrap="nowrap"><strong>' . $GLOBALS['LANG']->getLL('lifecycle')  . ':</strong> '.htmlspecialchars($this->formatCount($rec_off['t3ver_count'])).'</td>'.		// Lifecycle
 959									($this->showWorkspaceCol ? '
 960								<td nowrap="nowrap">&nbsp;&nbsp;<strong>' . $GLOBALS['LANG']->getLL('workspace')  . ':</strong> '.htmlspecialchars($this->formatWorkspace($rec_off['t3ver_wsid'])).'</td>' : ''):'');
 961
 962						if ($diffCode)	{
 963							$verElement = $verElement.'
 964							<br /><strong>' . $GLOBALS['LANG']->getLL('diffToLiveElement') . '</strong>
 965							<table border="0" cellpadding="0" cellspacing="0" class="ver-verElement">
 966								<tr>
 967									<td class="c-diffCell">'.$diffCode.'</td>
 968								</tr>
 969							</table>';
 970						}
 971
 972
 973							// Create version cell:
 974						$verCell = '
 975								<td align="center">'.$this->formatVerId($rec_off['t3ver_id']).'</td>
 976								<td nowrap="nowrap">'.
 977									$verElement.
 978									$subElements['off'].
 979									'</td>
 980								';
 981
 982							// Compile table row:
 983						$tableRows[] = '
 984							<tr class="bgColor4">
 985								'.
 986								($this->diffOnly?'':$mainCell).
 987								$verCell.
 988								$ctrlTable.
 989								'
 990							</tr>';
 991
 992							// Reset the main cell:
 993						$mainCell = '';
 994
 995					}
 996				}
 997			}
 998		}
 999
1000		return $tableRows;
1001	}
1002
1003	/**
1004	 * Building up of the $pArray
1005	 * (Internal)
1006	 *
1007	 * @param	array		Array that is built up with the page tree structure
1008	 * @param	string		Table name
1009	 * @param	array		Table row
1010	 * @return	void		$pArray is passed by reference and modified internally
1011	 */
1012	function displayWorkspaceOverview_setInPageArray(&$pArray,$table,$row)	{
1013		if (!$this->details || $this->details==$table.':'.$row['uid'])	{
1014			$pArray[$table][$row['t3ver_oid']][] = $row;
1015		}
1016	}
1017
1018	/**
1019	 * Links to stage change of a version
1020	 *
1021	 * @param	string		Table name
1022	 * @param	array		Offline record (version)
1023	 * @return	string		HTML content, mainly link tags and images.
1024	 */
1025	function displayWorkspaceOverview_allStageCmd()	{
1026
1027		$table = t3lib_div::_GP('table');
1028		if ($table && $table!='pages')	{
1029			$uid = t3lib_div::_GP('uid');
1030			if ($rec_off = t3lib_BEfunc::getRecordWSOL($table,$uid)) {
1031				$uid = $rec_off['_ORIG_uid'];
1032			}
1033		} else $table = '';
1034
1035		if ($table)	{
1036			if ($uid && $this->recIndex[$table][$uid])	{
1037				$sId = $this->recIndex[$table][$uid];
1038				switch($sId)	{
1039					case 1:
1040						$label = $GLOBALS['LANG']->getLL('commentForReviewer');
1041					break;
1042					case 10:
1043						$label = $GLOBALS['LANG']->getLL('commentForPublisher');
1044					break;
1045				}
1046			} else $sId = 0;
1047		} else {
1048			if (count($this->stageIndex[1]))	{	// Review:
1049				$sId = 1;
1050				$color = '#666666';
1051				$label = $GLOBALS['LANG']->getLL('sendItemsToReview') . $GLOBALS['LANG']->getLL('commentForReviewer');
1052				$titleAttrib = $GLOBALS['LANG']->getLL('sendAllToReview');
1053			} elseif(count($this->stageIndex[10]))  {	// Publish:
1054				$sId = 10;
1055				$color = '#6666cc';
1056				$label = $GLOBALS['LANG']->getLL('approveToPublish') . $GLOBALS['LANG']->getLL('commentForPublisher');
1057				$titleAttrib = $GLOBALS['LANG']->getLL('approveAllToPublish');
1058			} else {
1059				$sId = 0;
1060			}
1061		}
1062
1063		if ($sId>0)	{
1064			$issueCmd = '';
1065			$itemCount = 0;
1066
1067			if ($table && $uid && $this->recIndex[$table][$uid])	{
1068				$issueCmd.='&cmd['.$table.']['.$uid.'][version][action]=setStage';
1069				$issueCmd.='&cmd['.$table.']['.$uid.'][version][stageId]='.$this->recIndex[$table][$uid];
1070			} else {
1071				foreach($this->stageIndex[$sId] as $table => $uidArray)	{
1072					$issueCmd.='&cmd['.$table.']['.implode(',',$uidArray).'][version][action]=setStage';
1073					$issueCmd.='&cmd['.$table.']['.implode(',',$uidArray).'][version][stageId]='.$sId;
1074					$itemCount+=count($uidArray);
1075				}
1076			}
1077
1078			$onClick = 'var commentTxt=window.prompt("'.sprintf($label,$itemCount).'","");
1079							if (commentTxt!=null) {window.location.href="'.$this->doc->issueCommand($issueCmd,$this->REQUEST_URI).'&generalComment="+escape(commentTxt);}';
1080
1081			if (t3lib_div::_GP('sendToReview'))	{
1082				$onClick.= ' else {window.location.href = "'.$this->REQUEST_URI.'"}';
1083				$actionLinks.=
1084					$this->doc->wrapScriptTags($onClick);
1085			} else {
1086				$onClick.= ' return false;';
1087				$actionLinks.=
1088					'<input type="submit" name="_" value="'.htmlspecialchars($titleAttrib).'" onclick="'.htmlspecialchars($onClick).'" />';
1089			}
1090		} elseif (t3lib_div::_GP('sendToReview'))	{
1091			$onClick = 'window.location.href = "'.$this->REQUEST_URI.'";';
1092			$actionLinks.=
1093				$this->doc->wrapScriptTags($onClick);
1094		} else $actionLinks = '';
1095
1096		return $actionLinks;
1097	}
1098
1099
1100
1101
1102
1103
1104	/**************************************
1105	 *
1106	 * Helper functions (REDUNDANT FROM user/ws/index.php - someone could refactor this...)
1107	 *
1108	 *************************************/
1109
1110	/**
1111	 * Formatting the version number for HTML output
1112	 *
1113	 * @param	integer		Version number
1114	 * @return	string		Version number for output
1115	 */
1116	function formatVerId($verId)	{
1117		return '1.'.$verId;
1118	}
1119
1120	/**
1121	 * Formatting workspace ID into a visual label
1122	 *
1123	 * @param	integer		Workspace ID
1124	 * @return	string		Workspace title
1125	 */
1126	function formatWorkspace($wsid)	{
1127
1128			// Render, if not cached:
1129		if (!isset($this->formatWorkspace_cache[$wsid]))	{
1130			switch($wsid)	{
1131				case -1:
1132					$this->formatWorkspace_cache[$wsid] = $GLOBALS['LANG']->getLL('offline');
1133				break;
1134				case 0:
1135					$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...
1136				break;
1137				default:
1138					list($titleRec) = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('title','sys_workspace','uid='.intval($wsid).t3lib_BEfunc::deleteClause('sys_workspace'));
1139					$this->formatWorkspace_cache[$wsid] = '['.$wsid.'] '.$titleRec['title'];
1140				break;
1141			}
1142		}
1143
1144		return $this->formatWorkspace_cache[$wsid];
1145	}
1146
1147	/**
1148	 * Format publishing count for version (lifecycle state)
1149	 *
1150	 * @param	integer		t3ver_count value (number of times it has been online)
1151	 * @return	string		String translation of count.
1152	 */
1153	function formatCount($count)	{
1154
1155			// Render, if not cached:
1156		if (!isset($this->formatCount_cache[$count]))	{
1157			switch($count)	{
1158				case 0:
1159					$this->formatCount_cache[$count] = $GLOBALS['LANG']->getLL('draft');
1160				break;
1161				case 1:
1162					$this->formatCount_cache[$count] = $GLOBALS['LANG']->getLL('archive');
1163				break;
1164				default:
1165					$this->formatCount_cache[$count] = sprintf($GLOBALS['LANG']->getLL('publishedXTimes'), $count);
1166				break;
1167			}
1168		}
1169
1170		return $this->formatCount_cache[$count];
1171	}
1172
1173	/**
1174	 * Looking for versions of a record in other workspaces than the current
1175	 *
1176	 * @param	string		Table name
1177	 * @param	integer		Record uid
1178	 * @return	string		List of other workspace IDs
1179	 */
1180	function versionsInOtherWS($table,$uid)	{
1181
1182			// Check for duplicates:
1183			// Select all versions of record NOT in this workspace:
1184		$rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1185			't3ver_wsid',
1186			$table,
1187			'pid=-1
1188				AND t3ver_oid='.intval($uid).'
1189				AND t3ver_wsid!='.intval($GLOBALS['BE_USER']->workspace).'
1190				AND (t3ver_wsid=-1 OR t3ver_wsid>0)'.
1191				t3lib_BEfunc::deleteClause($table),
1192			'',
1193			't3ver_wsid',
1194			'',
1195			't3ver_wsid'
1196		);
1197		if (count($rows))	{
1198			return implode(',',array_keys($rows));
1199		}
1200	}
1201
1202	/**
1203	 * Looks up stage changes for version and displays a formatted view on mouseover.
1204	 *
1205	 * @param	string		Table name
1206	 * @param	integer		Record ID
1207	 * @param	string		HTML string to wrap the mouseover around (should be stage change links)
1208	 * @return	string		HTML code.
1209	 */
1210	function showStageChangeLog($table,$id,$stageCommands)	{
1211		$rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1212			'log_data,tstamp,userid',
1213			'sys_log',
1214			'action=6 and details_nr=30
1215				AND tablename='.$GLOBALS['TYPO3_DB']->fullQuoteStr($table,'sys_log').'
1216				AND recuid='.intval($id)
1217		);
1218
1219		$entry = array();
1220		foreach($rows as $dat)	{
1221			$data = unserialize($dat['log_data']);
1222			$username = $this->be_user_Array[$dat['userid']] ? $this->be_user_Array[$dat['userid']]['username'] : '['.$dat['userid'].']';
1223
1224			switch($data['stage'])	{
1225				case 1:
1226					$text = $GLOBALS['LANG']->getLL('stage.sentToReview');
1227				break;
1228				case 10:
1229					$text = $GLOBALS['LANG']->getLL('stage.approvedForPublish');
1230				break;
1231				case -1:
1232					$text = $GLOBALS['LANG']->getLL('stage.rejectedElement');
1233				break;
1234				case 0:
1235					$text = $GLOBALS['LANG']->getLL('stage.resetToEdit');
1236				break;
1237				default:
1238					$text = $GLOBALS['LANG']->getLL('stage.undefined');
1239				break;
1240			}
1241			$text = t3lib_BEfunc::dateTime($dat['tstamp']).': "'.$username.'" '.$text;
1242			$text.= ($data['comment'] ? '<br />' . $GLOBALS['LANG']->getLL('userComment') . ': <em>' . htmlspecialchars($data['comment']) . '</em>' : ''

Large files files are truncated, but you can click here to view the full file