"TYPO3 4.0.1: typo3_src-4.0.1/typo3/mod/user/ws/index.php Source File", "datetime" => "Sat Dec 2 19:22:16 2006", "date" => "2 Dec 2006", "doxygenversion" => "1.4.6", "projectname" => "TYPO3 4.0.1", "projectnumber" => "4.0.1" ); get_header($doxygen_vars); ?>

index.php

00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2005 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 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00095         // Initialize module:
00096 unset($MCONF);
00097 require ('conf.php');
00098 require ($BACK_PATH.'init.php');
00099 require ($BACK_PATH.'template.php');
00100 $BE_USER->modAccess($MCONF,1);
00101 
00102         // Include libraries of various kinds used inside:
00103 $LANG->includeLLFile('EXT:lang/locallang_mod_user_ws.xml');
00104 require_once(PATH_t3lib.'class.t3lib_scbase.php');
00105 require_once(PATH_typo3.'mod/user/ws/class.wslib.php');
00106 require_once(PATH_t3lib.'class.t3lib_diff.php');
00107 require_once(PATH_t3lib.'class.t3lib_pagetree.php');
00108 require_once(PATH_t3lib.'class.t3lib_tcemain.php');
00109 
00110 
00111 
00112 
00120 class SC_mod_user_ws_index extends t3lib_SCbase {
00121 
00122                 // Static:
00123         var $pageTreeIndent = 8;
00124         var $pageTreeIndent_titleLgd = 30;
00125 
00126                 // Default variables for backend modules
00127         var $MCONF = array();                           // Module configuration
00128         var $MOD_MENU = array();                        // Module menu items
00129         var $MOD_SETTINGS = array();            // Module session settings
00130         var $doc;                                                       // Document Template Object
00131         var $content;                                           // Accumulated content
00132 
00133 
00134                 // Internal:
00135         var $showWorkspaceCol = 0;
00136         var $formatWorkspace_cache = array();
00137         var $formatCount_cache = array();
00138         var $targets = array();         // Accumulation of online targets.
00139         var $pageModule = '';
00140         var $publishAccess = FALSE;
00141         var $be_user_Array = array();
00142         var $be_user_Array_full = array();      // not blinded, used by workspace listing
00143         var $stageIndex = array();
00144 
00145 
00146         /*********************************
00147          *
00148          * Standard module initialization
00149          *
00150          *********************************/
00151 
00157         function menuConfig()   {
00158                 global  $LANG;
00159 
00160                         // Menu items:
00161                 $this->MOD_MENU = array(
00162                         'function' => array(
00163                                 'publish' => $LANG->getLL('menuitem_review'),
00164                                 'workspaces' => $LANG->getLL('menuitem_workspaces'),
00165                         ),
00166                         'filter' => array(
00167                                 1 => $LANG->getLL('filter_drafts'),
00168                                 2 => $LANG->getLL('filter_archive'),
00169                                 0 => $LANG->getLL('filter_all'),
00170                         ),
00171                         'display' => array(
00172                                 0 => '[Live workspace]',
00173                                 -98 => 'Draft Workspaces',
00174                                 -99 => 'All',
00175                                 -1 => '[Default Draft]'
00176                         ),
00177                         'diff' => array(
00178                                 0 => $LANG->getLL('diff_no_diff'),
00179                                 1 => $LANG->getLL('diff_show_inline'),
00180                                 2 => $LANG->getLL('diff_show_popup'),
00181                         ),
00182                         'expandSubElements' => '',
00183                 );
00184 
00185                         // Add workspaces:
00186                 if ($GLOBALS['BE_USER']->workspace===0) {       // Spend time on this only in online workspace because it might take time:
00187                         $workspaces = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,title,adminusers,members,reviewers','sys_workspace','pid=0'.t3lib_BEfunc::deleteClause('sys_workspace'),'','title');
00188                         foreach($workspaces as $rec)    {
00189                                 if ($GLOBALS['BE_USER']->checkWorkspace($rec))  {
00190                                         $this->MOD_MENU['display'][$rec['uid']] = '['.$rec['uid'].'] '.$rec['title'];
00191                                 }
00192                         }
00193                 }
00194 
00195                         // CLEANSE SETTINGS
00196                 $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name'], 'ses');
00197         }
00198 
00204         function init() {
00205                 global $BACK_PATH, $BE_USER;
00206 
00207                         // Setting module configuration:
00208                 $this->MCONF = $GLOBALS['MCONF'];
00209 
00210                         // Initialize Document Template object:
00211                 $this->doc = t3lib_div::makeInstance('noDoc');
00212                 $this->doc->backPath = $BACK_PATH;
00213                 $this->doc->docType = 'xhtml_trans';
00214 
00215                         // JavaScript
00216                 $plusIcon = t3lib_iconWorks::skinImg($BACK_PATH, 'gfx/ol/plusbullet.gif', 'width="18" height="16"', 1);
00217                 $minusIcon = t3lib_iconWorks::skinImg($BACK_PATH, 'gfx/ol/minusbullet.gif', 'width="18" height="16"', 1);
00218                 $this->doc->JScode = $this->doc->wrapScriptTags('
00219                         script_ended = 0;
00220                         function jumpToUrl(URL) {       //
00221                                 window.location.href = URL;
00222                         }
00223 
00224                         function hlSubelements(origId, verId, over, diffLayer)  {       //
00225                                 if (over)       {
00226                                         document.getElementById(\'orig_\'+origId).attributes.getNamedItem("class").nodeValue = \'typo3-ver-hl\';
00227                                         document.getElementById(\'ver_\'+verId).attributes.getNamedItem("class").nodeValue = \'typo3-ver-hl\';
00228                                         if (diffLayer)  {
00229                                                 document.getElementById(\'diff_\'+verId).style.visibility = \'visible\';
00230                                         }
00231                                 } else {
00232                                         document.getElementById(\'orig_\'+origId).attributes.getNamedItem("class").nodeValue = \'typo3-ver\';
00233                                         document.getElementById(\'ver_\'+verId).attributes.getNamedItem("class").nodeValue = \'typo3-ver\';
00234                                         if (diffLayer)  {
00235                                                 document.getElementById(\'diff_\'+verId).style.visibility = \'hidden\';
00236                                         }
00237                                 }
00238                         }
00239 
00240                         function expandCollapse(rowNumber)      {       //
00241                                 elementId = \'wl_\' + rowNumber;
00242                                 element = document.getElementById(elementId);
00243                                 image = document.getElementById(elementId + \'i\');
00244                                 if (element.style)      {
00245                                         if (element.style.display == \'none\')  {
00246                                                 element.style.display = \'\';
00247                                                 image.src = \'' . $minusIcon . '\';
00248                                         } else {
00249                                                 element.style.display = \'none\';
00250                                                 image.src = \'' . $plusIcon . '\';
00251                                         }
00252                                 }
00253                         }
00254                 ');
00255                 $this->doc->form = '<form action="index.php" method="post" name="pageform">';
00256 
00257                         // Setting up the context sensitive menu:
00258                 $CMparts = $this->doc->getContextMenuCode();
00259                 $this->doc->JScode.= $CMparts[0];
00260                 $this->doc->bodyTagAdditions = $CMparts[1];
00261                 $this->doc->postCode.= $CMparts[2];
00262 
00263                         // Add JS for dynamic tabs:
00264                 $this->doc->JScode.= $this->doc->getDynTabMenuJScode();
00265 
00266                         // If another page module was specified, replace the default Page module with the new one
00267                 $newPageModule = trim($BE_USER->getTSConfigVal('options.overridePageModule'));
00268                 $this->pageModule = t3lib_BEfunc::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
00269 
00270                         // Setting publish access permission for workspace:
00271                 $this->publishAccess = $BE_USER->workspacePublishAccess($BE_USER->workspace);
00272 
00273                         // Parent initialization:
00274                 parent::init();
00275         }
00276 
00282         function main() {
00283                 global $LANG, $BE_USER, $BACK_PATH;
00284 
00285                 // See if we need to switch workspace
00286                 $changeWorkspace = t3lib_div::_GET('changeWorkspace');
00287                 if ($changeWorkspace != '') {
00288                         $BE_USER->setWorkspace($changeWorkspace);
00289                         $this->content = $this->doc->startPage($LANG->getLL('title'));
00290                         $this->content .= $this->doc->wrapScriptTags('top.location.href="' . $BACK_PATH . 'alt_main.php";');
00291                 }
00292                 else {
00293                                 // Perform workspace publishing action if buttons are pressed:
00294                         $errors = $this->publishAction();
00295 
00296                                 // Starting page:
00297                         $this->content.=$this->doc->startPage($LANG->getLL('title'));
00298                         $this->content.=$this->doc->header($LANG->getLL('title'));
00299                         $this->content.=$this->doc->spacer(5);
00300 
00301                                 // Build top menu:
00302                         $menuItems = array();
00303                         $menuItems[] = array(
00304                                 'label' => $LANG->getLL('menuitem_review'),
00305                                 'content' => (count($errors) ? '<h3>' . $LANG->getLL('label_errors') . '</h3><br/>'.implode('<br/>',$errors).'<hr/>' : '').$this->moduleContent_publish()
00306                         );
00307                         $menuItems[] = array(
00308                                 'label' => $LANG->getLL('menuitem_workspaces'),
00309                                 'content' => $this->moduleContent_workspaceList()
00310                         );
00311 
00312                                 // Add hidden fields and create tabs:
00313                         $content = $this->doc->getDynTabMenu($menuItems,'user_ws');
00314                         $this->content.=$this->doc->section('',$content,0,1);
00315                 }
00316         }
00317 
00323         function printContent() {
00324                 global $SOBE;
00325 
00326                 $this->content.= $this->doc->endPage();
00327                 echo $this->content;
00328         }
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342         /*********************************
00343          *
00344          * Module content: Publish
00345          *
00346          *********************************/
00347 
00353         function moduleContent_publish()        {
00354                 global  $LANG;
00355 
00356                         // Initialize:
00357                 $content = '';
00358                 $details = t3lib_div::_GP('details');
00359 
00360                         // Create additional menus:
00361                 $menu = '';
00362                 if ($GLOBALS['BE_USER']->workspace===0) {
00363                         $menu.= t3lib_BEfunc::getFuncMenu(0,'SET[filter]',$this->MOD_SETTINGS['filter'],$this->MOD_MENU['filter']);
00364                         $menu.= t3lib_BEfunc::getFuncMenu(0,'SET[display]',$this->MOD_SETTINGS['display'],$this->MOD_MENU['display']);
00365                 }
00366                 $menu.= t3lib_BEfunc::getFuncMenu(0,'SET[diff]',$this->MOD_SETTINGS['diff'],$this->MOD_MENU['diff']);
00367                 if ($GLOBALS['BE_USER']->workspace!==0) {
00368                         $menu.= t3lib_BEfunc::getFuncCheck(0,'SET[expandSubElements]',$this->MOD_SETTINGS['expandSubElements']).' Show sub-elements - ';
00369                 }
00370 
00371                         // Create header:
00372                 $title = '';
00373                 $description = '';
00374                 switch($GLOBALS['BE_USER']->workspace)  {
00375                         case 0:
00376                                 $title = t3lib_iconWorks::getIconImage('sys_workspace', array(), $this->doc->backPath, ' align="top"').'[LIVE workspace]';
00377                                 $description = $LANG->getLL('workspace_description_live');
00378                         break;
00379                         case -1:
00380                                 $title = t3lib_iconWorks::getIconImage('sys_workspace', array(), $this->doc->backPath, ' align="top"').'[Draft workspace]';
00381                                 $description = $LANG->getLL('workspace_description_draft');
00382                         break;
00383                         case -99:
00384                                 $title = $this->doc->icons(3).'[NONE]';
00385                                 $description = $LANG->getLL('workspace_description_no_access');
00386                         break;
00387                         default:
00388                                 $title = t3lib_iconWorks::getIconImage('sys_workspace', $GLOBALS['BE_USER']->workspaceRec, $this->doc->backPath, ' align="top"').
00389                                                         '['.$GLOBALS['BE_USER']->workspace.'] '.t3lib_BEfunc::getRecordTitle('sys_workspace',$GLOBALS['BE_USER']->workspaceRec,TRUE);
00390                                 $description = ($GLOBALS['BE_USER']->workspaceRec['description'] ? htmlspecialchars($GLOBALS['BE_USER']->workspaceRec['description']) : '<em>[None]</em>');
00391                         break;
00392                 }
00393 
00394                         // Buttons for publish / swap:
00395                 $actionLinks = '';
00396                 if ($GLOBALS['BE_USER']->workspace!==0) {
00397                         if ($this->publishAccess)       {
00398                                 $confirmation = $LANG->JScharCode($LANG->getLL(($GLOBALS['BE_USER']->workspaceRec['publish_access'] & 1) ? 'submit_publish_workspace_confirmation_1' :  'submit_publish_workspace_confirmation_2'));
00399                                 $actionLinks.= '<input type="submit" name="_publish" value="' . $LANG->getLL('submit_publish_workspace') . '" onclick="return confirm(' . $confirmation . ');"/>';
00400                                 if ($GLOBALS['BE_USER']->workspaceSwapAccess()) {
00401                                         $confirmation = $LANG->JScharCode($LANG->getLL(($GLOBALS['BE_USER']->workspaceRec['publish_access'] & 1) ? 'submit_swap_workspace_confirmation_1' :  'submit_swap_workspace_confirmation_2'));
00402                                         $actionLinks.= '<input type="submit" name="_swap" value="' . $LANG->getLL('submit_swap_workspace') . '" onclick="return confirm(' . $confirmation . ');" />';
00403                                 }
00404                         } else {
00405                                 $actionLinks.= $this->doc->icons(1) . $LANG->getLL('no_publish_permission');
00406                         }
00407                 }
00408 
00409                 $wsAccess = $GLOBALS['BE_USER']->checkWorkspace($GLOBALS['BE_USER']->workspaceRec);
00410 
00411                         // Add header to content variable:
00412                 $content = '
00413                 <table border="0" cellpadding="1" cellspacing="1" class="lrPadding" style="border: 1px solid black;">
00414                         <tr>
00415                                 <td class="bgColor2" nowrap="nowrap"><b>' . $LANG->getLL('label_workspace') . '</b>&nbsp;</td>
00416                                 <td class="bgColor4" nowrap="nowrap">'.$title.'</td>
00417                         </tr>
00418                         <tr>
00419                                 <td class="bgColor2" nowrap="nowrap"><b>' . $LANG->getLL('label_description') . '</b>&nbsp;</td>
00420                                 <td class="bgColor4">'.$description.'</td>
00421                         </tr>'.($GLOBALS['BE_USER']->workspace!=-99 && !$details ? '
00422                         <tr>
00423                                 <td class="bgColor2" nowrap="nowrap"><b>' . $LANG->getLL('label_options') . '</b>&nbsp;</td>
00424                                 <td class="bgColor4">'.$menu.$actionLinks.'</td>
00425                         </tr>
00426                         <tr>
00427                                 <td class="bgColor2" nowrap="nowrap"><b>' . $LANG->getLL('label_status') . '</b>&nbsp;</td>
00428                                 <td class="bgColor4">Access level: ' . $GLOBALS['LANG']->getLL('workspace_list_access_' . $wsAccess['_ACCESS']) . '</td>
00429                         </tr>' : '').'
00430                 </table>
00431                 <br/>
00432                 ';
00433 
00434                         // Add publishing and review overview:
00435                 if ($GLOBALS['BE_USER']->workspace!=-99)        {
00436                         if ($details)   {
00437                                 $content.= $this->displayVersionDetails($details);
00438                         } else {
00439                                 $content.= $this->displayWorkspaceOverview();
00440                         }
00441                         $content.='<br/>';
00442                 }
00443 
00444                         // Return content:
00445                 return $content;
00446         }
00447 
00454         function displayVersionDetails($details)        {
00455                 return 'TODO: Show details for version "'.$details.'"<hr/><a href="index.php">BACK</a>';
00456         }
00457 
00463         function displayWorkspaceOverview()     {
00464                 global  $LANG;
00465 
00466                         // Initialize variables:
00467                 $this->showWorkspaceCol = $GLOBALS['BE_USER']->workspace===0 && $this->MOD_SETTINGS['display']<=-98;
00468 
00469                         // Get usernames and groupnames
00470                 $be_group_Array = t3lib_BEfunc::getListGroupNames('title,uid');
00471                 $groupArray = array_keys($be_group_Array);
00472                         // Need 'admin' field for t3lib_iconWorks::getIconImage()
00473                 $this->be_user_Array_full = $this->be_user_Array = t3lib_BEfunc::getUserNames('username,usergroup,usergroup_cached_list,uid,admin,workspace_perms');
00474                 if (!$GLOBALS['BE_USER']->isAdmin())            $this->be_user_Array = t3lib_BEfunc::blindUserNames($this->be_user_Array,$groupArray,1);
00475 
00476                         // Initialize Workspace ID and filter-value:
00477                 if ($GLOBALS['BE_USER']->workspace===0) {
00478                         $wsid = $this->MOD_SETTINGS['display'];         // Set wsid to the value from the menu (displaying content of other workspaces)
00479                         $filter = $this->MOD_SETTINGS['filter'];
00480                 } else {
00481                         $wsid = $GLOBALS['BE_USER']->workspace;
00482                         $filter = 0;
00483                 }
00484 
00485                         // Initialize workspace object and request all pending versions:
00486                 $wslibObj = t3lib_div::makeInstance('wslib');
00487 
00488                         // Selecting ALL versions belonging to the workspace:
00489                 $versions = $wslibObj->selectVersionsInWorkspace($wsid, $filter);
00490 
00491                         // Traverse versions and build page-display array:
00492                 $pArray = array();
00493                 foreach($versions as $table => $records)        {
00494                         if (is_array($records)) {
00495                                 foreach($records as $rec)       {
00496                                         $pageIdField = $table==='pages' ? 't3ver_oid' : 'realpid';
00497                                         $this->displayWorkspaceOverview_setInPageArray(
00498                                                 $pArray,
00499                                                 t3lib_BEfunc::BEgetRootLine($rec[$pageIdField], 'AND 1=1'),
00500                                                 $table,
00501                                                 $rec
00502                                         );
00503                                 }
00504                         }
00505                 }
00506 
00507                         // Make header of overview:
00508                 $tableRows = array();
00509                 $tableRows[] = '
00510                         <tr class="bgColor5 tableheader">
00511                                 <td nowrap="nowrap" width="100">' . $LANG->getLL('label_pagetree') . '</td>
00512                                 <td nowrap="nowrap" colspan="2">' . $LANG->getLL('label_live_version') . '</td>
00513                                 <td nowrap="nowrap" colspan="2">' . $LANG->getLL('label_draft_versions') . '</td>
00514                                 <td nowrap="nowrap">' . $LANG->getLL('label_stage') . '</td>
00515                                 <td nowrap="nowrap">' . $LANG->getLL('label_publish') . '</td>
00516                                 <td>' . $LANG->getLL('label_lifecycle') . '</td>
00517                                 '.($this->showWorkspaceCol ? '<td>' . $LANG->getLL('label_workspace') . '</td>' : '').'
00518                         </tr>';
00519 
00520                         // Add lines from overview:
00521                 $tableRows = array_merge($tableRows, $this->displayWorkspaceOverview_list($pArray));
00522 
00523                 $table = '<table border="0" cellpadding="0" cellspacing="1" class="lrPadding workspace-overview">'.implode('',$tableRows).'</table>';
00524 
00525                 return $table.$this->markupNewOriginals();
00526         }
00527 
00538         function displayWorkspaceOverview_list($pArray, $tableRows=array(), $c=0, $warnAboutVersions=FALSE)     {
00539                 global $TCA;
00540 
00541                         // Initialize:
00542                 $fullColSpan = ($this->showWorkspaceCol?9:8);
00543 
00544                         // Traverse $pArray
00545                 if (is_array($pArray))  {
00546                         foreach($pArray as $k => $v)    {
00547                                 if (t3lib_div::testInt($k))     {
00548 
00549                                                 // If there are elements on this level, output a divider row which just creates a little visual space.
00550                                         if (is_array($pArray[$k.'_']))  {
00551                                                 $tableRows[] = '
00552                                                         <tr>
00553                                                                 <td colspan="'.$fullColSpan.'"><img src="clear.gif" width="1" height="3" alt="" /></td>
00554                                                         </tr>';
00555                                         }
00556 
00557                                                 // Printing a level from the page tree with no additional content:
00558                                                 // If there are NO elements on this level OR if there are NO pages on a level with elements, then show page tree icon and title (otherwise it is shown with the display of the elements)
00559                                         if (!is_array($pArray[$k.'_']) || !is_array($pArray[$k.'_']['pages']))  {
00560                                                 $tableRows[] = '
00561                                                         <tr class="bgColor4-20">
00562                                                                 <td nowrap="nowrap" colspan="'.$fullColSpan.'">'.
00563                                                                         $this->displayWorkspaceOverview_pageTreeIconTitle($k,$pArray[$k],$c).
00564                                                                         '</td>
00565                                                         </tr>';
00566                                         }
00567 
00568                                                 // If there ARE elements on this level, print them:
00569                                         $warnAboutVersions_next = $warnAboutVersions;
00570                                         $warnAboutVersions_nonPages = FALSE;
00571                                         $warnAboutVersions_page = FALSE;
00572                                         if (is_array($pArray[$k.'_']))  {
00573                                                 foreach($pArray[$k.'_'] as $table => $oidArray) {
00574                                                         foreach($oidArray as $oid => $recs)     {
00575 
00576                                                                         // Get CURRENT online record and icon based on "t3ver_oid":
00577                                                                 $rec_on = t3lib_BEfunc::getRecord($table,$oid);
00578                                                                 $icon = t3lib_iconWorks::getIconImage($table, $rec_on, $this->doc->backPath,' align="top" title="'.t3lib_BEfunc::getRecordIconAltText($rec_on,$table).'"');
00579                                                                 if ($GLOBALS['BE_USER']->workspace===0) {       // Only edit online records if in ONLINE workspace:
00580                                                                         $icon = $this->doc->wrapClickMenuOnIcon($icon, $table, $rec_on['uid'], 2, '', '+edit,view,info,delete');
00581                                                                 }
00582 
00583                                                                         // MAIN CELL / Online version display:
00584                                                                         // Create the main cells which will span over the number of versions there is. If the table is "pages" then it will show the page tree icon and title (which was not shown by the code above)
00585                                                                 $verLinkUrl = t3lib_extMgm::isLoaded('version') && $TCA[$table]['ctrl']['versioningWS'];
00586                                                                 $origElement = $icon.
00587                                                                         ($verLinkUrl ? '<a href="'.htmlspecialchars($this->doc->backPath.t3lib_extMgm::extRelPath('version').'cm1/index.php?table='.$table.'&uid='.$rec_on['uid']).'">' : '').
00588                                                                         t3lib_BEfunc::getRecordTitle($table,$rec_on,TRUE).
00589                                                                         ($verLinkUrl ? '</a>' : '');
00590                                                                 $mainCell_rowSpan = count($recs)>1 ? ' rowspan="'.count($recs).'"' : '';
00591                                                                 $mainCell = $table==='pages' ? '
00592                                                                                         <td class="bgColor4-20" nowrap="nowrap"'.$mainCell_rowSpan.'>'.
00593                                                                                         $this->displayWorkspaceOverview_pageTreeIconTitle($k,$pArray[$k],$c).
00594                                                                                         '</td>' : '
00595                                                                                         <td class="bgColor"'.$mainCell_rowSpan.'></td>';
00596                                                                 $mainCell.= '
00597                                                                                         <td align="center"'.$mainCell_rowSpan.'>'.$this->formatVerId($rec_on['t3ver_id']).'</td>
00598                                                                                         <td nowrap="nowrap"'.$mainCell_rowSpan.'>'.
00599                                                                                                 $origElement.
00600                                                                                                 '###SUB_ELEMENTS###'.   // For substitution with sub-elements, if any.
00601                                                                                         '</td>';
00602 
00603                                                                         // Offline versions display:
00604                                                                         // Traverse the versions of the element
00605                                                                 foreach($recs as $rec)  {
00606 
00607                                                                                 // Get the offline version record and icon:
00608                                                                         $rec_off = t3lib_BEfunc::getRecord($table,$rec['uid']);
00609                                                                         $icon = t3lib_iconWorks::getIconImage($table, $rec_off, $this->doc->backPath, ' align="top" title="'.t3lib_BEfunc::getRecordIconAltText($rec_off,$table).'"');
00610                                                                         $icon = $this->doc->wrapClickMenuOnIcon($icon, $table, $rec_off['uid'], 2, '', '+edit,view,info,delete');
00611 
00612                                                                                 // Prepare diff-code:
00613                                                                         if ($this->MOD_SETTINGS['diff'])        {
00614                                                                                 $diffCode = '';
00615                                                                                 list($diffHTML,$diffPct) = $this->createDiffView($table, $rec_off, $rec_on);
00616                                                                                 if ($rec_on['t3ver_state']==1)  {       // New record:
00617                                                                                         $diffCode.= $this->doc->icons(1).'New element<br/>';    // TODO Localize?
00618                                                                                         $diffCode.= $diffHTML;
00619                                                                                 } elseif ($rec_off['t3ver_state']==2)   {
00620                                                                                         $diffCode.= $this->doc->icons(2).'Deleted element<br/>';
00621                                                                                 } else {
00622                                                                                         $diffCode.= ($diffPct<0 ? 'N/A' : ($diffPct ? $diffPct.'% change:' : ''));
00623                                                                                         $diffCode.= $diffHTML;
00624                                                                                 }
00625 
00626                                                                         } else $diffCode = '';
00627 
00628                                                                                 // Prepare swap-mode values:
00629                                                                         if ($table==='pages' && $rec_off['t3ver_swapmode']!=-1) {
00630                                                                                 if ($rec_off['t3ver_swapmode']>0)       {
00631                                                                                         $vType = 'branch';      // Do not translate!
00632                                                                                 } else {
00633                                                                                         $vType = 'page';        // Do not translate!
00634                                                                                 }
00635                                                                         } else {
00636                                                                                 $vType = 'element';     // Do not translate!
00637                                                                         }
00638 
00639                                                                         switch($vType) {
00640                                                                                 case 'element':
00641                                                                                         $swapLabel = ' [Element]';      // TODO Localize?
00642                                                                                         $swapClass = 'ver-element';     // Do not translate!
00643                                                                                         $warnAboutVersions_nonPages = $warnAboutVersions_page;  // Setting this if sub elements are found with a page+content (must be rendered prior to this of course!)
00644                                                                                 break;
00645                                                                                 case 'page':
00646                                                                                         $swapLabel = ' [Page]'; // TODO Localize?
00647                                                                                         $swapClass = 'ver-page';        // Do not translate!
00648                                                                                         $warnAboutVersions_page = !$this->showWorkspaceCol;             // This value is true only if multiple workspaces are shown and we need the opposite here.
00649                                                                                 break;
00650                                                                                 case 'branch':
00651                                                                                         $swapLabel = ' [Branch]';       // TODO Localize?
00652                                                                                         $swapClass = 'ver-branch';      // Do not translate!
00653                                                                                         $warnAboutVersions_next = !$this->showWorkspaceCol;             // This value is true only if multiple workspaces are shown and we need the opposite here.
00654                                                                                 break;
00655                                                                         }
00656 
00657                                                                                 // Modify main cell based on first version shown:
00658                                                                         $subElements = array();
00659                                                                         if ($table==='pages' && $rec_off['t3ver_swapmode']!=-1 && $mainCell)    {       // For "Page" and "Branch" swap modes where $mainCell is still carrying content (only first version)
00660                                                                                 $subElements['on'] = $this->subElements($rec_on['uid'], $rec_off['t3ver_swapmode']);
00661                                                                                 $subElements['off'] = $this->subElements($rec_off['uid'],$rec_off['t3ver_swapmode'],$rec_on['uid']);
00662                                                                         }
00663                                                                         $mainCell = str_replace('###SUB_ELEMENTS###', $subElements['on'], $mainCell);
00664 
00665                                                                                 // Create version element:
00666                                                                         $versionsInOtherWS = $this->versionsInOtherWS($table, $rec_on['uid']);
00667                                                                         $versionsInOtherWSWarning = $versionsInOtherWS && $GLOBALS['BE_USER']->workspace!==0 ? '<br/>'.$this->doc->icons(2).'Other version(s) in workspace '.$versionsInOtherWS : '';
00668                                                                         $multipleWarning = (!$mainCell && $GLOBALS['BE_USER']->workspace!==0? '<br/>'.$this->doc->icons(3).'<b>Multiple versions in same workspace!</b>' : '');
00669                                                                         $verWarning = $warnAboutVersions || ($warnAboutVersions_nonPages && $GLOBALS['TCA'][$table]['ctrl']['versioning_followPages'])? '<br/>'.$this->doc->icons(3).'<b>Version inside version!</b>' : '';
00670                                                                         $verElement = $icon.
00671                                                                                 '<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(t3lib_div::getIndpEnv('REQUEST_URI'))).'">'.
00672                                                                                 t3lib_BEfunc::getRecordTitle($table,$rec_off,TRUE).
00673                                                                                 '</a>'.
00674                                                                                 $versionsInOtherWSWarning.
00675                                                                                 $multipleWarning.
00676                                                                                 $verWarning;
00677                                                                         if ($diffCode)  {
00678                                                                                 $verElement = '
00679                                                                                 <table border="0" cellpadding="0" cellspacing="0" class="ver-verElement">
00680                                                                                         <tr>
00681                                                                                                 <td nowrap="nowrap" width="180">'.$verElement.'&nbsp;&nbsp;</td>
00682                                                                                                 <td class="c-diffCell">'.$diffCode.'</td>
00683                                                                                         </tr>
00684                                                                                 </table>';
00685                                                                         }
00686 
00687                                                                                 // Create version cell:
00688                                                                         $verCell = '
00689                                                                                         <td align="center">'.$this->formatVerId($rec_off['t3ver_id']).'</td>
00690                                                                                         <td nowrap="nowrap">'.
00691                                                                                                 $verElement.
00692                                                                                                 $subElements['off'].
00693                                                                                                 '</td>';
00694 
00695                                                                                 // Compile table row:
00696                                                                         $tableRows[] = '
00697                                                                                 <tr class="bgColor4">
00698                                                                                         '.$mainCell.$verCell.'
00699                                                                                         <td nowrap="nowrap">'.$this->showStageChangeLog($table,$rec_off['uid'],$this->displayWorkspaceOverview_stageCmd($table,$rec_off)).'</td>
00700                                                                                         <td nowrap="nowrap" class="'.$swapClass.'">'.
00701                                                                                                 $this->displayWorkspaceOverview_commandLinks($table,$rec_on,$rec_off,$vType).
00702                                                                                                 htmlspecialchars($swapLabel).
00703                                                                                                 '</td>
00704                                                                                         <td nowrap="nowrap">'.htmlspecialchars($this->formatCount($rec_off['t3ver_count'])).'</td>'.            // Lifecycle
00705                                                                                                 ($this->showWorkspaceCol ? '
00706                                                                                         <td nowrap="nowrap">'.htmlspecialchars($this->formatWorkspace($rec_off['t3ver_wsid'])).'</td>' : '').'
00707                                                                                 </tr>';
00708 
00709                                                                                 // Reset the main cell:
00710                                                                         $mainCell = '';
00711                                                                 }
00712                                                         }
00713                                                 }
00714                                         }
00715                                                 // Call recursively for sub-rows:
00716                                         $tableRows = $this->displayWorkspaceOverview_list($pArray[$k.'.'], $tableRows, $c+1, $warnAboutVersions_next);
00717                                 }
00718                         }
00719                 }
00720                 return $tableRows;
00721         }
00722 
00731         function displayWorkspaceOverview_pageTreeIconTitle($pageUid, $title, $indentCount)     {
00732                 $pRec = t3lib_BEfunc::getRecord('pages',$pageUid);
00733                 return '<img src="clear.gif" width="1" height="1" hspace="'.($indentCount * $this->pageTreeIndent).'" align="top" alt="" />'.   // Indenting page tree
00734                                         t3lib_iconWorks::getIconImage('pages',$pRec,$this->doc->backPath,' align="top" title="'.t3lib_BEfunc::getRecordIconAltText($pRec,'pages').'"').
00735                                         htmlspecialchars(t3lib_div::fixed_lgd_cs($title,$this->pageTreeIndent_titleLgd)).
00736                                         '&nbsp;&nbsp;';
00737         }
00738 
00746         function displayWorkspaceOverview_stageCmd($table,&$rec_off)    {
00747 #debug($rec_off['t3ver_stage']);
00748                 switch((int)$rec_off['t3ver_stage'])    {
00749                         case 0:
00750                                 $sId = 1;
00751                                 $sLabel = 'Editing';    // TODO Localize
00752                                 $color = '#666666';     // TODO Use CSS?
00753                                 $label = 'Comment for Reviewer:';       // TODO Localize
00754                                 $titleAttrib = 'Send to Review';        // TODO Localize
00755                         break;
00756                         case 1:
00757                                 $sId = 10;
00758                                 $sLabel = 'Review';     // TODO Localize
00759                                 $color = '#6666cc';     // TODO Use CSS?
00760                                 $label = 'Comment for Publisher:';      // TODO Localize
00761                                 $titleAttrib = 'Approve for Publishing';        // TODO Localize
00762                         break;
00763                         case 10:
00764                                 $sLabel = 'Publish';    // TODO Localize
00765                                 $color = '#66cc66';     // TODO Use CSS?
00766                         break;
00767                         case -1:
00768                                 $sLabel = $this->doc->icons(2).'Rejected';      // TODO Localize
00769                                 $sId = 0;
00770                                 $color = '#ff0000';     // TODO Use CSS?
00771                                 $label = 'Comment:';    // TODO Localize
00772                                 $titleAttrib = 'Reset stage';   // TODO Localize
00773                         break;
00774                         default:
00775                                 $sLabel = 'Undefined';  // TODO Localize
00776                                 $sId = 0;
00777                                 $color = '';
00778                         break;
00779                 }
00780 #debug($sId);
00781 
00782                 $raiseOk = !$GLOBALS['BE_USER']->workspaceCannotEditOfflineVersion($table,$rec_off);
00783 
00784                 if ($raiseOk && $rec_off['t3ver_stage']!=-1)    {
00785                         // TODO Localize
00786                         $onClick = 'var commentTxt=window.prompt("Please explain why you reject:","");
00787                                                         if (commentTxt!=null) {window.location.href="'.$this->doc->issueCommand(
00788                                                         '&cmd['.$table.']['.$rec_off['uid'].'][version][action]=setStage'.
00789                                                         '&cmd['.$table.']['.$rec_off['uid'].'][version][stageId]=-1'
00790                                                         ).'&cmd['.$table.']['.$rec_off['uid'].'][version][comment]="+escape(commentTxt);}'.
00791                                                         ' return false;';
00792                                 // Reject:
00793                         $actionLinks.=
00794                                 '<a href="#" onclick="'.htmlspecialchars($onClick).'">'.
00795                                 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/down.gif','width="14" height="14"').' alt="" align="top" title="Reject" />'.
00796                                 '</a>';
00797                 } else {
00798                                 // Reject:
00799                         $actionLinks.=
00800                                 '<img src="'.$this->doc->backPath.'gfx/clear.gif" width="14" height="14" alt="" align="top" title="" />';
00801                 }
00802 
00803                 // TODO Use CSS?
00804                 $actionLinks.= '<span style="background-color: '.$color.'; color: white;">'.$sLabel.'</span>';
00805 
00806                         // Raise
00807                 if ($raiseOk)   {
00808                         $onClick = 'var commentTxt=window.prompt("'.$label.'","");
00809                                                         if (commentTxt!=null) {window.location.href="'.$this->doc->issueCommand(
00810                                                         '&cmd['.$table.']['.$rec_off['uid'].'][version][action]=setStage'.
00811                                                         '&cmd['.$table.']['.$rec_off['uid'].'][version][stageId]='.$sId
00812                                                         ).'&cmd['.$table.']['.$rec_off['uid'].'][version][comment]="+escape(commentTxt);}'.
00813                                                         ' return false;';
00814                         if ($rec_off['t3ver_stage']!=10)        {
00815                                 $actionLinks.=
00816                                         '<a href="#" onclick="'.htmlspecialchars($onClick).'">'.
00817                                         '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/up.gif','width="14" height="14"').' alt="" align="top" title="'.htmlspecialchars($titleAttrib).'" />'.
00818                                         '</a>';
00819 
00820                                 $this->stageIndex[$sId][$table][] = $rec_off['uid'];
00821                         }
00822                 }
00823 
00824                 return $actionLinks;
00825         }
00826 
00836         function displayWorkspaceOverview_commandLinks($table,&$rec_on,&$rec_off,$vType)        {
00837                 global  $LANG;
00838 
00839                 if ($this->publishAccess && (!($GLOBALS['BE_USER']->workspaceRec['publish_access']&1) || (int)$rec_off['t3ver_stage']===10))    {
00840                         $actionLinks =
00841                                 '<a href="'.htmlspecialchars($this->doc->issueCommand(
00842                                                 '&cmd['.$table.']['.$rec_on['uid'].'][version][action]=swap'.
00843                                                 '&cmd['.$table.']['.$rec_on['uid'].'][version][swapWith]='.$rec_off['uid']
00844                                                 )).'">'.
00845                                 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert1.gif','width="14" height="14"').' alt="" align="top" title="' . $LANG->getLL('img_title_publish') . '" />'.
00846                                 '</a>';
00847                         if ($GLOBALS['BE_USER']->workspaceSwapAccess() && (int)$rec_on['t3ver_state']!==1 && (int)$rec_off['t3ver_state']!==2)  {
00848                                 $actionLinks.=
00849                                         '<a href="'.htmlspecialchars($this->doc->issueCommand(
00850                                                         '&cmd['.$table.']['.$rec_on['uid'].'][version][action]=swap'.
00851                                                         '&cmd['.$table.']['.$rec_on['uid'].'][version][swapWith]='.$rec_off['uid'].
00852                                                         '&cmd['.$table.']['.$rec_on['uid'].'][version][swapIntoWS]=1'
00853                                                         )).'">'.
00854                                         '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/swap.png','width="14" height="14"').' alt="" align="top" title="' . $LANG->getLL('img_title_swap') . '" />'.
00855                                         '</a>';
00856                         }
00857                 }
00858 
00859                 if (!$GLOBALS['BE_USER']->workspaceCannotEditOfflineVersion($table,$rec_off))   {
00860 
00861                         if ($GLOBALS['BE_USER']->workspace!==0) {
00862                                         // Release
00863                                 $confirm = $LANG->JScharCode($LANG->getLL('remove_from_ws_confirmation'));
00864                                 $actionLinks.=
00865                                         '<a href="'.htmlspecialchars($this->doc->issueCommand('&cmd['.$table.']['.$rec_off['uid'].'][version][action]=clearWSID')).'" onclick="return confirm(' . $confirm . ');">'.
00866                                         '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/group_clear.gif','width="14" height="14"').' alt="" align="top" title="' . $LANG->getLL('img_title_remove_from_ws') . '" />'.
00867                                         '</a>';
00868                         }
00869 
00870                                 // Edit
00871                         if ($table==='pages' && $vType!=='element')     {
00872                                 $tempUid = ($vType==='branch' || $GLOBALS['BE_USER']->workspace===0 ? $rec_off['uid'] : $rec_on['uid']);
00873                                 $actionLinks.=
00874                                         '<a href="#" onclick="top.loadEditId('.$tempUid.');top.goToModule(\''.$this->pageModule.'\'); return false;">'.
00875                                         '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,t3lib_extMgm::extRelPath('cms').'layout/layout.gif','width="14" height="12"').' title="' . $LANG->getLL('img_title_edit_page') . '" alt="" />'.
00876                                         '</a>';
00877                         } else {
00878                                 $params = '&edit['.$table.']['.$rec_off['uid'].']=edit';
00879                                 $actionLinks.=
00880                                         '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->doc->backPath)).'">'.
00881                                         '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/edit2.gif','width="12" height="12"').' title="' . $LANG->getLL('img_title_edit_element') . '" alt="" />'.
00882                                         '</a>';
00883                         }
00884                 }
00885 
00886                         // History/Log
00887                 $actionLinks.=
00888                         '<a href="'.htmlspecialchars($this->doc->backPath.'show_rechis.php?element='.rawurlencode($table.':'.$rec_off['uid']).'&returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'))).'">'.
00889                         '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/history2.gif','width="13" height="12"').' title="' . $LANG->getLL('img_title_show_log') . '" alt="" />'.
00890                         '</a>';
00891 
00892                         // View
00893                 if ($table==='pages')   {
00894                         $tempUid = ($vType==='branch' || $GLOBALS['BE_USER']->workspace===0 ? $rec_off['uid'] : $rec_on['uid']);
00895                         $actionLinks.=
00896                                 '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($tempUid,$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($tempUid))).'">'.
00897                                 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/zoom.gif','width="12" height="12"').' title="" alt="" />'.
00898                                 '</a>';
00899                 }
00900 
00901                 return $actionLinks;
00902         }
00903 
00912         function displayWorkspaceOverview_commandLinksSub($table,$rec,$origId)  {
00913                 global $LANG;
00914 
00915                 $uid = $rec['uid'];
00916                 if ($origId || $GLOBALS['BE_USER']->workspace===0)      {
00917                         if (!$GLOBALS['BE_USER']->workspaceCannotEditRecord($table,$rec))       {
00918                                         // Edit
00919                                 if ($table==='pages')   {
00920                                         $actionLinks.=
00921                                                 '<a href="#" onclick="top.loadEditId('.$uid.');top.goToModule(\''.$this->pageModule.'\'); return false;">'.
00922                                                 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,t3lib_extMgm::extRelPath('cms').'layout/layout.gif','width="14" height="12"').' title="' . $LANG->getLL('img_title_edit_page') . '" alt="" />'.
00923                                                 '</a>';
00924                                 } else {
00925                                         $params = '&edit['.$table.']['.$uid.']=edit';
00926                                         $actionLinks.=
00927                                                 '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->doc->backPath)).'">'.
00928                                                 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/edit2.gif','width="12" height="12"').' title="' . $LANG->getLL('img_title_edit_element') . '" alt="" />'.
00929                                                 '</a>';
00930                                 }
00931                         }
00932 
00933                                 // History/Log
00934                         $actionLinks.=
00935                                 '<a href="'.htmlspecialchars($this->doc->backPath.'show_rechis.php?element='.rawurlencode($table.':'.$uid).'&returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'))).'">'.
00936                                 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/history2.gif','width="13" height="12"').' title="' . $LANG->getLL('img_title_show_log') . '" alt="" />'.
00937                                 '</a>';
00938                 }
00939 
00940                         // View
00941                 if ($table==='pages')   {
00942                         $actionLinks.=
00943                                 '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($uid,$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($uid))).'">'.
00944                                 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/zoom.gif','width="12" height="12"').' title="" alt="" />'.
00945                                 '</a>';
00946                 }
00947 
00948                 return $actionLinks;
00949         }
00950 
00962         function displayWorkspaceOverview_setInPageArray(&$pArray,$rlArr,$table,$row)   {
00963 
00964                         // Initialize:
00965                 ksort($rlArr);
00966                 reset($rlArr);
00967                 if (!$rlArr[0]['uid'])          array_shift($rlArr);
00968 
00969                         // Get and remove first element in root line:
00970                 $cEl = current($rlArr);
00971                 $pUid = $cEl['t3ver_oid'] ? $cEl['t3ver_oid'] : $cEl['uid'];            // Done to pile up "false versions" in the right branch...
00972 
00973                 $pArray[$pUid] = $cEl['title'];
00974                 array_shift($rlArr);
00975 
00976                         // If there are elements left in the root line, call this function recursively (to build $pArray in depth)
00977                 if (count($rlArr))      {
00978                         if (!isset($pArray[$pUid.'.'])) $pArray[$pUid.'.'] = array();
00979                         $this->displayWorkspaceOverview_setInPageArray($pArray[$pUid.'.'],$rlArr,$table,$row);
00980                 } else {        // If this was the last element, set the value:
00981                         $pArray[$pUid.'_'][$table][$row['t3ver_oid']][] = $row;
00982                 }
00983         }
00984 
00993         function subElements($uid,$treeLevel,$origId=0) {
00994                 global $TCA;
00995 
00996                 if ($GLOBALS['BE_USER']->workspace===0 || !$this->MOD_SETTINGS['expandSubElements'])    {       // In online workspace we have a reduced view because otherwise it will bloat the listing:
00997                         return '<br/>
00998                                         <img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/ol/joinbottom.gif','width="18" height="16"').' align="top" alt="" title="" />'.
00999                                         ($origId ?
01000                                                 '<a href="'.htmlspecialchars($this->doc->backPath.t3lib_extMgm::extRelPath('version').'cm1/index.php?id='.$uid.'&details='.rawurlencode('pages:'.$uid).'&returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'))).'">'.
01001                                                 '<span class="typo3-dimmed"><em>[Sub elements, click for details]</em><span></a>' :
01002                                                 '<span class="typo3-dimmed"><em>[Sub elements]</em><span>');
01003                 } else {        // For an offline workspace, show sub elements:
01004 
01005                         $tCell = array();
01006 
01007                                 // Find records that follow pages when swapping versions:
01008                         $recList = array();
01009                         foreach($TCA as $tN => $tCfg)   {
01010                                 if ($tN!='pages' && ($treeLevel>0 || $TCA[$tN]['ctrl']['versioning_followPages']))      {
01011                                         $this->subElements_getNonPageRecords($tN, $uid, $recList);
01012                                 }
01013                         }
01014 
01015                                 // Render records collected above:
01016                         $elCount = count($recList)-1;
01017                         foreach($recList as $c => $comb)        {
01018                                 list($tN,$rec) = $comb;
01019 
01020                                 $this->subElements_renderItem(
01021                                         $tCell,
01022                                         $tN,
01023                                         $uid,
01024                                         $rec,
01025                                         $origId,
01026                                         $c==$elCount && $treeLevel==0 ? 1 : 0,          // If true, will show bottom-join icon.
01027                                         ''
01028                                 );
01029                         }
01030 
01031                                 // For branch, dive into the subtree:
01032                         if ($treeLevel>0) {
01033 
01034                                         // Drawing tree:
01035                                 $tree = t3lib_div::makeInstance('t3lib_pageTree');
01036                                 $tree->init('AND '.$GLOBALS['BE_USER']->getPagePermsClause(1));
01037                                 $tree->makeHTML = 2;            // 2=Also rendering depth-data into the result array
01038                                 $tree->getTree($uid, 99, '');
01039 
01040                                         // Traverse page tree:
01041                                 foreach($tree->tree as $data)   {
01042 
01043                                                 // Render page in table cell:
01044                                         $this->subElements_renderItem(
01045                                                 $tCell,
01046                                                 'pages',
01047                                                 $uid,
01048                                                 t3lib_BEfunc::getRecord('pages',$data['row']['uid']),   // Needs all fields, at least more than what is given in $data['row']...
01049                                                 $origId,
01050                                                 2,              // 2=the join icon and icon for the record is not rendered for pages (where all is in $data['HTML']
01051                                                 $data['HTML']
01052                                         );
01053 
01054                                                 // Find all records from page and collect in $recList:
01055                                         $recList = array();
01056                                         foreach($TCA as $tN => $tCfg)   {
01057                                                 if ($tN!=='pages')      {
01058                                                         $this->subElements_getNonPageRecords($tN, $data['row']['uid'], $recList);
01059                                                 }
01060                                         }
01061 
01062                                                 // Render records collected above:
01063                                         $elCount = count($recList)-1;
01064                                         foreach($recList as $c => $comb)        {
01065                                                 list($tN,$rec) = $comb;
01066 
01067                                                 $this->subElements_renderItem(
01068                                                         $tCell,
01069                                                         $tN,
01070                                                         $uid,
01071                                                         $rec,
01072                                                         $origId,
01073                                                         $c==$elCount?1:0,       // If true, will show bottom-join icon.
01074                                                         $data['HTML_depthData']
01075                                                 );
01076                                         }
01077                                 }
01078                         }
01079 
01080                         return '
01081                                         <!-- Sub-element tree for versions -->
01082                                         <table border="0" cellpadding="0" cellspacing="1" class="ver-subtree">
01083                                                 '.implode('',$tCell).'
01084                                         </table>';
01085                 }
01086         }
01087 
01096         function subElements_getNonPageRecords($tN, $uid, &$recList)    {
01097                 global $TCA;
01098 
01099                 $records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
01100                         '*',
01101                         $tN,
01102                         'pid='.intval($uid).
01103                                 ($TCA[$tN]['ctrl']['versioningWS'] ? ' AND t3ver_state=0' : '').
01104                                 t3lib_BEfunc::deleteClause($tN),
01105                         '',
01106                         $TCA[$tN]['ctrl']['sortby'] ? $TCA[$tN]['ctrl']['sortby'] : $GLOBALS['TYPO3_DB']->stripOrderBy($TCA[$tN]['ctrl']['default_sortby'])
01107                 );
01108 
01109                 foreach($records as $rec)       {
01110                         $recList[] = array($tN,$rec);
01111                 }
01112         }
01113 
01126         function subElements_renderItem(&$tCell,$tN,$uid,$rec,$origId,$iconMode,$HTMLdata)      {
01127                 global $TCA;
01128 
01129                         // Initialize:
01130                 $origUidFields = $TCA[$tN]['ctrl']['origUid'];
01131                 $diffCode = '';
01132 
01133                 if ($origUidFields)     {       // If there is a field for this table with original uids we will use that to connect records:
01134                         if (!$origId)   {       // In case we are displaying the online originals:
01135                                 $this->targets['orig_'.$uid.'_'.$tN.'_'.$rec['uid']] = $rec;    // Build up target array (important that
01136                                 $tdParams =  ' id="orig_'.$uid.'_'.$tN.'_'.$rec['uid'].'" class="typo3-ver"';           // Setting ID of the table row
01137                         } else {        // Version branch:
01138                                 if ($this->targets['orig_'.$origId.'_'.$tN.'_'.$rec[$origUidFields]])   {       // If there IS a corresponding original record...:
01139 
01140                                                 // Prepare Table row parameters:
01141                                         $tdParams =  ' onmouseover="hlSubelements(\''.$origId.'_'.$tN.'_'.$rec[$origUidFields].'\', \''.$uid.'_'.$tN.'_'.$rec[$origUidFields].'\', 1, '.($this->MOD_SETTINGS['diff']==2?1:0).');"'.
01142                                                                 ' onmouseout="hlSubelements(\''.$origId.'_'.$tN.'_'.$rec[$origUidFields].'\', \''.$uid.'_'.$tN.'_'.$rec[$origUidFields].'\', 0, '.($this->MOD_SETTINGS['diff']==2?1:0).');"'.
01143                                                                 ' id="ver_'.$uid.'_'.$tN.'_'.$rec[$origUidFields].'" class="typo3-ver"';
01144 
01145                                                 // Create diff view:
01146                                         if ($this->MOD_SETTINGS['diff'])        {
01147                                                 list($diffHTML,$diffPct) = $this->createDiffView($tN, $rec, $this->targets['orig_'.$origId.'_'.$tN.'_'.$rec[$origUidFields]]);
01148 
01149                                                 if ($this->MOD_SETTINGS['diff']==2)     {
01150                                                         $diffCode =
01151                                                                 ($diffPct ? '<span class="nobr">'.$diffPct.'% change</span>' : '-').
01152                                                                 '<div style="visibility: hidden; position: absolute;" id="diff_'.$uid.'_'.$tN.'_'.$rec[$origUidFields].'" class="diffLayer">'.
01153                                                                 $diffHTML.
01154                                                                 '</div>';
01155                                                 } else {
01156                                                         $diffCode =
01157                                                                 ($diffPct<0 ? 'N/A' : ($diffPct ? $diffPct.'% change:' : '')).
01158                                                                 $diffHTML;
01159                                                 }
01160                                         }
01161 
01162                                                 // Unsetting the target fields allows us to mark all originals without a version in the subtree (see ->markupNewOriginals())
01163                                         unset($this->targets['orig_'.$origId.'_'.$tN.'_'.$rec[$origUidFields]]);
01164                                 } else {        // No original record, so must be new:
01165                                         $tdParams =  ' class="typo3-ver-new"';
01166                                 }
01167                         }
01168                 } else {        // If no original uid column is supported for this table we are forced NOT to display any diff or highlighting.
01169                         $tdParams = ' class="typo3-ver-noComp"';
01170                 }
01171 
01172                         // Compile the cell:
01173                 $tCell[] = '
01174                                                 <tr'.$tdParams.'>
01175                                                         <td class="iconTitle">'.
01176                                                                 $HTMLdata.
01177                                                                 ($iconMode < 2 ?
01178                                                                         '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/ol/join'.($iconMode ? 'bottom' : '').'.gif','width="18" height="16"').' alt="" />'.
01179                                                                         t3lib_iconWorks::getIconImage($tN, $rec, $this->doc->backPath,'') : '').
01180                                                                 t3lib_BEfunc::getRecordTitle($tN, $rec, TRUE).
01181                                                         '</td>
01182                                                         <td class="cmdCell">'.
01183                                                                 $this->displayWorkspaceOverview_commandLinksSub($tN,$rec,$origId).
01184                                                         '</td>'.($origId ? '<td class="diffCell">'.
01185                                                                 $diffCode.
01186                                                         '</td>':'').'
01187                                                 </tr>';
01188         }
01189 
01195         function markupNewOriginals()   {
01196 
01197                 if (count($this->targets))      {
01198                         $scriptCode = '';
01199                         foreach($this->targets as $key => $rec) {
01200                                 $scriptCode.='
01201                                         document.getElementById(\''.$key.'\').attributes.getNamedItem("class").nodeValue = \'typo3-ver-new\';
01202                                 ';
01203                         }
01204 
01205                         return $this->doc->wrapScriptTags($scriptCode);
01206                 }
01207         }
01208 
01217         function createDiffView($table, $diff_1_record, $diff_2_record) {
01218                 global $TCA, $LANG;
01219 
01220                         // Initialize:
01221                 $pctChange = 'N/A';
01222 
01223                         // Check that records are arrays:
01224                 if (is_array($diff_1_record) && is_array($diff_2_record))       {
01225 
01226                                 // Load full table description and initialize diff-object:
01227                         t3lib_div::loadTCA($table);
01228                         $t3lib_diff_Obj = t3lib_div::makeInstance('t3lib_diff');
01229 
01230                                 // Add header row:
01231                         $tRows = array();
01232                         $tRows[] = '
01233                                 <tr class="bgColor5 tableheader">
01234                                         <td>' . $LANG->getLL('diffview_label_field_name') . '</td>
01235                                         <td width="98%" nowrap="nowrap">' . $LANG->getLL('diffview_label_colored_diff_view') . '</td>
01236                                 </tr>
01237                         ';
01238 
01239                                 // Initialize variables to pick up string lengths in:
01240                         $allStrLen = 0;
01241                         $diffStrLen = 0;
01242 
01243                                 // Traversing the first record and process all fields which are editable:
01244                         foreach($diff_1_record as $fN => $fV)   {
01245                                 if ($TCA[$table]['columns'][$fN] && $TCA[$table]['columns'][$fN]['config']['type']!='passthrough' && !t3lib_div::inList('t3ver_label',$fN))     {
01246 
01247                                                 // Check if it is files:
01248                                         $isFiles = FALSE;
01249                                         if (strcmp(trim($diff_1_record[$fN]),trim($diff_2_record[$fN])) &&
01250                                                         $TCA[$table]['columns'][$fN]['config']['type']=='group' &&
01251                                                         $TCA[$table]['columns'][$fN]['config']['internal_type']=='file')        {
01252 
01253                                                         // Initialize:
01254                                                 $uploadFolder = $TCA[$table]['columns'][$fN]['config']['uploadfolder'];
01255                                                 $files1 = array_flip(t3lib_div::trimExplode(',', $diff_1_record[$fN],1));
01256                                                 $files2 = array_flip(t3lib_div::trimExplode(',', $diff_2_record[$fN],1));
01257 
01258                                                         // Traverse filenames and read their md5 sum:
01259                                                 foreach($files1 as $filename => $tmp)   {
01260                                                         $files1[$filename] = @is_file(PATH_site.$uploadFolder.'/'.$filename) ? md5(t3lib_div::getUrl(PATH_site.$uploadFolder.'/'.$filename)) : $filename;
01261                                                 }
01262                                                 foreach($files2 as $filename => $tmp)   {
01263                                                         $files2[$filename] = @is_file(PATH_site.$uploadFolder.'/'.$filename) ? md5(t3lib_div::getUrl(PATH_site.$uploadFolder.'/'.$filename)) : $filename;
01264                                                 }
01265 
01266                                                         // Implode MD5 sums and set flag:
01267                                                 $diff_1_record[$fN] = implode(' ',$files1);
01268                                                 $diff_2_record[$fN] = implode(' ',$files2);
01269                                                 $isFiles = TRUE;
01270                                         }
01271 
01272                                                 // If there is a change of value:
01273                                         if (strcmp(trim($diff_1_record[$fN]),trim($diff_2_record[$fN])))        {
01274 
01275 
01276                                                         // Get the best visual presentation of the value and present that:
01277                                                 $val1 = t3lib_BEfunc::getProcessedValue($table,$fN,$diff_2_record[$fN],0,1);
01278                                                 $val2 = t3lib_BEfunc::getProcessedValue($table,$fN,$diff_1_record[$fN],0,1);
01279 
01280                                                         // Make diff result and record string lenghts:
01281                                                 $diffres = $t3lib_diff_Obj->makeDiffDisplay($val1,$val2,$isFiles?'div':'span');
01282                                                 $diffStrLen+= $t3lib_diff_Obj->differenceLgd;
01283                                                 $allStrLen+= strlen($val1.$val2);
01284 
01285                                                         // If the compared values were files, substituted MD5 hashes:
01286                                                 if ($isFiles)   {
01287                                                         $allFiles = array_merge($files1,$files2);
01288                                                         foreach($allFiles as $filename => $token)       {
01289                                                                 if (strlen($token)==32 && strstr($diffres,$token))      {
01290                                                                         $filename =
01291                                                                                 t3lib_BEfunc::thumbCode(array($fN=>$filename),$table,$fN,$this->doc->backPath).
01292                                                                                 $filename;
01293                                                                         $diffres = str_replace($token,$filename,$diffres);
01294                                                                 }
01295                                                         }
01296                                                 }
01297 
01298                                                         // Add table row with result:
01299                                                 $tRows[] = '
01300                                                         <tr class="bgColor4">
01301                                                                 <td>'.htmlspecialchars($GLOBALS['LANG']->sL(t3lib_BEfunc::getItemLabel($table,$fN))).'</td>
01302                                                                 <td width="98%">'.$diffres.'</td>
01303                                                         </tr>
01304                                                 ';
01305                                         } else {
01306                                                         // Add string lengths even if value matched - in this was the change percentage is not high if only a single field is changed:
01307                                                 $allStrLen+=strlen($diff_1_record[$fN].$diff_2_record[$fN]);
01308                                         }
01309                                 }
01310                         }
01311 
01312                                 // Calculate final change percentage:
01313                         $pctChange = $allStrLen ? ceil($diffStrLen*100/$allStrLen) : -1;
01314 
01315                                 // Create visual representation of result:
01316                         if (count($tRows)>1)    {
01317                                 $content.= '<table border="0" cellpadding="1" cellspacing="1" class="diffTable">'.implode('',$tRows).'</table>';
01318                         } else {
01319                                 $content.= '<span class="nobr">'.$this->doc->icons(1).$LANG->getLL('diffview_complete_match').'</span>';
01320                         }
01321                 } else $content.= $this->doc->icons(3).$LANG->getLL('diffview_cannot_find_records');
01322 
01323                         // Return value:
01324                 return array($content,$pctChange);
01325         }
01326 
01327 
01328 
01329 
01330 
01331 
01332 
01333 
01334 
01335 
01336 
01337 
01338         /********************************
01339          *
01340          * Module content: Workspace list
01341          *
01342          ********************************/
01343 
01349         function moduleContent_workspaceList()  {
01350                 // Original Kasper's TODO: Workspace listing
01351                 //
01352                 //      - LISTING: Shows list of available workspaces for user. Used can see title, description, publication time, freeze-state, db-mount, member users/groups etc. Current workspace is indicated.
01353                 //      - SWITCHING: Switching between available workspaces is done by a button shown for each in the list
01354                 //      - ADMIN: Administrator of a workspace can click an edit-button linking to a form where he can edit the workspace. Users and groups should be selected based on some filtering so he cannot select groups he is not a member off himself (or some other rule... like for permission display with blinded users/groups)
01355                 //      - CREATE: If allowed, the user can create a new workspace which brings up a form where he can enter basic data. This is saved by a local instance of tcemain with forced admin-rights (creation in pid=0!).
01356                 return $this->workspaceList_displayUserWorkspaceList();
01357         }
01358 
01364         function workspaceList_displayUserWorkspaceList()       {
01365                 global  $BACK_PATH, $LANG;
01366 
01367                         // table header
01368                 $content = $this->workspaceList_displayUserWorkspaceListHeader();
01369 
01370                         // get & walk workspace list generating content
01371                 $wkspList = $this->workspaceList_getUserWorkspaceList();
01372                 $rowNum = 1;
01373                 foreach ($wkspList as $wksp)    {
01374                         $currentWksp = ($GLOBALS['BE_USER']->workspace == $wksp['uid']);
01375 
01376                         // Each workspace data occupies two rows:
01377                         // (1) Folding + Icons + Title + Description
01378                         // (2) Information about workspace (initially hidden)
01379 
01380                         $cssClass = ($currentWksp ? 'bgColor3' : 'bgColor4');
01381                                 // Start first row
01382                         $content .= '<tr class="' . $cssClass . '">';
01383 
01384                                 // row #1, column #1: expand icon
01385                         $content .= '<td>' .
01386                                                 '<a href="javascript:expandCollapse(' . $rowNum . ')">' .
01387                                                 '<img ' . t3lib_iconWorks::skinImg($BACK_PATH, 'gfx/ol/plusbullet.gif', 'width="18" height="16"') . ' id="wl_' . $rowNum . 'i" border="0" hspace="1" alt="' . $LANG->getLL('img_title_show_more') . '" />' .
01388                                                 '</a></td>';
01389 
01390                                 // row #1, column #2: icon panel
01391                         $content .= '<td nowrap="nowrap">';     // Mozilla Firefox will attempt wrap due to `width="1"` on topmost column
01392                         $content .= $this->workspaceList_displayIcons($currentWksp, $wksp);
01393                         $content .= '</td>';
01394 
01395                                 // row #1, column #3: current workspace indicator
01396                         $content .= '<td nowrap="nowrap" style="text-align: center">';  // Mozilla Firefox will attempt wrap due to `width="1"` on topmost column
01397                         $content .= (!$currentWksp ? '&nbsp;' : '<img ' . t3lib_iconWorks::skinImg($BACK_PATH, 'gfx/icon_ok.gif', 'width="18" height="16"') . ' id="wl_' . $rowNum . 'i" border="0" hspace="1" alt="' . $LANG->getLL('img_title_current_workspace') . '" />');
01398                         $content .= '</td>';
01399 
01400                                 // row #1, column #4 and 5: title and description
01401                         $content .= '<td nowrap="nowrap">' . $wksp['title'] . '</td>' .
01402                                                 '<td>' . nl2br($wksp['description']) . '</td>';
01403                         $content .= '</tr>';
01404 
01405                                 // row #2, column #1 and #2
01406                         $content .= '<tr id="wl_' . $rowNum . '" class="bgColor" style="display: none">';
01407                         $content .= '<td colspan="2" style="border-right: none;">&nbsp;</td>';
01408 
01409                                 // row #2, column #3, #4 and #4
01410                         $content .= '<td colspan="3" style="border-left: none;">' .
01411                                                 $this->workspaceList_formatWorkspaceData($wksp) .
01412                                                 '</td>';
01413 
01414                         $content .= '</tr>';
01415                         $rowNum++;
01416                 }
01417                 $content .= '</table>';
01418 
01419                 $newWkspUrl = 'workspaceforms.php?action=new';
01420 
01421                         // workspace creation link
01422                 if ($GLOBALS['BE_USER']->isAdmin() || 0 != ($GLOBALS['BE_USER']->groupData['workspace_perms'] & 4))     {
01423                         $content .= '<br /><a href="' . $newWkspUrl . '">' .
01424                                                 '<img ' .
01425                                                 t3lib_iconWorks::skinImg($BACK_PATH, 'gfx/new_el.gif', 'width="11" height="12"') .
01426                                                 ' alt="' . $LANG->getLL('img_title_create_new_workspace'). '" id="ver-wl-new-workspace-icon" />' .
01427                                                 $LANG->getLL('link_text_create_new_workspace') . '</a>';
01428                 }
01429                 return $content;
01430         }
01431 
01432 
01433 
01434 
01435 
01441         function workspaceList_getUserWorkspaceList()   {
01442                         // Get BE users if necessary
01443                 if (!is_array($this->be_user_Array))    {
01444                         $this->be_user_Array = t3lib_BEfunc::getUserNames();
01445                 }
01446                         // Get list of all workspaces. Note: system workspaces will be always displayed before custom ones!
01447                 $workspaces = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*','sys_workspace','pid=0'.t3lib_BEfunc::deleteClause('sys_workspace'),'','title');
01448                 $availableWorkspaces = array();
01449 
01450                         // Live
01451                 $wksp = $this->workspaceList_createFakeWorkspaceRecord(0);
01452                 $wksp = $GLOBALS['BE_USER']->checkWorkspace($wksp);
01453                 if (false !== $wksp) {
01454                         $availableWorkspaces[] = $wksp;
01455                 }
01456 
01457                         // Draft
01458                 $wksp = $this->workspaceList_createFakeWorkspaceRecord(-1);
01459                 $wksp = $GLOBALS['BE_USER']->checkWorkspace($wksp);
01460                 if (false !== $wksp) {
01461                         $availableWorkspaces[] = $wksp;
01462                 }
01463 
01464                         // Custom
01465                 foreach($workspaces as $rec)    {
01466                                 // see if user can access this workspace in any way
01467                         if (false !== ($result = $GLOBALS['BE_USER']->checkWorkspace($rec)))    {
01468                                 $availableWorkspaces[] = $result;       // `$result` contains `$rec` plus access type through '_ACCESS' key
01469                         }
01470                 }
01471                 return $availableWorkspaces;
01472         }
01473 
01483         function workspaceList_formatWorkspaceData(&$wksp)      {
01484                 global $LANG;
01485 
01486                 $content = '<table cellspacing="1" cellpadding="1" width="100%" class="ver-wl-details-table">' .
01487                                 '<tr><td class="ver-wl-details-label"><b>' . $LANG->getLL('workspace_list_label_file_mountpoints') . '</b></td>' .
01488                                 '<td class="ver-wl-details">' . $this->workspaceList_getFileMountPoints($wksp) . '</td></tr>' .
01489                                 '<tr><td class="ver-wl-details-label"><b>' . $LANG->getLL('workspace_list_label_db_mountpoints') . '</b></td>' .
01490                                 '<td class="ver-wl-details">' . $this->workspaceList_getWebMountPoints($wksp) . '</td></tr>';
01491                 if ($wksp['uid'] > 0) {
01492                         // Displaying information below makes sence only for custom workspaces
01493                         $content .=
01494                                 '<tr><td class="ver-wl-details-label"><b>' . $LANG->getLL('workspace_list_label_frozen') . '</b></td>' .
01495                                 '<td class="ver-wl-details">' . $LANG->getLL($wksp['freeze'] ? 'workspace_list_label_frozen_yes' : 'workspace_list_label_frozen_no') . '</td></tr>' .
01496                                 '<tr><td class="ver-wl-details-label"><b>' . $LANG->getLL('workspace_list_label_publish_date') . '</b></td>' .
01497                                 '<td class="ver-wl-details">' . ($wksp['publish_time'] == 0 ? '&nbsp;&ndash;' : t3lib_BEfunc::datetime($wksp['publish_time'])) . '</td></tr>' .
01498                                 '<tr><td class="ver-wl-details-label"><b>' . $LANG->getLL('workspace_list_label_unpublish_date') . '</b></td>' .
01499                                 '<td class="ver-wl-details">' . ($wksp['unpublish_time'] == 0 ? '&nbsp;&ndash;' : t3lib_BEfunc::datetime($wksp['unpublish_time'])) . '</td></tr>' .
01500                                 '<tr><td class="ver-wl-details-label"><b>' . $LANG->getLL('workspace_list_label_your_access') . '</b></td>' .
01501                                 '<td class="ver-wl-details">' . $LANG->getLL('workspace_list_access_' . $wksp['_ACCESS']) . '</td></tr>' .
01502                                 '<tr><td class="ver-wl-details-label"><b>' . $LANG->getLL('workspace_list_label_workspace_users') . '</b></td>' .
01503                                 '<td class="ver-wl-details">' . $this->workspaceList_getUserList($wksp) . '</td></tr>';
01504                 }
01505                 else if ($GLOBALS['BE_USER']->isAdmin()) {
01506                         // show users for draft/live workspace only to admin users
01507                         $content .=     '<tr><td class="ver-wl-details-label"><b>' . $LANG->getLL('workspace_list_label_workspace_users') . '</b></td>' .
01508                                 '<td class="ver-wl-details">' . $this->workspaceList_getUserList($wksp) . '</td></tr>';
01509                 }
01510                 $content .= '</table>';
01511 
01512                 return $content;
01513         }
01514 
01515 
01516 
01517 
01518 
01525         function workspaceList_getWebMountPoints(&$wksp)        {
01526                 if ($wksp['uid'] <= 0) {
01527                         // system workspaces
01528                         return $GLOBALS['LANG']->getLL($wksp['uid'] == 0 ? 'workspace_list_db_mount_point_live' : 'workspace_list_db_mount_point_draft');
01529                 }
01530 
01531                 // here only if obtaining mount points for custom workspaces
01532 
01533                 // Warning: all fields needed for t3lib_iconWorks::getIconImage()!
01534                 $MPs = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'pages', 'deleted=0 AND uid IN (' . $GLOBALS['TYPO3_DB']->cleanIntList($wksp['db_mountpoints']) . ')', '', 'title');
01535                 $content_array = array();
01536                 if (count($MPs) > 0)    {
01537                         $isAdmin = $GLOBALS['BE_USER']->isAdmin();
01538                         if (!$isAdmin) {
01539                                 // We need to fetch user's mount point list (including MPS mounted from groups).
01540                                 // This list must not be affects by current user's workspace. It means we cannot use
01541                                 // $BE_USER->isInWebMount() to check mount points.
01542                                 $userMPs = explode(',', $GLOBALS['BE_USER']->dataLists['webmount_list']); // includes group data if necessary!
01543                         }
01544                         foreach ($MPs as $mp)   {
01545                                 if (!$isAdmin && !in_array($mp['uid'], $userMPs)) {
01546                                         // Show warning icon
01547                                         $title = $GLOBALS['LANG']->getLL('workspace_list_mount_point_inaccessible');
01548                                         $str = '<img ' . t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'], 'gfx/icon_warning.gif', 'width="18" height="16"') .
01549                                                         ' alt="' . $title . '" title="' . $title . '" align="absmiddle" />';
01550                                         $classAttr = 'class="ver-wl-mp-inacessible" ';
01551                                 }
01552                                 else {
01553                                         // normal icon
01554                                         $str = t3lib_iconWorks::getIconImage('pages', $mp, $GLOBALS['BACK_PATH'], ' align="absmiddle"');
01555                                         $classAttr = '';
01556                                 }
01557                                 // Will show UID on hover. Just convinient to user.
01558                                 $content_array[] = $str . '<span ' . $classAttr . 'title="UID: ' . $mp['uid'] . '">' . $mp['title'] . '</span>';
01559                         }
01560                 }
01561                 if (count($content_array) > 0) {
01562                         return implode('<br />', $content_array);
01563                 }
01564                 // no mount points
01565                 return $GLOBALS['LANG']->getLL('workspace_list_db_mount_point_custom');
01566         }
01567 
01574         function workspaceList_getFileMountPoints(&$wksp)       {
01575                 if ($wksp['uid'] == -1) {
01576                         // draft workspace - none!
01577                         return $GLOBALS['LANG']->getLL('workspace_list_file_mount_point_draft');
01578                 }
01579                 else if ($wksp['uid'] == 0) {
01580                         // live workspace
01581                         return $GLOBALS['LANG']->getLL('workspace_list_file_mount_point_live');
01582                 }
01583 
01584                 // Here if displaying information for custom workspace
01585 
01586                 // Warning: all fields needed for t3lib_iconWorks::getIconImage()!
01587                 $MPs = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'sys_filemounts', 'deleted=0 AND hidden=0 AND uid IN (' . $GLOBALS['TYPO3_DB']->cleanIntList($wksp['file_mountpoints']) . ')', '', 'title');
01588                 if (count($MPs) != 0)   {
01589                         // Has mount points
01590                         $isAdmin = $GLOBALS['BE_USER']->isAdmin();
01591                         if (!$isAdmin) {
01592                                 // We need to fetch user's mount point list (including MPS mounted from groups).
01593                                 // This list must not be affects by current user's workspace. It means we cannot use
01594                                 // $BE_USER->isInWebMount() to check mount points.
01595                                 $userMPs = explode(',', $GLOBALS['BE_USER']->dataLists['filemount_list']); // includes group data if necessary!
01596                         }
01597                         foreach ($MPs as $mp)   {
01598                                 if (!$isAdmin && !in_array($mp['uid'], $userMPs)) {
01599                                         // Show warning icon
01600                                         $title = $GLOBALS['LANG']->getLL('workspace_list_mount_point_inaccessible');
01601                                         $str = '<img ' . t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'], 'gfx/icon_warning.gif', 'width="18" height="16"') .
01602                                                         ' alt="' . $title . '" title="' . $title . '" align="absmiddle" />';
01603                                         $classAttr = 'class="ver-wl-mp-inacessible" ';
01604                                 }
01605                                 else {
01606                                         // normal icon
01607                                         $str = t3lib_iconWorks::getIconImage('sys_filemounts', $mp, $GLOBALS['BACK_PATH'], ' align="absmiddle"');
01608                                         $classAttr = '';
01609                                 }
01610                                 // Will show UID on hover. Just convinient to user.
01611                                 $content_array[] = $str . '<span ' . $classAttr . 'title="UID: ' . $mp['uid'] . '">' . $mp['title'] . '</span>';
01612                         }
01613                 }
01614                 if (count($content_array) > 0) {
01615                         return implode('<br />', $content_array);
01616                 }
01617                 // No file mount points
01618                 return $GLOBALS['LANG']->getLL('workspace_list_file_mount_point_custom');
01619         }
01620 
01627         function workspaceList_displayUserWorkspaceListHeader() {
01628                 global  $LANG;
01629                 // TODO CSH lables?
01630                 return '<table border="0" cellpadding="0" cellspacing="1" class="lrPadding workspace-overview ver-wl-table">
01631                         <tr class="bgColor5 tableheader">
01632                                 <td width="1">&nbsp;</td>
01633                                 <td width="1">&nbsp;</td>
01634                                 <td nowrap="nowrap">' . $LANG->getLL('workspace_list_label_current_workspace') . '</td>
01635                                 <td nowrap="nowrap">' . $LANG->getLL('workspace_list_label_workspace_title') . '</td>
01636                                 <td nowrap="nowrap">' . $LANG->getLL('workspace_list_label_workspace_description') . '</td>
01637                         </tr>';
01638         }
01639 
01640 
01647         function workspaceList_getUserList(&$wksp) {
01648                 global  $LANG;
01649 
01650                 if ($wksp['uid'] > 0) {
01651                         // custom workspaces
01652                         $content = $this->workspaceList_getUserListWithAccess($wksp['adminusers'], $LANG->getLL('workspace_list_label_owners')); // owners
01653                         $content .= $this->workspaceList_getUserListWithAccess($wksp['members'], $LANG->getLL('workspace_list_label_members')); // members
01654                         $content .= $this->workspaceList_getUserListWithAccess($wksp['reviewers'], $LANG->getLL('workspace_list_label_reviewers')); // reviewers
01655                         if ($content != '')     {
01656                                 $content = '<table cellpadding="0" cellspacing="1" width="100%" class="lrPadding workspace-overview">' . $content . '</table>';
01657                         } else {
01658                                 $content = $LANG->getLL($wksp['uid'] > 0 ? 'workspace_list_access_admins_only' : 'workspace_list_access_anyone');
01659                         }
01660                 }
01661                 else {
01662                         // live and draft workspace
01663                         $content = $this->workspaceList_getUserListForSysWorkspace($wksp);
01664                 }
01665                 return $content;
01666         }
01667 
01674         function workspaceList_getUserListForSysWorkspace(&$wksp) {
01675                 $option = ($wksp['uid'] == 0 ? 1 : 2);
01676                 $content_array = array();
01677                 foreach ($this->be_user_Array_full as $uid => $user) {
01678                         if ($user['admin'] != 0 || 0 != ($user['workspace_perms'] & $option)) {
01679                                 if ($uid == $GLOBALS['BE_USER']->user['uid']) {
01680                                         // highlight current user
01681                                         $tag0 = '<span class="ver-wl-current-user">';
01682                                         $tag1 = '</span>';
01683                                 }
01684                                 else {
01685                                         $tag0 = $tag1 = '';
01686                                 }
01687                                 $content_array[] = t3lib_iconWorks::getIconImage('be_users', $uid, $GLOBALS['BACK_PATH'], ' align="middle" alt="UID: ' . $uid . '"') .
01688                                                                         $tag0 . $user['username'] . $tag1;
01689                         }
01690                 }
01691                 return implode('<br />', $content_array);
01692         }
01693 
01701         function workspaceList_getUserListWithAccess(&$list, $access)   {
01702                 $content_array = array();
01703                 if ($list != '')        {
01704                         $userIDs = explode(',', $list);
01705 
01706                                 // get user names and sort
01707                         $regExp = '/^(be_[^_]+)_(\d+)$/';
01708                         $groups = false;
01709                         foreach ($userIDs as $userUID)  {
01710                                 $id = $userUID;
01711 
01712                                 if (preg_match($regExp, $userUID)) {
01713                                         $table = preg_replace($regExp, '\1', $userUID);
01714                                         $id = intval(preg_replace($regExp, '\2', $userUID));
01715                                         if ($table == 'be_users') {
01716                                                 // user
01717                                                 $icon = $GLOBALS['TCA']['be_users']['typeicons'][$this->be_user_Array[$id]['admin']];
01718                                                 if ($id == $GLOBALS['BE_USER']->user['uid']) {
01719                                                         // highlight current user
01720                                                         $tag0 = '<span class="ver-wl-current-user">';
01721                                                         $tag1 = '</span>';
01722                                                 }
01723                                                 else {
01724                                                         $tag0 = $tag1 = '';
01725                                                 }
01726                                                 $content_array[] = t3lib_iconWorks::getIconImage($table, $this->be_user_Array[$id], $GLOBALS['BACK_PATH'], ' align="middle" alt="UID: ' . $id . '"') .
01727                                                                                         $tag0 . $this->be_user_Array_full[$id]['username'] . $tag1;
01728                                         }
01729                                         else {
01730                                                 // group
01731                                                 if (false === $groups) {
01732                                                         $groups = t3lib_BEfunc::getGroupNames();
01733                                                 }
01734                                                 $content_array[] = t3lib_iconWorks::getIconImage($table, $groups[$id], $GLOBALS['BACK_PATH'], ' align="middle" alt="UID: ' . $id . '"') .
01735                                                                                         $groups[$id]['title'];
01736                                         }
01737                                 }
01738                                 else {
01739                                         // user id
01740                                         if ($userUID == $GLOBALS['BE_USER']->user['uid']) {
01741                                                 // highlight current user
01742                                                 $tag0 = '<span class="ver-wl-current-user">';
01743                                                 $tag1 = '</span>';
01744                                         }
01745                                         else {
01746                                                 $tag0 = $tag1 = '';
01747                                         }
01748                                         $content_array[] = t3lib_iconWorks::getIconImage('be_users', $this->be_user_Array[$id], $GLOBALS['BACK_PATH'], ' align="middle" alt="UID: ' . $id . '"') .
01749                                                                                 $tag0 . $this->be_user_Array_full[$userUID]['username'] . $tag1;
01750                                 }
01751                         }
01752                         sort($content_array);
01753                 }
01754                 else {
01755                         $content_array[] = '&nbsp;&ndash;';
01756                 }
01757 
01758                 $content = '<tr><td class="ver-wl-details-label ver-wl-details-user-list-label">';
01759                 // TODO CSH lable explaining access here?
01760                 $content .= '<b>' . $access . '</b></td>';
01761                 $content .= '<td class="ver-wl-details">' . implode('<br />', $content_array) . '</td></tr>';
01762                 return $content;
01763         }
01764 
01765 
01766 
01774         function workspaceList_displayIcons($currentWorkspace, &$wksp)  {
01775                 global  $BACK_PATH, $LANG;
01776 
01777                 $content = '';
01778                         // `edit workspace` button
01779                 if ($this->workspaceList_hasEditAccess($wksp))  {
01780                                 // User can modify workspace parameters, display corresponding link and icon
01781                         $editUrl = 'workspaceforms.php?action=edit&amp;wkspId=' . $wksp['uid'];
01782 
01783                         $content .= '<a href="' . $editUrl . '" />' .
01784                                         '<img ' . t3lib_iconWorks::skinImg($BACK_PATH, 'gfx/edit2.gif', 'width="11" height="12"') . ' border="0" alt="' . $LANG->getLL('workspace_list_icon_title_edit_workspace') . '" align="middle" hspace="1" />' .
01785                                         '</a>';
01786                 } else {
01787                                 // User can NOT modify workspace parameters, display space
01788                                 // Get only withdth and height from skinning API
01789                         $content .= '<img src="clear.gif" ' .
01790                                         t3lib_iconWorks::skinImg($BACK_PATH, 'gfx/edit2.gif', 'width="11" height="12"', 2) .
01791                                         ' border="0" alt="" hspace="1" align="middle" />';
01792                 }
01793                         // `switch workspace` button
01794                 if (!$currentWorkspace) {
01795                                 // Workspace switching button
01796                         $content .= '<a href="' .
01797                                         t3lib_div::getIndpEnv('SCRIPT_NAME') .
01798                                         '?changeWorkspace=' . $wksp['uid'] . '"/>' .
01799                                         '<img ' . t3lib_iconWorks::skinImg($BACK_PATH, 'gfx/switch.gif', 'width="11" height="10"') . ' border="0" alt="' . $LANG->getLL('workspace_list_icon_title_switch_workspace') . '" align="middle" hspace="1" />' .
01800                                         '</a>';
01801                 } else {
01802                                 // Current workspace: empty space instead of workspace switching button
01803                                 //
01804                                 // Here get only width and height from skinning API
01805                         $content .= '<img src="clear.gif" ' .
01806                                         t3lib_iconWorks::skinImg($BACK_PATH, 'gfx/switch.png', 'width="18" height="16"', 2) .
01807                                         ' border="0" alt="" hspace="1" align="middle" alt="" />';
01808                 }
01809                 return $content;
01810         }
01811 
01822         function workspaceList_hasEditAccess(&$wksp)    {
01823                 $access = &$wksp['_ACCESS'];
01824                 return ($wksp['uid'] > 0 && ($access == 'admin' || $access == 'owner'));
01825         }
01826 
01834         function workspaceList_createFakeWorkspaceRecord($uid)  {
01835                 global  $BE_USER;
01836 
01837                 $record = array(
01838                         'uid' => $uid,
01839                         'pid' => 0,                             // always 0!
01840                         'tstamp' => 0,                  // does not really matter
01841                         'deleted' => 0,
01842                         // TODO Localize all strings below
01843                         'title' => ($uid == 0 ? '[Live workspace]' : '[Draft workspace]'),              // TODO Localize this!
01844                         // TODO Localize all strings below
01845                         'description' => ($uid == 0 ? 'Live workspace' : 'Draft workspace'),    // TODO Localize this!
01846                         'adminusers' => '',
01847                         'members' => '',
01848                         'reviewers' => '',
01849                         'db_mountpoints' => '',         // TODO get mount points from user profile
01850                         'file_mountpoints' => '',       // TODO get mount points from user profile for live workspace only (uid == 0)
01851                         'publish_time' => 0,
01852                         'unpublish_time' => 0,
01853                         'freeze' => 0,
01854                         'live_edit' => ($uid == 0),
01855                         'vtypes' => 0,
01856                         'disable_autocreate' => 0,
01857                         'swap_modes' => 0,
01858                         'publish_access' => 0,
01859                         'stagechg_notification' => 0
01860                 );
01861                 return $record;
01862         }
01863 
01864 
01865 
01866 
01867 
01868 
01869 
01870 
01871 
01872 
01873 
01874 
01875 
01876 
01877 
01878 
01879 
01880 
01881 
01882 
01883 
01884 
01885 
01886 
01887         /**************************************
01888          *
01889          * Helper functions
01890          *
01891          *************************************/
01892 
01899         function formatVerId($verId)    {
01900                 return '1.'.$verId;
01901         }
01902 
01909         function formatWorkspace($wsid) {
01910 
01911                         // Render, if not cached:
01912                 if (!isset($this->formatWorkspace_cache[$wsid]))        {
01913                         switch($wsid)   {
01914                                 case -1:
01915                                         $this->formatWorkspace_cache[$wsid] = '[Draft]';
01916                                 break;
01917                                 case 0:
01918                                         $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...
01919                                 break;
01920                                 default:
01921                                         list($titleRec) = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('title','sys_workspace','uid='.intval($wsid).t3lib_BEfunc::deleteClause('sys_workspace'));
01922                                         $this->formatWorkspace_cache[$wsid] = '['.$wsid.'] '.$titleRec['title'];
01923                                 break;
01924                         }
01925                 }
01926 
01927                 return $this->formatWorkspace_cache[$wsid];
01928         }
01929 
01936         function formatCount($count)    {
01937                 global  $LANG;
01938 
01939                         // Render, if not cached:
01940                 if (!isset($this->formatCount_cache[$count]))   {
01941                         switch($count)  {
01942                                 case 0:
01943                                         $this->formatCount_cache[$count] = $LANG->getLL('workspace_list_publishing_count_draft');
01944                                 break;
01945                                 case 1:
01946                                         $this->formatCount_cache[$count] = $LANG->getLL('workspace_list_publishing_count_archive');
01947                                 break;
01948                                 default:
01949                                         $this->formatCount_cache[$count] = sprintf($LANG->getLL('workspace_list_publishing_count'), $count);
01950                                 break;
01951                         }
01952                 }
01953 
01954                 return $this->formatCount_cache[$count];
01955         }
01956 
01964         function versionsInOtherWS($table,$uid) {
01965 
01966                         // Check for duplicates:
01967                         // Select all versions of record NOT in this workspace:
01968                 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
01969                         't3ver_wsid',
01970                         $table,
01971                         'pid=-1
01972                                 AND t3ver_oid='.intval($uid).'
01973                                 AND t3ver_wsid!='.intval($GLOBALS['BE_USER']->workspace).'
01974                                 AND (t3ver_wsid=-1 OR t3ver_wsid>0)'.
01975                                 t3lib_BEfunc::deleteClause($table),
01976                         '',
01977                         't3ver_wsid',
01978                         '',
01979                         't3ver_wsid'
01980                 );
01981                 if (count($rows))       {
01982                         return implode(',',array_keys($rows));
01983                 }
01984         }
01985 
01994         function showStageChangeLog($table,$id,$stageCommands)  {
01995                 global  $LANG;
01996 
01997                 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
01998                         'log_data,tstamp,userid',
01999                         'sys_log',
02000                         'action=6 and details_nr=30
02001                                 AND tablename='.$GLOBALS['TYPO3_DB']->fullQuoteStr($table,'sys_log').'
02002                                 AND recuid='.intval($id)
02003                 );
02004 
02005                 $entry = array();
02006                 foreach($rows as $dat)  {
02007                         $data = unserialize($dat['log_data']);
02008                         $username = $this->be_user_Array[$dat['userid']] ? $this->be_user_Array[$dat['userid']]['username'] : '['.$dat['userid'].']';
02009 
02010                         switch($data['stage'])  {
02011                                 case 1:
02012                                         $text = $LANG->getLL('stage_sent_to_review');
02013                                 break;
02014                                 case 10:
02015                                         $text = $LANG->getLL('stage_approved_for_publish');
02016                                 break;
02017                                 case -1:
02018                                         $text = $LANG->getLL('stage_rejected');
02019                                 break;
02020                                 case 0:
02021                                         $text = $LANG->getLL('stage_reset_to_editing');
02022                                 break;
02023                                 default:
02024                                         $text = $LANG->getLL('stage_undefined');
02025                                 break;
02026                         }
02027                         $text = t3lib_BEfunc::datetime($dat['tstamp']).': ' . sprintf($text, $username);
02028                         $text.= ($data['comment']?'<br/>' . $LANG->getLL('stage_label_user_comment'). ' <em>'.$data['comment'].'</em>':'');
02029 
02030                         $entry[] = $text;
02031                 }
02032 
02033                 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>'.
02034                                 '<div class="logLayer" style="visibility: hidden; position: absolute;" id="log_'.$table.$id.'">'.implode('<hr/>',$entry).'</div>' : $stageCommands;
02035         }
02036 
02037 
02038 
02039 
02040 
02041 
02042 
02043 
02044         /**********************************
02045          *
02046          * Processing
02047          *
02048          **********************************/
02049 
02055         function publishAction()        {
02056 
02057                         // If "Publish" or "Swap" buttons are pressed:
02058                 if (t3lib_div::_POST('_publish') || t3lib_div::_POST('_swap'))  {
02059 
02060                                 // Initialize workspace object and request all pending versions:
02061                         $wslibObj = t3lib_div::makeInstance('wslib');
02062                         $cmd = $wslibObj->getCmdArrayForPublishWS($GLOBALS['BE_USER']->workspace, t3lib_div::_POST('_swap'));
02063 
02064                                 // Execute the commands:
02065                         $tce = t3lib_div::makeInstance('t3lib_TCEmain');
02066                         $tce->stripslashes_values = 0;
02067                         $tce->start(array(), $cmd);
02068                         $tce->process_cmdmap();
02069 
02070                         return $tce->errorLog;
02071                 }
02072         }
02073 }
02074 
02075 // Include extension?
02076 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/user/ws/index.php'])     {
02077         include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/user/ws/index.php']);
02078 }
02079 
02080 
02081 
02082 
02083 
02084 
02085 
02086 
02087 
02088 // Make instance:
02089 $SOBE = t3lib_div::makeInstance('SC_mod_user_ws_index');
02090 $SOBE->init();
02091 $SOBE->main();
02092 $SOBE->printContent();
02093 ?>