index.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 2004-2010 Kasper Skaarhoj (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 Skaarhoj <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 Skaarhoj <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_extMgm::createListViewLink(
00360                 $this->pageinfo['uid'],
00361                 '&returnUrl=' . rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI')),
00362                 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showList', TRUE)
00363             );
00364         }
00365         return $buttons;
00366     }
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375     /******************************
00376      *
00377      * Versioning management
00378      *
00379      ******************************/
00380 
00381     /**
00382      * Management of versions for record
00383      *
00384      * @return  void
00385      */
00386     function versioningMgm()    {
00387         global $TCA;
00388 
00389             // Diffing:
00390         $diff_1 = t3lib_div::_POST('diff_1');
00391         $diff_2 = t3lib_div::_POST('diff_2');
00392         if (t3lib_div::_POST('do_diff'))    {
00393             $content='';
00394             $content.='<h3>' . $GLOBALS['LANG']->getLL('diffing') . ':</h3>';
00395             if ($diff_1 && $diff_2) {
00396                 $diff_1_record = t3lib_BEfunc::getRecord($this->table, $diff_1);
00397                 $diff_2_record = t3lib_BEfunc::getRecord($this->table, $diff_2);
00398 
00399                 if (is_array($diff_1_record) && is_array($diff_2_record))   {
00400                     t3lib_div::loadTCA($this->table);
00401                     $t3lib_diff_Obj = t3lib_div::makeInstance('t3lib_diff');
00402 
00403                     $tRows=array();
00404                                 $tRows[] = '
00405                                     <tr class="bgColor5 tableheader">
00406                                         <td>' . $GLOBALS['LANG']->getLL('fieldname') . '</td>
00407                                         <td width="98%">' . $GLOBALS['LANG']->getLL('coloredDiffView') . ':</td>
00408                                     </tr>
00409                                 ';
00410                     foreach($diff_1_record as $fN => $fV)   {
00411                         if ($TCA[$this->table]['columns'][$fN] && $TCA[$this->table]['columns'][$fN]['config']['type']!='passthrough' && !t3lib_div::inList('t3ver_label',$fN)) {
00412                             if (strcmp($diff_1_record[$fN],$diff_2_record[$fN]))    {
00413 
00414                                 $diffres = $t3lib_diff_Obj->makeDiffDisplay(
00415                                     t3lib_BEfunc::getProcessedValue($this->table,$fN,$diff_2_record[$fN],0,1),
00416                                     t3lib_BEfunc::getProcessedValue($this->table,$fN,$diff_1_record[$fN],0,1)
00417                                 );
00418 
00419                                 $tRows[] = '
00420                                     <tr class="bgColor4">
00421                                         <td>'.$fN.'</td>
00422                                         <td width="98%">'.$diffres.'</td>
00423                                     </tr>
00424                                 ';
00425                             }
00426                         }
00427                     }
00428 
00429                     if (count($tRows)>1)    {
00430                         $content .= '<table border="0" cellpadding="1" cellspacing="1" width="100%">' . implode('', $tRows) . '</table><br /><br />';
00431                     } else {
00432                         $content .= $GLOBALS['LANG']->getLL('recordsMatchesCompletely');
00433                     }
00434                 } else $content .= $GLOBALS['LANG']->getLL('errorRecordsNotFound');
00435             } else {
00436                 $content .= $GLOBALS['LANG']->getLL('errorDiffSources');
00437             }
00438         }
00439 
00440             // Element:
00441         $record = t3lib_BEfunc::getRecord($this->table,$this->uid);
00442         $recordIcon = t3lib_iconWorks::getSpriteIconForRecord($this->table, $record);
00443         $recTitle = t3lib_BEfunc::getRecordTitle($this->table,$record,TRUE);
00444 
00445             // Display versions:
00446         $content.='
00447             '.$recordIcon.$recTitle.'
00448             <form name="theform" action="'.str_replace('&sendToReview=1','',$this->REQUEST_URI).'" method="post">
00449             <table border="0" cellspacing="1" cellpadding="1">';
00450             $content.='
00451                 <tr class="bgColor5 tableheader">
00452                     <td>&nbsp;</td>
00453                     <td>&nbsp;</td>
00454                     <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_title') . '">' . $GLOBALS['LANG']->getLL('tblHeader_title') . '</td>
00455                     <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_uid') . '">' . $GLOBALS['LANG']->getLL('tblHeader_uid') . '</td>
00456                     <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_oid') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_oid') . '</td>
00457                     <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_id') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_id') . '</td>
00458                     <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_wsid') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_wsid') . '</td>
00459                     <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_state') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_state') . '</td>
00460                     <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_stage') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_stage') . '</td>
00461                     <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_count') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_count') . '</td>
00462                     <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_pid') . '">' . $GLOBALS['LANG']->getLL('tblHeader_pid') . '</td>
00463                     <td title="' . $GLOBALS['LANG']->getLL('tblHeaderDesc_t3ver_label') . '">' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_label') . '</td>
00464                     <td colspan="2"><input type="submit" name="do_diff" value="' . $GLOBALS['LANG']->getLL('diff') . '" /></td>
00465                 </tr>';
00466 
00467         $versions = t3lib_BEfunc::selectVersionsOfRecord($this->table, $this->uid, '*', $GLOBALS['BE_USER']->workspace);
00468         foreach($versions as $row)  {
00469             $adminLinks = $this->adminLinks($this->table,$row);
00470 
00471             $content.='
00472                 <tr class="' . ($row['uid'] != $this->uid ? 'bgColor4' : 'bgColor2 tableheader') . '">
00473                     <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) . '">'.
00474                         t3lib_iconWorks::getSpriteIcon('actions-version-swap-version') .
00475                         '</a>' /* (
00476                             $this->table == 'pages' ?
00477                             '<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').'">'.
00478                         '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert2.gif','width="14" height="14"').' alt="" title="Publish page AND content!" />'.
00479                         '</a>'.
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]=ALL').'">'.
00481                         '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert4.gif','width="14" height="14"').' alt="" title="Publish page AND content! - AND ALL SUBPAGES!" />'.
00482                         '</a>' : '') */ : t3lib_iconWorks::getSpriteIcon('status-status-current', array('title' =>  $GLOBALS['LANG']->getLL('currentOnlineVersion', TRUE)))) . '</td>
00483                     <td nowrap="nowrap">'.$adminLinks.'</td>
00484                     <td nowrap="nowrap">'.t3lib_BEfunc::getRecordTitle($this->table,$row,TRUE).'</td>
00485                     <td>'.$row['uid'].'</td>
00486                     <td>'.$row['t3ver_oid'].'</td>
00487                     <td>'.$row['t3ver_id'].'</td>
00488                     <td>'.$row['t3ver_wsid'].'</td>
00489                     <td>'.$row['t3ver_state'].'</td>
00490                     <td>'.$row['t3ver_stage'].'</td>
00491                     <td>'.$row['t3ver_count'].'</td>
00492                     <td>'.$row['pid'].'</td>
00493                     <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) . '">' .
00494                             t3lib_iconWorks::getSpriteIcon('actions-document-open') .
00495                         '</a>' . htmlspecialchars($row['t3ver_label']) . '</td>
00496                     <td class="version-diff-1"><input type="radio" name="diff_1" value="'.$row['uid'].'"'.($diff_1==$row['uid'] ? ' checked="checked"':'').'/></td>
00497                     <td class="version-diff-2"><input type="radio" name="diff_2" value="'.$row['uid'].'"'.($diff_2==$row['uid'] ? ' checked="checked"':'').'/></td>
00498                 </tr>';
00499 
00500                 // 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;)
00501             if ($this->table == 'pages' && $row['uid']!=$this->uid) {
00502                 $sub = $this->pageSubContent($row['uid']);
00503 
00504                 if ($sub)   {
00505                     $content.='
00506                         <tr>
00507                             <td></td>
00508                             <td></td>
00509                             <td colspan="10">'.$sub.'</td>
00510                             <td colspan="2"></td>
00511                         </tr>';
00512                 }
00513             }
00514         }
00515         $content.='</table></form>';
00516 
00517         $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('title'), $content, 0, 1);
00518 
00519 
00520             // Create new:
00521         $content='
00522 
00523             <form action="'.$this->doc->backPath.'tce_db.php" method="post">
00524             ' . $GLOBALS['LANG']->getLL('tblHeader_t3ver_label') . ': <input type="text" name="cmd[' . $this->table . '][' . $this->uid . '][version][label]" /><br />
00525             '.(($this->table == 'pages' && $GLOBALS['TYPO3_CONF_VARS']['BE']['elementVersioningOnly'] == FALSE)? '<select name="cmd['.$this->table.']['.$this->uid.'][version][treeLevels]">
00526                 '.($GLOBALS['BE_USER']->workspaceVersioningTypeAccess(0) ? '<option value="0">' . $GLOBALS['LANG']->getLL('cmdPid0') . '</option>' : '').'
00527                 '.($GLOBALS['BE_USER']->workspaceVersioningTypeAccess(1) ? '<option value="100">' . $GLOBALS['LANG']->getLL('cmdPid100') . '</option>' : '').'
00528                 '.($GLOBALS['BE_USER']->workspaceVersioningTypeAccess(-1) ? '<option value="-1">' . $GLOBALS['LANG']->getLL('cmdPid1') . '</option>' : '').'
00529             </select>' : '').'
00530             <br /><input type="hidden" name="cmd[' . $this->table . '][' . $this->uid . '][version][action]" value="new" />
00531             <input type="hidden" name="prErr" value="1" />
00532             <input type="hidden" name="redirect" value="'.htmlspecialchars($this->REQUEST_URI).'" />
00533             <input type="submit" name="_" value="' . $GLOBALS['LANG']->getLL('createNewVersion') . '" />
00534 
00535             </form>
00536 
00537         ';
00538 
00539         $this->content.=$this->doc->spacer(15);
00540         $this->content.=$this->doc->section($GLOBALS['LANG']->getLL('createNewVersion'), $content,0,1);
00541 
00542     }
00543 
00544     /**
00545      * Recursively look for children for page version with $pid
00546      *
00547      * @param   integer     UID of page record for which to look up sub-elements following that version
00548      * @param   integer     Counter, do not set (limits to 100 levels)
00549      * @return  string      Table with content if any
00550      */
00551     function pageSubContent($pid,$c=0)  {
00552         global $TCA;
00553 
00554         $tableNames = t3lib_div::removeArrayEntryByValue(array_keys($TCA),'pages');
00555         $tableNames[] = 'pages';
00556 
00557         foreach($tableNames as $tN) {
00558                 // Basically list ALL tables - not only those being copied might be found!
00559             #if ($TCA[$tN]['ctrl']['versioning_followPages'] || $tN=='pages')   {
00560                 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $tN, 'pid='.intval($pid).t3lib_BEfunc::deleteClause($tN), '', ($TCA[$tN]['ctrl']['sortby'] ? $TCA[$tN]['ctrl']['sortby'] : ''));
00561 
00562                 if ($GLOBALS['TYPO3_DB']->sql_num_rows($mres))  {
00563                     $content.='
00564                         <tr>
00565                             <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>
00566                         </tr>';
00567                     while ($subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres))  {
00568                         $ownVer = $this->lookForOwnVersions($tN,$subrow['uid']);
00569                         $content.='
00570                             <tr>
00571                                 <td>'.$this->adminLinks($tN,$subrow).'</td>
00572                                 <td>'.$subrow['uid'].'</td>
00573                                 '.($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>').'
00574                                 <td width="98%">'.t3lib_BEfunc::getRecordTitle($tN,$subrow,TRUE).'</td>
00575                             </tr>';
00576 
00577                         if ($tN == 'pages' && $c<100)   {
00578                             $sub = $this->pageSubContent($subrow['uid'],$c+1);
00579 
00580                             if ($sub)   {
00581                                 $content.='
00582                                     <tr>
00583                                         <td></td>
00584                                         <td></td>
00585                                         <td></td>
00586                                         <td width="98%">'.$sub.'</td>
00587                                     </tr>';
00588                             }
00589                         }
00590                     }
00591                 }
00592             #}
00593         }
00594 
00595         return $content ? '<table border="1" cellpadding="1" cellspacing="0" width="100%">'.$content.'</table>' : '';
00596     }
00597 
00598     /**
00599      * Look for number of versions of a record
00600      *
00601      * @param   string      Table name
00602      * @param   integer     Record uid
00603      * @return  integer     Number of versions for record, false if none.
00604      */
00605     function lookForOwnVersions($table,$uid)    {
00606         global $TCA;
00607 
00608         $versions = t3lib_BEfunc::selectVersionsOfRecord($table, $uid, 'uid');
00609         if (is_array($versions))    {
00610             return count($versions);
00611         }
00612         return FALSE;
00613     }
00614 
00615     /**
00616      * Administrative links for a table / record
00617      *
00618      * @param   string      Table name
00619      * @param   array       Record for which administrative links are generated.
00620      * @return  string      HTML link tags.
00621      */
00622     function adminLinks($table,$row)    {
00623         global $BE_USER;
00624 
00625             // Edit link:
00626         $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) . '">'.
00627                             t3lib_iconWorks::getSpriteIcon('actions-document-open') .
00628                         '</a>';
00629 
00630             // Delete link:
00631         $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) . '">' .
00632                             t3lib_iconWorks::getSpriteIcon('actions-edit-delete') .
00633                         '</a>';
00634 
00635 
00636 
00637         if ($table == 'pages')  {
00638 
00639                 // If another page module was specified, replace the default Page module with the new one
00640             $newPageModule = trim($BE_USER->getTSConfigVal('options.overridePageModule'));
00641             $pageModule = t3lib_BEfunc::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
00642 
00643                 // Perform some acccess checks:
00644             $a_wl = $BE_USER->check('modules','web_list');
00645             $a_wp = t3lib_extMgm::isLoaded('cms') && $BE_USER->check('modules',$pageModule);
00646 
00647             $adminLink.='<a href="#" onclick="top.loadEditId('.$row['uid'].');top.goToModule(\''.$pageModule.'\'); return false;">'.
00648                             t3lib_iconWorks::getSpriteIcon('actions-page-open') .
00649                         '</a>';
00650             $adminLink.='<a href="#" onclick="top.loadEditId('.$row['uid'].');top.goToModule(\'web_list\'); return false;">'.
00651                             t3lib_iconWorks::getSpriteIcon('actions-system-list-open') .
00652                         '</a>';
00653 
00654                 // "View page" icon is added:
00655             $adminLink.='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($row['uid'],$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($row['uid']))).'">'.
00656                     t3lib_iconWorks::getSpriteIcon('actions-document-view') .
00657                 '</a>';
00658         } else {
00659             if ($row['pid']==-1)    {
00660                 $getVars = '&ADMCMD_vPrev['.rawurlencode($table.':'.$row['t3ver_oid']).']='.$row['uid'];
00661 
00662                     // "View page" icon is added:
00663                 $adminLink.='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($row['_REAL_PID'],$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($row['_REAL_PID']),'','',$getVars)).'">'.
00664                         t3lib_iconWorks::getSpriteIcon('actions-document-view') .
00665                     '</a>';
00666             }
00667         }
00668 
00669         return $adminLink;
00670     }
00671 
00672 
00673 
00674 
00675 
00676 
00677 
00678 
00679 
00680 
00681 
00682     /******************************
00683      *
00684      * Workspace management
00685      *
00686      ******************************/
00687 
00688     /**
00689      * Management of workspace for page ID
00690      * Called when $this->id is set.
00691      *
00692      * @return  void
00693      */
00694     function workspaceMgm() {
00695 
00696             // Perform workspace publishing action if buttons are pressed:
00697         $errors = $this->publishAction();
00698 
00699             // Generate workspace overview:
00700         $WSoverview = $this->displayWorkspaceOverview();
00701 
00702             // Buttons for publish / swap:
00703         $actionLinks = '<br />';
00704         if ($GLOBALS['BE_USER']->workspace!==0) {
00705             if ($this->publishAccess)   {
00706                 $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') : '') . '\');"/>';
00707                 if ($GLOBALS['BE_USER']->workspaceSwapAccess()) {
00708                     $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') : '') . '\');" />';
00709                 }
00710             } else {
00711                 $actionLinks.= $this->doc->icons(1) . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_user_ws.xml:no_publish_permission');
00712             }
00713         }
00714 
00715         $actionLinks.= '<input type="submit" name="_" value="' . $GLOBALS['LANG']->getLL('refresh') . '" />';
00716         $actionLinks.= '<input type="submit" name="_previewLink" value="' . $GLOBALS['LANG']->getLL('previewLink') . '" />';
00717         $actionLinks.= '<input type="checkbox" class="checkbox" name="_previewLink_wholeWorkspace" id="_previewLink_wholeWorkspace" value="1" /><label for="_previewLink_wholeWorkspace">' . $GLOBALS['LANG']->getLL('allowPreviewOfWholeWorkspace') . '</label>';
00718         $actionLinks.= $this->displayWorkspaceOverview_allStageCmd();
00719 
00720         if ($actionLinks || count($errors)) {
00721             $this->content .= $this->doc->section('', $actionLinks . (count($errors) ? '<h3>' . $GLOABLS['LANG']->getLL('errors') . '</h3><br />' . implode('<br />', $errors) . '<hr />' : ''), 0, 1);
00722         }
00723 
00724         if (t3lib_div::_POST('_previewLink'))   {
00725             $ttlHours = intval($GLOBALS['BE_USER']->getTSConfigVal('options.workspaces.previewLinkTTLHours'));
00726             $ttlHours = ($ttlHours ? $ttlHours : 24*2);
00727 
00728             if (t3lib_div::_POST('_previewLink_wholeWorkspace'))    {
00729                 $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);
00730             } else {
00731                 $params = 'id='.$this->id.'&ADMCMD_previewWS='.$GLOBALS['BE_USER']->workspace;
00732                 $previewUrl = t3lib_div::getIndpEnv('TYPO3_SITE_URL').'index.php?ADMCMD_prev='.t3lib_BEfunc::compilePreviewKeyword($params, $GLOBALS['BE_USER']->user['uid'],60*60*$ttlHours);
00733             }
00734             $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);
00735         }
00736 
00737             // Output overview content:
00738         $this->content.= $this->doc->spacer(15);
00739         $this->content.= $this->doc->section($this->details ? $GLOBALS['LANG']->getLL('versionDetails') : $GLOBALS['LANG']->getLL('wsManagement'), $WSoverview,0,1);
00740 
00741     }
00742 
00743     function workspaceMenu() {
00744         if($this->id) {
00745             $menu = '';
00746             if ($GLOBALS['BE_USER']->workspace===0) {
00747                 $menu.= t3lib_BEfunc::getFuncMenu($this->id,'SET[filter]',$this->MOD_SETTINGS['filter'],$this->MOD_MENU['filter']);
00748                 $menu.= t3lib_BEfunc::getFuncMenu($this->id,'SET[display]',$this->MOD_SETTINGS['display'],$this->MOD_MENU['display']);
00749             }
00750             if (!$this->details && $GLOBALS['BE_USER']->workspace && !$this->diffOnly)  {
00751                 $menu.= t3lib_BEfunc::getFuncCheck($this->id,'SET[diff]',$this->MOD_SETTINGS['diff'],'','','id="checkDiff"').' <label for="checkDiff">' . $GLOBALS['LANG']->getLL('showDiffView') . '</label>';
00752             }
00753 
00754             if ($menu)  {
00755                 return $menu;
00756             }
00757         }
00758     }
00759 
00760     /**
00761      * Rendering the overview of versions in the current workspace
00762      *
00763      * @return  string      HTML (table)
00764      * @see ws/index.php for sister function!
00765      */
00766     function displayWorkspaceOverview() {
00767 
00768             // Initialize variables:
00769         $this->showWorkspaceCol = $GLOBALS['BE_USER']->workspace===0 && $this->MOD_SETTINGS['display']<=-98;
00770 
00771             // Get usernames and groupnames
00772         $be_group_Array = t3lib_BEfunc::getListGroupNames('title,uid');
00773         $groupArray = array_keys($be_group_Array);
00774         $this->be_user_Array = t3lib_BEfunc::getUserNames();
00775         if (!$GLOBALS['BE_USER']->isAdmin())        $this->be_user_Array = t3lib_BEfunc::blindUserNames($this->be_user_Array,$groupArray,1);
00776 
00777             // Initialize Workspace ID and filter-value:
00778         if ($GLOBALS['BE_USER']->workspace===0) {
00779             $wsid = $this->details ? -99 : $this->MOD_SETTINGS['display'];      // Set wsid to the value from the menu (displaying content of other workspaces)
00780             $filter = $this->details ? 0 : $this->MOD_SETTINGS['filter'];
00781         } else {
00782             $wsid = $GLOBALS['BE_USER']->workspace;
00783             $filter = 0;
00784         }
00785 
00786             // Initialize workspace object and request all pending versions:
00787         $wslibObj = t3lib_div::makeInstance('wslib');
00788 
00789             // Selecting ALL versions belonging to the workspace:
00790         $versions = $wslibObj->selectVersionsInWorkspace($wsid, $filter, -99, $this->uid);  // $this->uid is the page id of LIVE record.
00791 
00792             // Traverse versions and build page-display array:
00793         $pArray = array();
00794         foreach($versions as $table => $records)    {
00795             foreach($records as $rec)   {
00796                 $pageIdField = $table==='pages' ? 't3ver_oid' : 'realpid';
00797                 $this->displayWorkspaceOverview_setInPageArray(
00798                     $pArray,
00799                     $table,
00800                     $rec
00801                 );
00802             }
00803         }
00804 
00805             // Make header of overview:
00806         $tableRows = array();
00807         if (count($pArray)) {
00808             $tableRows[] = '
00809                 <tr class="bgColor5 tableheader">
00810                     '.($this->diffOnly?'':'<td nowrap="nowrap" colspan="2">' . $GLOBALS['LANG']->getLL('liveVersion') . '</td>').'
00811                     <td nowrap="nowrap" colspan="2">' . $GLOBALS['LANG']->getLL('wsVersions') . '</td>
00812                     <td nowrap="nowrap"'.($this->diffOnly?' colspan="2"':' colspan="4"').'>' . $GLOBALS['LANG']->getLL('controls') . '</td>
00813                 </tr>';
00814 
00815                 // Add lines from overview:
00816             $tableRows = array_merge($tableRows, $this->displayWorkspaceOverview_list($pArray));
00817 
00818             $table = '<table border="0" cellpadding="0" cellspacing="1" class="lrPadding workspace-overview">'.implode('',$tableRows).'</table>';
00819         } else $table = '';
00820 
00821         $linkBack = t3lib_div::_GP('returnUrl') ? '<a href="' . htmlspecialchars(t3lib_div::_GP('returnUrl')) . '" class="typo3-goBack">' .
00822                 t3lib_iconWorks::getSpriteIcon('actions-view-go-back') . $GLOBALS['LANG']->getLL('goBack', TRUE) .
00823             '</a><br /><br />' : '';
00824         $resetDiffOnly = $this->diffOnly ? '<a href="index.php?id=' . intval($this->id) . '" class="typo3-goBack">' . $GLOBALS['LANG']->getLL('showAllInformation') . '</a><br /><br />' : '';
00825 
00826         $versionSelector = $GLOBALS['BE_USER']->workspace ? $this->doc->getVersionSelector($this->id) : '';
00827 
00828         return $versionSelector.$linkBack.$resetDiffOnly.$table.$this->markupNewOriginals();
00829     }
00830 
00831     /**
00832      * Rendering the content for the publish / review overview:
00833      * (Made for internal recursive calling)
00834      *
00835      * @param   array       Storage of the elements to display (see displayWorkspaceOverview() / displayWorkspaceOverview_setInPageArray())
00836      * @return  array       Table rows, see displayWorkspaceOverview()
00837      */
00838     function displayWorkspaceOverview_list($pArray) {
00839         global $TCA;
00840 
00841             // If there ARE elements on this level, print them:
00842         $warnAboutVersions_nonPages = FALSE;
00843         $warnAboutVersions_page = FALSE;
00844         if (is_array($pArray))  {
00845             foreach($pArray as $table => $oidArray) {
00846                 foreach($oidArray as $oid => $recs) {
00847 
00848                         // Get CURRENT online record and icon based on "t3ver_oid":
00849                     $rec_on = t3lib_BEfunc::getRecord($table,$oid);
00850                     $icon = t3lib_iconWorks::getSpriteIconForRecord($table, $rec_on, array('title' => t3lib_BEfunc::getRecordIconAltText($rec_on,$table)));
00851                     if ($GLOBALS['BE_USER']->workspace===0) {   // Only edit online records if in ONLINE workspace:
00852                         $icon = $this->doc->wrapClickMenuOnIcon($icon, $table, $rec_on['uid'], 1, '', '+edit,view,info,delete');
00853                     }
00854 
00855                         // Online version display:
00856                         // Create the main cells which will span over the number of versions there is.
00857                     $verLinkUrl = $TCA[$table]['ctrl']['versioningWS'];
00858                     $origElement = $icon.
00859                         ($verLinkUrl ? '<a href="'.htmlspecialchars('index.php?table='.$table.'&uid='.$rec_on['uid']).'">' : '').
00860                         t3lib_BEfunc::getRecordTitle($table,$rec_on,TRUE).
00861                         ($verLinkUrl ? '</a>' : '');
00862                     $mainCell_rowSpan = count($recs)>1 ? ' rowspan="'.count($recs).'"' : '';
00863                     $mainCell = '
00864                                 <td align="center"'.$mainCell_rowSpan.'>'.$this->formatVerId($rec_on['t3ver_id']).'</td>
00865                                 <td nowrap="nowrap"'.$mainCell_rowSpan.'>'.
00866                                     $origElement.
00867                                     '###SUB_ELEMENTS###'.   // For substitution with sub-elements, if any.
00868                                 '</td>';
00869 
00870                         // Offline versions display:
00871                         // Traverse the versions of the element
00872                     foreach($recs as $rec)  {
00873 
00874                             // Get the offline version record and icon:
00875                         $rec_off = t3lib_BEfunc::getRecord($table,$rec['uid']);
00876 
00877                         // Prepare swap-mode values:
00878                         if ($table==='pages' && $rec_off['t3ver_swapmode']!=-1) {
00879                             if ($rec_off['t3ver_swapmode']>0)   {
00880                                 $vType = 'branch';
00881                             } else {
00882                                 $vType = 'page';
00883                             }
00884                         } else {
00885                             $vType = 'element';
00886                         }
00887 
00888                         // Get icon
00889                         $icon = t3lib_iconWorks::getSpriteIconForRecord($table, $rec_off, array('title' => t3lib_BEfunc::getRecordIconAltText($rec_off, $table)));
00890                         $tempUid = ($table != 'pages' || $vType==='branch' || $GLOBALS['BE_USER']->workspace===0 ? $rec_off['uid'] : $rec_on['uid']);
00891                         $icon = $this->doc->wrapClickMenuOnIcon($icon, $table, $tempUid, 1, '', '+edit,' . ($table == 'pages' ? 'view,info,' : '') . 'delete');
00892 
00893                             // Prepare diff-code:
00894                         if ($this->MOD_SETTINGS['diff'] || $this->diffOnly) {
00895                             $diffCode = '';
00896                             list($diffHTML,$diffPct) = $this->createDiffView($table, $rec_off, $rec_on);
00897                             if ($rec_on['t3ver_state']==1)  {   // New record:
00898                                 $diffCode.= $this->doc->icons(1) . $GLOBALS['LANG']->getLL('newElement') . '<br />';
00899                                 $diffCode.= $diffHTML;
00900                             } elseif ($rec_off['t3ver_state']==2)   {
00901                                 $diffCode.= $this->doc->icons(2) . $GLOBALS['LANG']->getLL('deletedElement') . '<br />';
00902                             } elseif ($rec_on['t3ver_state']==3)    {
00903                                 $diffCode.= $this->doc->icons(1) . $GLOBALS['LANG']->getLL('moveToPlaceholder') . '<br />';
00904                             } elseif ($rec_off['t3ver_state']==4)   {
00905                                 $diffCode.= $this->doc->icons(1) . $GLOBALS['LANG']->getLL('moveToPointer') . '<br />';
00906                             } else {
00907                                 $diffCode.= ($diffPct<0 ? $GLOBALS['LANG']->getLL('notAvailable') : ($diffPct ? $diffPct . '% ' . $GLOBALS['LANG']->getLL('change') : ''));
00908                                 $diffCode.= $diffHTML;
00909                             }
00910                         } else $diffCode = '';
00911 
00912                         switch($vType) {
00913                             case 'element':
00914                                 $swapLabel = $GLOBALS['LANG']->getLL('element');
00915                                 $swapClass = 'ver-element';
00916                                 $warnAboutVersions_nonPages = $warnAboutVersions_page;  // Setting this if sub elements are found with a page+content (must be rendered prior to this of course!)
00917                             break;
00918                             case 'page':
00919                                 $swapLabel = $GLOBALS['LANG']->getLL('page');
00920                                 $swapClass = 'ver-page';
00921                                 $warnAboutVersions_page = !$this->showWorkspaceCol;     // This value is true only if multiple workspaces are shown and we need the opposite here.
00922                             break;
00923                             case 'branch':
00924                                 $swapLabel = $GLOBALS['LANG']->getLL('branch');
00925                                 $swapClass = 'ver-branch';
00926                             break;
00927                         }
00928 
00929                             // Modify main cell based on first version shown:
00930                         $subElements = array();
00931                         if ($table==='pages' && $rec_off['t3ver_swapmode']!=-1 && $mainCell)    {   // For "Page" and "Branch" swap modes where $mainCell is still carrying content (only first version)
00932                             $subElements['on'] = $this->subElements($rec_on['uid'], $rec_off['t3ver_swapmode']);
00933                             $subElements['off'] = $this->subElements($rec_off['uid'],$rec_off['t3ver_swapmode'],$rec_on['uid']);
00934                         }
00935                         $mainCell = str_replace('###SUB_ELEMENTS###', $subElements['on'], $mainCell);
00936 
00937                             // Create version element:
00938                         $versionsInOtherWS = $this->versionsInOtherWS($table, $rec_on['uid']);
00939                         $versionsInOtherWSWarning = $versionsInOtherWS && $GLOBALS['BE_USER']->workspace !== 0 ? '<br />' . $this->doc->icons(2) . $GLOBALS['LANG']->getLL('otherVersions') . $versionsInOtherWS : '';
00940                         $multipleWarning = (!$mainCell && $GLOBALS['BE_USER']->workspace !== 0 ? '<br />' . $this->doc->icons(3) . '<strong>' . $GLOBALS['LANG']->getLL('multipleVersions') . '</strong>' : '');
00941                         $verWarning = $warnAboutVersions || ($warnAboutVersions_nonPages && $GLOBALS['TCA'][$table]['ctrl']['versioning_followPages']) ? '<br />' . $this->doc->icons(3) . '<strong>' . $GLOBALS['LANG']->getLL('versionInVersion') . '</strong>' : '';
00942                         $verElement = $icon.
00943                             (!$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)).'">' : '').
00944                             t3lib_BEfunc::getRecordTitle($table,$rec_off,TRUE).
00945                             (!$this->details ? '</a>' : '').
00946                             $versionsInOtherWSWarning.
00947                             $multipleWarning.
00948                             $verWarning;
00949 
00950                         $ctrlTable = '
00951                                 <td nowrap="nowrap">'.$this->showStageChangeLog($table,$rec_off['uid'],$this->displayWorkspaceOverview_stageCmd($table,$rec_off)).'</td>
00952                                 <td nowrap="nowrap" class="'.$swapClass.'">'.
00953                                     $this->displayWorkspaceOverview_commandLinks($table,$rec_on,$rec_off,$vType).
00954                                     htmlspecialchars($swapLabel).
00955                                     '&nbsp;&nbsp;</td>
00956                                 '.(!$this->diffOnly?'<td nowrap="nowrap"><strong>' . $GLOBALS['LANG']->getLL('lifecycle')  . ':</strong> '.htmlspecialchars($this->formatCount($rec_off['t3ver_count'])).'</td>'.       // Lifecycle
00957                                     ($this->showWorkspaceCol ? '
00958                                 <td nowrap="nowrap">&nbsp;&nbsp;<strong>' . $GLOBALS['LANG']->getLL('workspace')  . ':</strong> '.htmlspecialchars($this->formatWorkspace($rec_off['t3ver_wsid'])).'</td>' : ''):'');
00959 
00960                         if ($diffCode)  {
00961                             $verElement = $verElement.'
00962                             <br /><strong>' . $GLOBALS['LANG']->getLL('diffToLiveElement') . '</strong>
00963                             <table border="0" cellpadding="0" cellspacing="0" class="ver-verElement">
00964                                 <tr>
00965                                     <td class="c-diffCell">'.$diffCode.'</td>
00966                                 </tr>
00967                             </table>';
00968                         }
00969 
00970 
00971                             // Create version cell:
00972                         $verCell = '
00973                                 <td align="center">'.$this->formatVerId($rec_off['t3ver_id']).'</td>
00974                                 <td nowrap="nowrap">'.
00975                                     $verElement.
00976                                     $subElements['off'].
00977                                     '</td>
00978                                 ';
00979 
00980                             // Compile table row:
00981                         $tableRows[] = '
00982                             <tr class="bgColor4">
00983                                 '.
00984                                 ($this->diffOnly?'':$mainCell).
00985                                 $verCell.
00986                                 $ctrlTable.
00987                                 '
00988                             </tr>';
00989 
00990                             // Reset the main cell:
00991                         $mainCell = '';
00992 
00993                     }
00994                 }
00995             }
00996         }
00997 
00998         return $tableRows;
00999     }
01000 
01001     /**
01002      * Building up of the $pArray
01003      * (Internal)
01004      *
01005      * @param   array       Array that is built up with the page tree structure
01006      * @param   string      Table name
01007      * @param   array       Table row
01008      * @return  void        $pArray is passed by reference and modified internally
01009      */
01010     function displayWorkspaceOverview_setInPageArray(&$pArray,$table,$row)  {
01011         if (!$this->details || $this->details==$table.':'.$row['uid'])  {
01012             $pArray[$table][$row['t3ver_oid']][] = $row;
01013         }
01014     }
01015 
01016     /**
01017      * Links to stage change of a version
01018      *
01019      * @param   string      Table name
01020      * @param   array       Offline record (version)
01021      * @return  string      HTML content, mainly link tags and images.
01022      */
01023     function displayWorkspaceOverview_allStageCmd() {
01024 
01025         $table = t3lib_div::_GP('table');
01026         if ($table && $table!='pages')  {
01027             $uid = t3lib_div::_GP('uid');
01028             if ($rec_off = t3lib_BEfunc::getRecordWSOL($table,$uid)) {
01029                 $uid = $rec_off['_ORIG_uid'];
01030             }
01031         } else $table = '';
01032 
01033         if ($table) {
01034             if ($uid && $this->recIndex[$table][$uid])  {
01035                 $sId = $this->recIndex[$table][$uid];
01036                 switch($sId)    {
01037                     case 1:
01038                         $label = $GLOBALS['LANG']->getLL('commentForReviewer');
01039                     break;
01040                     case 10:
01041                         $label = $GLOBALS['LANG']->getLL('commentForPublisher');
01042                     break;
01043                 }
01044             } else $sId = 0;
01045         } else {
01046             if (count($this->stageIndex[1]))    {   // Review:
01047                 $sId = 1;
01048                 $color = '#666666';
01049                 $label = $GLOBALS['LANG']->getLL('sendItemsToReview') . $GLOBALS['LANG']->getLL('commentForReviewer');
01050                 $titleAttrib = $GLOBALS['LANG']->getLL('sendAllToReview');
01051             } elseif(count($this->stageIndex[10]))  {   // Publish:
01052                 $sId = 10;
01053                 $color = '#6666cc';
01054                 $label = $GLOBALS['LANG']->getLL('approveToPublish') . $GLOBALS['LANG']->getLL('commentForPublisher');
01055                 $titleAttrib = $GLOBALS['LANG']->getLL('approveAllToPublish');
01056             } else {
01057                 $sId = 0;
01058             }
01059         }
01060 
01061         if ($sId>0) {
01062             $issueCmd = '';
01063             $itemCount = 0;
01064 
01065             if ($table && $uid && $this->recIndex[$table][$uid])    {
01066                 $issueCmd.='&cmd['.$table.']['.$uid.'][version][action]=setStage';
01067                 $issueCmd.='&cmd['.$table.']['.$uid.'][version][stageId]='.$this->recIndex[$table][$uid];
01068             } else {
01069                 foreach($this->stageIndex[$sId] as $table => $uidArray) {
01070                     $issueCmd.='&cmd['.$table.']['.implode(',',$uidArray).'][version][action]=setStage';
01071                     $issueCmd.='&cmd['.$table.']['.implode(',',$uidArray).'][version][stageId]='.$sId;
01072                     $itemCount+=count($uidArray);
01073                 }
01074             }
01075 
01076             $onClick = 'var commentTxt=window.prompt("'.sprintf($label,$itemCount).'","");
01077                             if (commentTxt!=null) {window.location.href="'.$this->doc->issueCommand($issueCmd,$this->REQUEST_URI).'&generalComment="+escape(commentTxt);}';
01078 
01079             if (t3lib_div::_GP('sendToReview')) {
01080                 $onClick.= ' else {window.location.href = "'.$this->REQUEST_URI.'"}';
01081                 $actionLinks.=
01082                     $this->doc->wrapScriptTags($onClick);
01083             } else {
01084                 $onClick.= ' return false;';
01085                 $actionLinks.=
01086                     '<input type="submit" name="_" value="'.htmlspecialchars($titleAttrib).'" onclick="'.htmlspecialchars($onClick).'" />';
01087             }
01088         } elseif (t3lib_div::_GP('sendToReview'))   {
01089             $onClick = 'window.location.href = "'.$this->REQUEST_URI.'";';
01090             $actionLinks.=
01091                 $this->doc->wrapScriptTags($onClick);
01092         } else $actionLinks = '';
01093 
01094         return $actionLinks;
01095     }
01096 
01097 
01098 
01099 
01100 
01101 
01102     /**************************************
01103      *
01104      * Helper functions (REDUNDANT FROM user/ws/index.php - someone could refactor this...)
01105      *
01106      *************************************/
01107 
01108     /**
01109      * Formatting the version number for HTML output
01110      *
01111      * @param   integer     Version number
01112      * @return  string      Version number for output
01113      */
01114     function formatVerId($verId)    {
01115         return '1.'.$verId;
01116     }
01117 
01118     /**
01119      * Formatting workspace ID into a visual label
01120      *
01121      * @param   integer     Workspace ID
01122      * @return  string      Workspace title
01123      */
01124     function formatWorkspace($wsid) {
01125 
01126             // Render, if not cached:
01127         if (!isset($this->formatWorkspace_cache[$wsid]))    {
01128             switch($wsid)   {
01129                 case -1:
01130                     $this->formatWorkspace_cache[$wsid] = $GLOBALS['LANG']->getLL('offline');
01131                 break;
01132                 case 0:
01133                     $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...
01134                 break;
01135                 default:
01136                     list($titleRec) = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('title','sys_workspace','uid='.intval($wsid).t3lib_BEfunc::deleteClause('sys_workspace'));
01137                     $this->formatWorkspace_cache[$wsid] = '['.$wsid.'] '.$titleRec['title'];
01138                 break;
01139             }
01140         }
01141 
01142         return $this->formatWorkspace_cache[$wsid];
01143     }
01144 
01145     /**
01146      * Format publishing count for version (lifecycle state)
01147      *
01148      * @param   integer     t3ver_count value (number of times it has been online)
01149      * @return  string      String translation of count.
01150      */
01151     function formatCount($count)    {
01152 
01153             // Render, if not cached:
01154         if (!isset($this->formatCount_cache[$count]))   {
01155             switch($count)  {
01156                 case 0:
01157                     $this->formatCount_cache[$count] = $GLOBALS['LANG']->getLL('draft');
01158                 break;
01159                 case 1:
01160                     $this->formatCount_cache[$count] = $GLOBALS['LANG']->getLL('archive');
01161                 break;
01162                 default:
01163                     $this->formatCount_cache[$count] = sprintf($GLOBALS['LANG']->getLL('publishedXTimes'), $count);
01164                 break;
01165             }
01166         }
01167 
01168         return $this->formatCount_cache[$count];
01169     }
01170 
01171     /**
01172      * Looking for versions of a record in other workspaces than the current
01173      *
01174      * @param   string      Table name
01175      * @param   integer     Record uid
01176      * @return  string      List of other workspace IDs
01177      */
01178     function versionsInOtherWS($table,$uid) {
01179 
01180             // Check for duplicates:
01181             // Select all versions of record NOT in this workspace:
01182         $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
01183             't3ver_wsid',
01184             $table,
01185             'pid=-1
01186                 AND t3ver_oid='.intval($uid).'
01187                 AND t3ver_wsid!='.intval($GLOBALS['BE_USER']->workspace).'
01188                 AND (t3ver_wsid=-1 OR t3ver_wsid>0)'.
01189                 t3lib_BEfunc::deleteClause($table),
01190             '',
01191             't3ver_wsid',
01192             '',
01193             't3ver_wsid'
01194         );
01195         if (count($rows))   {
01196             return implode(',',array_keys($rows));
01197         }
01198     }
01199 
01200     /**
01201      * Looks up stage changes for version and displays a formatted view on mouseover.
01202      *
01203      * @param   string      Table name
01204      * @param   integer     Record ID
01205      * @param   string      HTML string to wrap the mouseover around (should be stage change links)
01206      * @return  string      HTML code.
01207      */
01208     function showStageChangeLog($table,$id,$stageCommands)  {
01209         $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
01210             'log_data,tstamp,userid',
01211             'sys_log',
01212             'action=6 and details_nr=30
01213                 AND tablename='.$GLOBALS['TYPO3_DB']->fullQuoteStr($table,'sys_log').'
01214                 AND recuid='.intval($id)
01215         );
01216 
01217         $entry = array();
01218         foreach($rows as $dat)  {
01219             $data = unserialize($dat['log_data']);
01220             $username = $this->be_user_Array[$dat['userid']] ? $this->be_user_Array[$dat['userid']]['username'] : '['.$dat['userid'].']';
01221 
01222             switch($data['stage'])  {
01223                 case 1:
01224                     $text = $GLOBALS['LANG']->getLL('stage.sentToReview');
01225                 break;
01226                 case 10:
01227                     $text = $GLOBALS['LANG']->getLL('stage.approvedForPublish');
01228                 break;
01229                 case -1:
01230                     $text = $GLOBALS['LANG']->getLL('stage.rejectedElement');
01231                 break;
01232                 case 0:
01233                     $text = $GLOBALS['LANG']->getLL('stage.resetToEdit');
01234                 break;
01235                 default:
01236                     $text = $GLOBALS['LANG']->getLL('stage.undefined');
01237                 break;
01238             }
01239             $text = t3lib_BEfunc::dateTime($dat['tstamp']).': "'.$username.'" '.$text;
01240             $text.= ($data['comment'] ? '<br />' . $GLOBALS['LANG']->getLL('userComment') . ': <em>' . htmlspecialchars($data['comment']) . '</em>' : '');
01241 
01242             $entry[] = $text;
01243         }
01244 
01245         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>'.
01246                 '<div class="logLayer" style="visibility: hidden; position: absolute;" id="log_'.$table.$id.'">'.implode('<hr/>',array_reverse($entry)).'</div>' : $stageCommands;
01247     }
01248 
01249     /**
01250      * Creates display of sub elements of a page when the swap mode is either "Page" or "Branch" (0 / ALL)
01251      *
01252      * @param   integer     Page uid (for either online or offline version, but it MUST have swapmode/treeLevel set to >0 (not -1 indicating element versioning)
01253      * @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!)
01254      * @param   integer     For offline versions; This is t3ver_oid, the original ID of the online page.
01255      * @return  string      HTML content.
01256      */
01257     function subElements($uid,$treeLevel,$origId=0) {
01258         global $TCA;
01259 
01260         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:
01261             return '<br />
01262                     <img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/ol/joinbottom.gif','width="18" height="16"').' align="top" alt="" title="" />'.
01263                     ($origId ?
01264                         '<a href="'.htmlspecialchars($this->doc->backPath.t3lib_extMgm::extRelPath('version').'cm1/index.php?id='.$uid.'&details='.rawurlencode('pages:'.$uid).'&returnUrl='.rawurlencode($this->REQUEST_URI)).'">'.
01265                         '<span class="typo3-dimmed"><em>' . $GLOBALS['LANG']->getLL('subElementsClick')  . '</em><span></a>' :
01266                         '<span class="typo3-dimmed"><em>' . $GLOBALS['LANG']->getLL('subElements') . '</em><span>');
01267         } else {    // For an offline workspace, show sub elements:
01268 
01269             $tCell = array();
01270 
01271                 // Find records that follow pages when swapping versions:
01272             $recList = array();
01273             foreach($TCA as $tN => $tCfg)   {
01274                 if ($tN!='pages' && ($treeLevel>0 || $TCA[$tN]['ctrl']['versioning_followPages']))  {
01275                     $this->subElements_getNonPageRecords($tN, $uid, $recList);
01276                 }
01277             }
01278 
01279                 // Render records collected above:
01280             $elCount = count($recList)-1;
01281             foreach($recList as $c => $comb)    {
01282                 list($tN,$rec) = $comb;
01283 
01284                 $this->subElements_renderItem(
01285                     $tCell,
01286                     $tN,
01287                     $uid,
01288                     $rec,
01289                     $origId,
01290                     $c==$elCount && $treeLevel==0 ? 1 : 0,      // If true, will show bottom-join icon.
01291                     ''
01292                 );
01293             }
01294 
01295                 // For branch, dive into the subtree:
01296             if ($treeLevel>0) {
01297 
01298                     // Drawing tree:
01299                 $tree = t3lib_div::makeInstance('t3lib_pageTree');
01300                 $tree->init('AND '.$GLOBALS['BE_USER']->getPagePermsClause(1));
01301                 $tree->makeHTML = 2;        // 2=Also rendering depth-data into the result array
01302                 $tree->getTree($uid, 99, '');
01303 
01304                     // Traverse page tree:
01305                 foreach($tree->tree as $data)   {
01306 
01307                         // Render page in table cell:
01308                     $this->subElements_renderItem(
01309                         $tCell,
01310                         'pages',
01311                         $uid,
01312                         t3lib_BEfunc::getRecord('pages',$data['row']['uid']),   // Needs all fields, at least more than what is given in $data['row']...
01313                         $origId,
01314                         2,      // 2=the join icon and icon for the record is not rendered for pages (where all is in $data['HTML']
01315                         $data['HTML']
01316                     );
01317 
01318                         // Find all records from page and collect in $recList:
01319                     $recList = array();
01320                     foreach($TCA as $tN => $tCfg)   {
01321                         if ($tN!=='pages')  {
01322                             $this->subElements_getNonPageRecords($tN, $data['row']['uid'], $recList);
01323                         }
01324                     }
01325 
01326                         // Render records collected above:
01327                     $elCount = count($recList)-1;
01328                     foreach($recList as $c => $comb)    {
01329                         list($tN,$rec) = $comb;
01330 
01331                         $this->subElements_renderItem(
01332                             $tCell,
01333                             $tN,
01334                             $uid,
01335                             $rec,
01336                             $origId,
01337                             $c==$elCount?1:0,   // If true, will show bottom-join icon.
01338                             $data['HTML_depthData']
01339                         );
01340                     }
01341                 }
01342             }
01343 
01344             return '
01345                     <!-- Sub-element tree for versions -->
01346                     <table border="0" cellpadding="0" cellspacing="1" class="ver-subtree">
01347                         '.implode('',$tCell).'
01348                     </table>';
01349         }
01350     }
01351 
01352     /**
01353      * Select records from a table and add them to recList
01354      *
01355      * @param   string      Table name (from TCA)
01356      * @param   integer     PID to select records from
01357      * @param   array       Array where records are accumulated, passed by reference
01358      * @return  void
01359      */
01360     function subElements_getNonPageRecords($tN, $uid, &$recList)    {
01361         global $TCA;
01362 
01363         $records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
01364             '*',
01365             $tN,
01366             'pid='.intval($uid).
01367                 ($TCA[$tN]['ctrl']['versioningWS'] ? ' AND t3ver_state=0' : '').
01368                 t3lib_BEfunc::deleteClause($tN),
01369             '',
01370             $TCA[$tN]['ctrl']['sortby'] ? $TCA[$tN]['ctrl']['sortby'] : $GLOBALS['TYPO3_DB']->stripOrderBy($TCA[$tN]['ctrl']['default_sortby'])
01371         );
01372 
01373         foreach($records as $rec)   {
01374             $recList[] = array($tN,$rec);
01375         }
01376     }
01377 
01378     /**
01379      * Render a single item in a subelement list into a table row:
01380      *
01381      * @param   array       Table rows, passed by reference
01382      * @param   string      Table name
01383      * @param   integer     Page uid for which the subelements are selected/shown
01384      * @param   array       Row of element in list
01385      * @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.
01386      * @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)
01387      * @param   string      Prefix HTML data (icons for tree rendering)
01388      * @return  void        (Content accumulated in $tCell!)
01389      */
01390     function subElements_renderItem(&$tCell,$tN,$uid,$rec,$origId,$iconMode,$HTMLdata)  {
01391         global $TCA;
01392 
01393             // Initialize:
01394         $origUidFields = $TCA[$tN]['ctrl']['origUid'];
01395         $diffCode = '';
01396 
01397         if ($origUidFields) {   // If there is a field for this table with original uids we will use that to connect records:
01398             if (!$origId)   {   // In case we are displaying the online originals:
01399                 $this->targets['orig_'.$uid.'_'.$tN.'_'.$rec['uid']] = $rec;    // Build up target array (important that
01400                 $tdParams =  ' id="orig_'.$uid.'_'.$tN.'_'.$rec['uid'].'" class="typo3-ver"';       // Setting ID of the table row
01401             } else {    // Version branch:
01402                 if ($this->targets['orig_'.$origId.'_'.$tN.'_'.$rec[$origUidFields]])   {   // If there IS a corresponding original record...:
01403 
01404                         // Prepare Table row parameters:
01405                     $tdParams =  ' onmouseover="hlSubelements(\''.$origId.'_'.$tN.'_'.$rec[$origUidFields].'\', \''.$uid.'_'.$tN.'_'.$rec[$origUidFields].'\', 1, '.($this->MOD_SETTINGS['diff']==2?1:0).');"'.
01406                                 ' onmouseout="hlSubelements(\''.$origId.'_'.$tN.'_'.$rec[$origUidFields].'\', \''.$uid.'_'.$tN.'_'.$rec[$origUidFields].'\', 0, '.($this->MOD_SETTINGS['diff']==2?1:0).');"'.
01407                                 ' id="ver_'.$uid.'_'.$tN.'_'.$rec[$origUidFields].'" class="typo3-ver"';
01408 
01409                         // Create diff view:
01410                     if ($this->MOD_SETTINGS['diff'])    {
01411                         list($diffHTML,$diffPct) = $this->createDiffView($tN, $rec, $this->targets['orig_'.$origId.'_'.$tN.'_'.$rec[$origUidFields]]);
01412 
01413                         if ($this->MOD_SETTINGS['diff']==2) {
01414                             $diffCode =
01415                                 ($diffPct ? '<span class="nobr">'.$diffPct.'% change</span>' : '-').
01416                                 '<div style="visibility: hidden; position: absolute;" id="diff_'.$uid.'_'.$tN.'_'.$rec[$origUidFields].'" class="diffLayer">'.
01417                                 $diffHTML.
01418                                 '</div>';
01419                         } else {
01420                             $diffCode =
01421                                 ($diffPct<0 ? $GLOBALS['LANG']->getLL('notAvailable') : ($diffPct ? $diffPct . '% ' . $GLOBALS['LANG']->getLL('change') : '')).
01422                                 $diffHTML;
01423                         }
01424                     }
01425 
01426                         // Unsetting the target fields allows us to mark all originals without a version in the subtree (see ->markupNewOriginals())
01427                     unset($this->targets['orig_'.$origId.'_'.$tN.'_'.$rec[$origUidFields]]);
01428                 } else {    // No original record, so must be new:
01429                     $tdParams =  ' class="typo3-ver-new"';
01430                 }
01431             }
01432         } else {    // If no original uid column is supported for this table we are forced NOT to display any diff or highlighting.
01433             $tdParams = ' class="typo3-ver-noComp"';
01434         }
01435 
01436             // Compile the cell:
01437         $tCell[] = '
01438                         <tr'.$tdParams.'>
01439                             <td class="iconTitle">'.
01440                                 $HTMLdata.
01441                                 ($iconMode < 2 ?
01442                                     '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/ol/join'.($iconMode ? 'bottom' : '').'.gif','width="18" height="16"').' alt="" />'.
01443                                     t3lib_iconWorks::getSpriteIconForRecord($tN, $rec) : '').
01444                                 t3lib_BEfunc::getRecordTitle($tN, $rec, TRUE).
01445                             '</td>
01446                             <td class="cmdCell">'.
01447                                 $this->displayWorkspaceOverview_commandLinksSub($tN,$rec,$origId).
01448                             '</td>'.($origId ? '<td class="diffCell">'.
01449                                 $diffCode.
01450                             '</td>':'').'
01451                         </tr>';
01452     }
01453 
01454     /**
01455      * JavaScript code to mark up new records that are online (in sub element lists)
01456      *
01457      * @return  string      HTML javascript section
01458      */
01459     function markupNewOriginals()   {
01460 
01461         if (count($this->targets))  {
01462             $scriptCode = '';
01463             foreach($this->targets as $key => $rec) {
01464                 $scriptCode.='
01465                     document.getElementById(\''.$key.'\').attributes.getNamedItem("class").nodeValue = \'typo3-ver-new\';
01466                 ';
01467             }
01468 
01469             return $this->doc->wrapScriptTags($scriptCode);
01470         }
01471     }
01472 
01473     /**
01474      * Create visual difference view of two records. Using t3lib_diff library
01475      *
01476      * @param   string      Table name
01477      * @param   array       New version record (green)
01478      * @param   array       Old version record (red)
01479      * @return  array       Array with two keys (0/1) with HTML content / percentage integer (if -1, then it means N/A) indicating amount of change
01480      */
01481     function createDiffView($table, $diff_1_record, $diff_2_record) {
01482         global $TCA;
01483 
01484             // Initialize:
01485         $pctChange = 'N/A';
01486 
01487             // Check that records are arrays:
01488         if (is_array($diff_1_record) && is_array($diff_2_record))   {
01489 
01490                 // Load full table description and initialize diff-object:
01491             t3lib_div::loadTCA($table);
01492             $t3lib_diff_Obj = t3lib_div::makeInstance('t3lib_diff');
01493 
01494                 // Add header row:
01495             $tRows = array();
01496             $tRows[] = '
01497                 <tr class="bgColor5 tableheader">
01498                     <td>' . $GLOBALS['LANG']->getLL('fieldname')  . ':</td>
01499                     <td width="98%" nowrap="nowrap">' . $GLOBALS['LANG']->getLL('coloredDiffView') . ':</td>
01500                 </tr>
01501             ';
01502 
01503                 // Initialize variables to pick up string lengths in:
01504             $allStrLen = 0;
01505             $diffStrLen = 0;
01506 
01507                 // Traversing the first record and process all fields which are editable:
01508             foreach($diff_1_record as $fN => $fV)   {
01509                 if ($TCA[$table]['columns'][$fN] && $TCA[$table]['columns'][$fN]['config']['type']!='passthrough' && !t3lib_div::inList('t3ver_label',$fN)) {
01510 
01511                         // Check if it is files:
01512                     $isFiles = FALSE;
01513                     if (strcmp(trim($diff_1_record[$fN]),trim($diff_2_record[$fN])) &&
01514                             $TCA[$table]['columns'][$fN]['config']['type']=='group' &&
01515                             $TCA[$table]['columns'][$fN]['config']['internal_type']=='file')    {
01516 
01517                             // Initialize:
01518                         $uploadFolder = $TCA[$table]['columns'][$fN]['config']['uploadfolder'];
01519                         $files1 = array_flip(t3lib_div::trimExplode(',', $diff_1_record[$fN],1));
01520                         $files2 = array_flip(t3lib_div::trimExplode(',', $diff_2_record[$fN],1));
01521 
01522                             // Traverse filenames and read their md5 sum:
01523                         foreach($files1 as $filename => $tmp)   {
01524                             $files1[$filename] = @is_file(PATH_site.$uploadFolder.'/'.$filename) ? md5(t3lib_div::getUrl(PATH_site.$uploadFolder.'/'.$filename)) : $filename;
01525                         }
01526                         foreach($files2 as $filename => $tmp)   {
01527                             $files2[$filename] = @is_file(PATH_site.$uploadFolder.'/'.$filename) ? md5(t3lib_div::getUrl(PATH_site.$uploadFolder.'/'.$filename)) : $filename;
01528                         }
01529 
01530                             // Implode MD5 sums and set flag:
01531                         $diff_1_record[$fN] = implode(' ',$files1);
01532                         $diff_2_record[$fN] = implode(' ',$files2);
01533                         $isFiles = TRUE;
01534                     }
01535 
01536                         // If there is a change of value:
01537                     if (strcmp(trim($diff_1_record[$fN]),trim($diff_2_record[$fN])))    {
01538 
01539 
01540                             // Get the best visual presentation of the value and present that:
01541                         $val1 = t3lib_BEfunc::getProcessedValue($table,$fN,$diff_2_record[$fN],0,1);
01542                         $val2 = t3lib_BEfunc::getProcessedValue($table,$fN,$diff_1_record[$fN],0,1);
01543 
01544                             // Make diff result and record string lenghts:
01545                         $diffres = $t3lib_diff_Obj->makeDiffDisplay($val1,$val2,$isFiles?'div':'span');
01546                         $diffStrLen+= $t3lib_diff_Obj->differenceLgd;
01547                         $allStrLen+= strlen($val1.$val2);
01548 
01549                             // If the compared values were files, substituted MD5 hashes:
01550                         if ($isFiles)   {
01551                             $allFiles = array_merge($files1,$files2);
01552                             foreach($allFiles as $filename => $token)   {
01553                                 if (strlen($token)==32 && strstr($diffres,$token))  {
01554                                     $filename =
01555                                         t3lib_BEfunc::thumbCode(array($fN=>$filename),$table,$fN,$this->doc->backPath).
01556                                         $filename;
01557                                     $diffres = str_replace($token,$filename,$diffres);
01558                                 }
01559                             }
01560                         }
01561 
01562                             // Add table row with result:
01563                         $tRows[] = '
01564                             <tr class="bgColor4">
01565                                 <td>'.htmlspecialchars($GLOBALS['LANG']->sL(t3lib_BEfunc::getItemLabel($table,$fN))).'</td>
01566                                 <td width="98%">'.$diffres.'</td>
01567                             </tr>
01568                         ';
01569                     } else {
01570                             // Add string lengths even if value matched - in this was the change percentage is not high if only a single field is changed:
01571                         $allStrLen+=strlen($diff_1_record[$fN].$diff_2_record[$fN]);
01572                     }
01573                 }
01574             }
01575 
01576                 // Calculate final change percentage:
01577             $pctChange = $allStrLen ? ceil($diffStrLen*100/$allStrLen) : -1;
01578 
01579                 // Create visual representation of result:
01580             if (count($tRows)>1)    {
01581                 $content.= '<table border="0" cellpadding="1" cellspacing="1" class="diffTable">'.implode('',$tRows).'</table>';
01582             } else {
01583                 $content.= '<span class="nobr">'.$this->doc->icons(1) . $GLOBALS['LANG']->getLL('completeMatch') . '</span>';
01584             }
01585         } else $content.= $this->doc->icons(3) . $GLOBALS['LANG']->getLL('errorRecordsNotFound');
01586 
01587             // Return value:
01588         return array($content,$pctChange);
01589     }
01590 
01591     /**
01592      * Links to stage change of a version
01593      *
01594      * @param   string      Table name
01595      * @param   array       Offline record (version)
01596      * @return  string      HTML content, mainly link tags and images.
01597      */
01598     function displayWorkspaceOverview_stageCmd($table,&$rec_off)    {
01599 #debug($rec_off['t3ver_stage']);
01600         switch((int)$rec_off['t3ver_stage'])    {
01601             case 0:
01602                 $sId = 1;
01603                 $sLabel = $GLOBALS['LANG']->getLL('editing');
01604                 $color = '#666666';
01605                 $label = $GLOBALS['LANG']->getLL('commentForReviewer');
01606                 $titleAttrib = $GLOBALS['LANG']->getLL('sendToReview');
01607             break;
01608             case 1:
01609                 $sId = 10;
01610                 $sLabel = $GLOBALS['LANG']->getLL('review');
01611                 $color = '#6666cc';
01612                 $label = $GLOBALS['LANG']->getLL('commentForPublisher');
01613                 $titleAttrib = $GLOBALS['LANG']->getLL('approveForPublishing');
01614             break;
01615             case 10:
01616                 $sLabel = $GLOBALS['LANG']->getLL('publish');
01617                 $color = '#66cc66';
01618             break;
01619             case -1:
01620                 $sLabel = $this->doc->icons(2) . $GLOBALS['LANG']->getLL('rejected');
01621                 $sId = 0;
01622                 $color = '#ff0000';
01623                 $label = $GLOBALS['LANG']->getLL('comment');
01624                 $titleAttrib = $GLOBALS['LANG']->getLL('resetStage');
01625             break;
01626             default:
01627                 $sLabel = $GLOBALS['LANG']->getLL('undefined');
01628                 $sId = 0;
01629                 $color = '';
01630             break;
01631         }
01632 #debug($sId);
01633 
01634         $raiseOk = !$GLOBALS['BE_USER']->workspaceCannotEditOfflineVersion($table,$rec_off);
01635 
01636         if ($raiseOk && $rec_off['t3ver_stage']!=-1)    {
01637             $onClick = 'var commentTxt=window.prompt("' . $GLOBALS['LANG']->getLL('rejectExplain') . '","");
01638                             if (commentTxt!=null) {window.location.href="'.$this->doc->issueCommand(
01639                             '&cmd['.$table.']['.$rec_off['uid'].'][version][action]=setStage'.
01640                             '&cmd['.$table.']['.$rec_off['uid'].'][version][stageId]=-1'
01641                             ).'&cmd['.$table.']['.$rec_off['uid'].'][version][comment]="+escape(commentTxt);}'.
01642                             ' return false;';
01643                 // Reject:
01644             $actionLinks.=
01645                 '<a href="#" onclick="'.htmlspecialchars($onClick).'" title="' . $GLOBALS['LANG']->getLL('reject', TRUE) . '">'.
01646                     t3lib_iconWorks::getSpriteIcon('actions-move-down') .
01647                 '</a>';
01648         } else {
01649                 // Reject:
01650             $actionLinks.=
01651                 '<img src="'.$this->doc->backPath.'gfx/clear.gif" width="14" height="14" alt="" align="top" title="" />';
01652         }
01653 
01654         $actionLinks.= '<span style="background-color: '.$color.'; color: white;">'.$sLabel.'</span>';
01655 
01656             // Raise
01657         if ($raiseOk)   {
01658             $onClick = 'var commentTxt=window.prompt("'.$label.'","");
01659                             if (commentTxt!=null) {window.location.href="'.$this->doc->issueCommand(
01660                             '&cmd['.$table.']['.$rec_off['uid'].'][version][action]=setStage'.
01661                             '&cmd['.$table.']['.$rec_off['uid'].'][version][stageId]='.$sId
01662                             ).'&cmd['.$table.']['.$rec_off['uid'].'][version][comment]="+escape(commentTxt);}'.
01663                             ' return false;';
01664             if ($rec_off['t3ver_stage']!=10)    {
01665                 $actionLinks.=
01666                     '<a href="#" onclick="'.htmlspecialchars($onClick).'" title="' . htmlspecialchars($titleAttrib) . '">' .
01667                         t3lib_iconWorks::getSpriteIcon('actions-move-up') .
01668                     '</a>';
01669 
01670                 $this->stageIndex[$sId][$table][] = $rec_off['uid'];
01671                 $this->recIndex[$table][$rec_off['uid']] = $sId;
01672             }
01673         }
01674         return $actionLinks;
01675     }
01676 
01677     /**
01678      * Links to publishing etc of a version
01679      *
01680      * @param   string      Table name
01681      * @param   array       Online record
01682      * @param   array       Offline record (version)
01683      * @param   string      Swap type, "branch", "page" or "element"
01684      * @return  string      HTML content, mainly link tags and images.
01685      */
01686     function displayWorkspaceOverview_commandLinks($table,&$rec_on,&$rec_off,$vType)    {
01687         if ($this->publishAccess && (!($GLOBALS['BE_USER']->workspaceRec['publish_access']&1) || (int)$rec_off['t3ver_stage']===10))    {
01688             $actionLinks =
01689                 '<a href="'.htmlspecialchars($this->doc->issueCommand(
01690                         '&cmd['.$table.']['.$rec_on['uid'].'][version][action]=swap'.
01691                         '&cmd['.$table.']['.$rec_on['uid'].'][version][swapWith]='.$rec_off['uid']
01692                         )).'" title="' . $GLOBALS['LANG']->getLL('publish', TRUE) . '">'.
01693                     t3lib_iconWorks::getSpriteIcon('actions-version-swap-versions') .
01694                 '</a>';
01695             if ($GLOBALS['BE_USER']->workspaceSwapAccess()) {
01696                 $actionLinks.=
01697                     '<a href="'.htmlspecialchars($this->doc->issueCommand(
01698                             '&cmd['.$table.']['.$rec_on['uid'].'][version][action]=swap'.
01699                             '&cmd['.$table.']['.$rec_on['uid'].'][version][swapWith]='.$rec_off['uid'].
01700                             '&cmd['.$table.']['.$rec_on['uid'].'][version][swapIntoWS]=1'
01701                             )).'" title="' . $GLOBALS['LANG']->getLL('swap', TRUE) . '">'.
01702                         t3lib_iconWorks::getSpriteIcon('actions-version-swap-workspace') .
01703                     '</a>';
01704             }
01705         }
01706 
01707         if (!$GLOBALS['BE_USER']->workspaceCannotEditOfflineVersion($table,$rec_off))   {
01708                 // Release
01709             $actionLinks.=
01710                 '<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) . '">'.
01711                     t3lib_iconWorks::getSpriteIcon('actions-version-document-remove') .
01712                 '</a>';
01713 
01714                 // Edit
01715             if ($table==='pages' && $vType!=='element') {
01716                 $tempUid = ($vType==='branch' || $GLOBALS['BE_USER']->workspace===0 ? $rec_off['uid'] : $rec_on['uid']);
01717                 $actionLinks.=
01718                     '<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) . '">'.
01719                         t3lib_iconWorks::getSpriteIcon('actions-version-page-open') .
01720                     '</a>';
01721             } else {
01722                 $params = '&edit['.$table.']['.$rec_off['uid'].']=edit';
01723                 $actionLinks.=
01724                     '<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). '">'.
01725                         t3lib_iconWorks::getSpriteIcon('actions-document-open') .
01726                     '</a>';
01727             }
01728         }
01729 
01730             // History/Log
01731         $actionLinks.=
01732             '<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) . '">'.
01733                 t3lib_iconWorks::getSpriteIcon('actions-document-history-open') .
01734             '</a>';
01735 
01736             // View
01737         if ($table==='pages')   {
01738             $tempUid = ($vType==='branch' || $GLOBALS['BE_USER']->workspace===0 ? $rec_off['uid'] : $rec_on['uid']);
01739             $actionLinks.=
01740                 '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($tempUid,$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($tempUid))).'">'.
01741                     t3lib_iconWorks::getSpriteIcon('actions-document-view') .
01742                 '</a>';
01743         }
01744 
01745         return $actionLinks;
01746     }
01747 
01748     /**
01749      * Links to publishing etc of a version
01750      *
01751      * @param   string      Table name
01752      * @param   array       Record
01753      * @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.
01754      * @return  string      HTML content, mainly link tags and images.
01755      */
01756     function displayWorkspaceOverview_commandLinksSub($table,$rec,$origId)  {
01757         $uid = $rec['uid'];
01758         if ($origId || $GLOBALS['BE_USER']->workspace===0)  {
01759             if (!$GLOBALS['BE_USER']->workspaceCannotEditRecord($table,$rec))   {
01760                     // Edit
01761                 if ($table==='pages')   {
01762                     $actionLinks.=
01763                         '<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) . '">'.
01764                             t3lib_iconWorks::getSpriteIcon('apps-version-page-open') .
01765                         '</a>';
01766                 } else {
01767                     $params = '&edit['.$table.']['.$uid.']=edit';
01768                     $actionLinks.=
01769                         '<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) . '">'.
01770                             t3lib_iconWorks::getSpriteIcon('actions-document-open') .
01771                         '</a>';
01772                 }
01773             }
01774 
01775                 // History/Log
01776             $actionLinks.=
01777                 '<a href="'.htmlspecialchars($this->doc->backPath.'show_rechis.php?element='.rawurlencode($table.':'.$uid).'&returnUrl='.rawurlencode($this->REQUEST_URI)).'" title="' . $GLOBALS['LANG']->getLL('showLog', TRUE) . '">'.
01778                     t3lib_iconWorks::getSpriteIcon('actions-document-history-open') .
01779                 '</a>';
01780         }
01781 
01782             // View
01783         if ($table==='pages')   {
01784             $actionLinks.=
01785                 '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($uid,$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($uid))).'">'.
01786                     t3lib_iconWorks::getSpriteIcon('actions-document-view') .
01787                 '</a>';
01788         }
01789 
01790         return $actionLinks;
01791     }
01792 
01793 
01794 
01795 
01796 
01797 
01798 
01799 
01800 
01801     /**********************************
01802      *
01803      * Processing
01804      *
01805      **********************************/
01806 
01807     /**
01808      * Will publish workspace if buttons are pressed
01809      *
01810      * @return  void
01811      */
01812     function publishAction()    {
01813 
01814             // If "Publish" or "Swap" buttons are pressed:
01815         if (t3lib_div::_POST('_publish') || t3lib_div::_POST('_swap'))  {
01816 
01817             if ($this->table==='pages') {   // Making sure ->uid is a page ID!
01818                     // Initialize workspace object and request all pending versions:
01819                 $wslibObj = t3lib_div::makeInstance('wslib');
01820                 $cmd = $wslibObj->getCmdArrayForPublishWS($GLOBALS['BE_USER']->workspace, t3lib_div::_POST('_swap'),$this->uid);
01821 
01822                     // Execute the commands:
01823                 $tce = t3lib_div::makeInstance('t3lib_TCEmain');
01824                 $tce->stripslashes_values = 0;
01825                 $tce->start(array(), $cmd);
01826                 $tce->process_cmdmap();
01827 
01828                 t3lib_BEfunc::setUpdateSignal('updatePageTree');
01829 
01830                 return $tce->errorLog;
01831             }
01832         }
01833     }
01834 }
01835 
01836 
01837 
01838 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/version/cm1/index.php'])   {
01839     include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/version/cm1/index.php']);
01840 }
01841 
01842 
01843 
01844 
01845 // Make instance:
01846 $SOBE = t3lib_div::makeInstance('tx_version_cm1');
01847 $SOBE->init();
01848 
01849 
01850 $SOBE->main();
01851 $SOBE->printContent();
01852 
01853 ?>

Generated on Sat Jul 24 04:17:16 2010 for TYPO3 API by  doxygen 1.4.7