Fixed bug 14523: Missing icons in workspace modules
[Packages/TYPO3.CMS.git] / typo3 / mod / user / ws / index.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Module: Workspace manager
29 *
30 * $Id$
31 *
32 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
33 * @author Dmitry Dulepov <typo3@accio.lv>
34 */
35 /**
36 * [CLASS/FUNCTION INDEX of SCRIPT]
37 *
38 *
39 *
40 * 101: class SC_mod_user_ws_index extends t3lib_SCbase
41 *
42 * SECTION: Standard module initialization
43 * 128: function menuConfig()
44 * 175: function init()
45 * 233: function main()
46 * 280: function printContent()
47 *
48 * SECTION: Module content: Publish
49 * 310: function moduleContent_publish()
50 * 411: function displayVersionDetails($details)
51 * 420: function displayWorkspaceOverview()
52 *
53 * SECTION: Module content: Workspace list
54 * 461: function moduleContent_workspaceList()
55 * 476: function workspaceList_displayUserWorkspaceList()
56 * 553: function workspaceList_getUserWorkspaceList()
57 * 592: function workspaceList_formatWorkspaceData(&$wksp)
58 * 634: function workspaceList_getWebMountPoints(&$wksp)
59 * 683: function workspaceList_getFileMountPoints(&$wksp)
60 * 736: function workspaceList_displayUserWorkspaceListHeader()
61 * 756: function workspaceList_getUserList(&$wksp)
62 * 783: function workspaceList_getUserListForSysWorkspace(&$wksp)
63 * 810: function workspaceList_getUserListWithAccess(&$list, $access)
64 * 883: function workspaceList_displayIcons($currentWorkspace, &$wksp)
65 * 931: function workspaceList_hasEditAccess(&$wksp)
66 * 943: function workspaceList_createFakeWorkspaceRecord($uid)
67 *
68 * TOTAL FUNCTIONS: 20
69 * (This index is automatically created/updated by the extension "extdeveval")
70 *
71 */
72
73 // Initialize module:
74 unset($MCONF);
75 require ('conf.php');
76 require ($BACK_PATH.'init.php');
77 require ($BACK_PATH.'template.php');
78 $BE_USER->modAccess($MCONF,1);
79
80 // Include libraries of various kinds used inside:
81 $LANG->includeLLFile('EXT:lang/locallang_mod_user_ws.xml');
82 $LANG->includeLLFile('EXT:lang/locallang_misc.xml');
83 require_once(PATH_typo3.'mod/user/ws/class.wslib.php');
84 require_once(PATH_typo3.'mod/user/ws/class.wslib_gui.php');
85
86
87
88
89 /**
90 * Module: Workspace manager
91 *
92 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
93 * @package TYPO3
94 * @subpackage core
95 */
96 class SC_mod_user_ws_index extends t3lib_SCbase {
97
98 // Default variables for backend modules
99 var $MCONF = array(); // Module configuration
100 var $MOD_MENU = array(); // Module menu items
101 var $MOD_SETTINGS = array(); // Module session settings
102
103 /**
104 * Document Template Object
105 *
106 * @var noDoc
107 */
108 var $doc;
109 var $content; // Accumulated content
110
111
112 // Internal:
113 var $publishAccess = FALSE;
114 var $be_user_Array = array();
115 var $be_user_Array_full = array(); // not blinded, used by workspace listing
116
117
118 /*********************************
119 *
120 * Standard module initialization
121 *
122 *********************************/
123
124 /**
125 * Initialize menu configuration
126 *
127 * @return void
128 */
129 function menuConfig() {
130 global $LANG;
131
132 // Menu items:
133 $this->MOD_MENU = array(
134 'function' => array(
135 'publish' => $LANG->getLL('menuitem_review'),
136 'workspaces' => $LANG->getLL('menuitem_workspaces'),
137 ),
138 'filter' => array(
139 1 => $LANG->getLL('filter_drafts'),
140 2 => $LANG->getLL('filter_archive'),
141 0 => $LANG->getLL('filter_all'),
142 ),
143 'display' => array(
144 0 => '['.$LANG->getLL('shortcut_onlineWS').']',
145 -98 => $LANG->getLL('label_offlineWSes'),
146 -99 => $LANG->getLL('label_allWSes'),
147 -1 => '['.$LANG->getLL('shortcut_offlineWS').']'
148 ),
149 'diff' => array(
150 0 => $LANG->getLL('diff_no_diff'),
151 1 => $LANG->getLL('diff_show_inline'),
152 2 => $LANG->getLL('diff_show_popup'),
153 ),
154 'expandSubElements' => '',
155 );
156
157 // Add workspaces:
158 if ($GLOBALS['BE_USER']->workspace===0) { // Spend time on this only in online workspace because it might take time:
159 $workspaces = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,title,adminusers,members,reviewers','sys_workspace','pid=0'.t3lib_BEfunc::deleteClause('sys_workspace'),'','title');
160 foreach($workspaces as $rec) {
161 if ($GLOBALS['BE_USER']->checkWorkspace($rec)) {
162 $this->MOD_MENU['display'][$rec['uid']] = '[' . $rec['uid'] . '] ' . htmlspecialchars($rec['title']);
163 }
164 }
165 }
166
167 // CLEANSE SETTINGS
168 $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name'], 'ses');
169 }
170
171 /**
172 * Executes action for selected elements, if any is sent:
173 */
174 function execute() {
175 $post = t3lib_div::_POST();
176
177 # debug($post);
178
179 if ($post['_with_selected_do']) {
180 if (is_array($post['items']) && count($post['items'])) {
181 $cmdArray = array();
182
183 foreach($post['items'] as $item => $v) {
184 list($table,$uid) = explode(':',$item,2);
185
186 if ($GLOBALS['TCA'][$table] && t3lib_div::testInt($uid)) {
187 switch($post['_with_selected_do']) {
188 case "stage_-1":
189 $cmdArray[$table][$uid]['version']['action'] = 'setStage';
190 $cmdArray[$table][$uid]['version']['stageId'] = -1;
191 break;
192 case "stage_0":
193 $cmdArray[$table][$uid]['version']['action'] = 'setStage';
194 $cmdArray[$table][$uid]['version']['stageId'] = 0;
195 break;
196 case "stage_1":
197 $cmdArray[$table][$uid]['version']['action'] = 'setStage';
198 $cmdArray[$table][$uid]['version']['stageId'] = 1;
199 break;
200 case "stage_10":
201 $cmdArray[$table][$uid]['version']['action'] = 'setStage';
202 $cmdArray[$table][$uid]['version']['stageId'] = 10;
203 break;
204 case "publish":
205 if ($onlineRec = t3lib_BEfunc::getLiveVersionOfRecord($table,$uid,'uid')) {
206 $cmdArray[$table][$onlineRec['uid']]['version']['action'] = 'swap';
207 $cmdArray[$table][$onlineRec['uid']]['version']['swapWith'] = $uid;
208 }
209 break;
210 case "swap":
211 if ($onlineRec = t3lib_BEfunc::getLiveVersionOfRecord($table,$uid,'uid')) {
212 $cmdArray[$table][$onlineRec['uid']]['version']['action'] = 'swap';
213 $cmdArray[$table][$onlineRec['uid']]['version']['swapWith'] = $uid;
214 $cmdArray[$table][$onlineRec['uid']]['version']['swapIntoWS'] = 1;
215 }
216 break;
217 case "release":
218 $cmdArray[$table][$uid]['version']['action'] = 'clearWSID';
219 break;
220 case "flush":
221 $cmdArray[$table][$uid]['version']['action'] = 'flush';
222 break;
223 }
224 }
225 }
226
227 # debug($cmdArray);
228
229 $tce = t3lib_div::makeInstance('t3lib_TCEmain');
230 $tce->stripslashes_values = 0;
231 $tce->start(array(), $cmdArray);
232 $tce->process_cmdmap();
233 }
234 }
235 }
236
237 /**
238 * Standard init function of a module.
239 *
240 * @return void
241 */
242 function init() {
243 global $BACK_PATH, $BE_USER;
244
245 // Setting module configuration:
246 $this->MCONF = $GLOBALS['MCONF'];
247
248 // Initialize Document Template object:
249 $this->doc = t3lib_div::makeInstance('template');
250 $this->doc->backPath = $BACK_PATH;
251 $this->doc->setModuleTemplate('templates/ws.html');
252
253 // JavaScript
254 $this->doc->JScode = $this->doc->wrapScriptTags('
255 script_ended = 0;
256 function jumpToUrl(URL) { //
257 window.location.href = URL;
258 }
259
260 function expandCollapse(rowNumber) {
261 elementId = "wl_" + rowNumber;
262 element = document.getElementById(elementId);
263 image = document.getElementById("spanw1_" + rowNumber);
264 if (element.style) {
265 if (element.style.display == "none") {
266 element.style.display = "block";
267 image.className = "t3-icon t3-icon-actions t3-icon-actions-view t3-icon-view-table-collapse";
268 } else {
269 element.style.display = "none";
270 image.className = "t3-icon t3-icon-actions t3-icon-actions-view t3-icon-view-table-expand";
271 }
272 }
273 }
274 ');
275 $this->doc->form = '<form action="index.php" method="post" name="pageform">';
276
277 // Setting up the context sensitive menu:
278 $this->doc->getContextMenuCode();
279
280 // Add JS for dynamic tabs:
281 $this->doc->JScode.= $this->doc->getDynTabMenuJScode();
282
283 // Setting publish access permission for workspace:
284 $this->publishAccess = $BE_USER->workspacePublishAccess($BE_USER->workspace);
285
286 // Parent initialization:
287 parent::init();
288 }
289
290 /**
291 * Main function for Workspace Manager module.
292 *
293 * @return void
294 */
295 function main() {
296 global $LANG, $BE_USER, $BACK_PATH;
297
298 // See if we need to switch workspace
299 $changeWorkspace = t3lib_div::_GET('changeWorkspace');
300 if ($changeWorkspace != '') {
301 $BE_USER->setWorkspace($changeWorkspace);
302 $this->content .= $this->doc->wrapScriptTags('top.location.href="' . $BACK_PATH . t3lib_BEfunc::getBackendScript() . '";');
303 } else {
304 // Starting page:
305 $this->content.=$this->doc->header($LANG->getLL('title'));
306 $this->content.=$this->doc->spacer(5);
307
308 // Get usernames and groupnames
309 $be_group_Array = t3lib_BEfunc::getListGroupNames('title,uid');
310 $groupArray = array_keys($be_group_Array);
311 // Need 'admin' field for t3lib_iconWorks::getIconImage()
312 $this->be_user_Array_full = $this->be_user_Array = t3lib_BEfunc::getUserNames('username,usergroup,usergroup_cached_list,uid,admin,workspace_perms');
313 if (!$GLOBALS['BE_USER']->isAdmin()) {
314 $this->be_user_Array = t3lib_BEfunc::blindUserNames($this->be_user_Array,$groupArray,1);
315 }
316
317 // Build top menu:
318 $menuItems = array();
319 $menuItems[] = array(
320 'label' => $LANG->getLL('menuitem_review'),
321 'content' => $this->moduleContent_publish()
322 );
323 $menuItems[] = array(
324 'label' => $LANG->getLL('menuitem_workspaces'),
325 'content' => $this->moduleContent_workspaceList()
326 );
327
328 // Add hidden fields and create tabs:
329 $content = $this->doc->getDynTabMenu($menuItems,'user_ws');
330 $this->content.=$this->doc->section('',$content,0,1);
331
332 // Setting up the buttons and markers for docheader
333 $docHeaderButtons = $this->getButtons();
334 // $markers['CSH'] = $docHeaderButtons['csh'];
335
336 }
337 $markers['CONTENT'] = $this->content;
338
339 // Build the <body> for the module
340 $this->content = $this->doc->startPage($LANG->getLL('title'));
341 $this->content.= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
342 $this->content.= $this->doc->endPage();
343 $this->content = $this->doc->insertStylesAndJS($this->content);
344
345 }
346
347 /**
348 * Print module content. Called as last thing in the global scope.
349 *
350 * @return void
351 */
352 function printContent() {
353 echo $this->content;
354 }
355
356 /**
357 * Create the panel of buttons for submitting the form or otherwise perform operations.
358 *
359 * @return array all available buttons as an assoc. array
360 */
361 protected function getButtons() {
362 global $LANG, $BACK_PATH;
363
364 $buttons = array(
365 'new_record' => '',
366 );
367
368 $newWkspUrl = 'workspaceforms.php?action=new';
369
370 // workspace creation link
371 if ($GLOBALS['BE_USER']->isAdmin() || 0 != ($GLOBALS['BE_USER']->groupData['workspace_perms'] & 4)) {
372 $buttons['new_record'] = '<a href="' . $newWkspUrl . '">' .
373 '<img ' . t3lib_iconWorks::skinImg($BACK_PATH, 'gfx/add_workspaces.gif') . ' alt="' . $LANG->getLL('img_title_create_new_workspace') . '" id="ver-wl-new-workspace-icon" />' .
374 '</a>';
375 }
376 return $buttons;
377 }
378
379
380
381
382
383
384
385
386
387
388
389 /*********************************
390 *
391 * Module content: Publish
392 *
393 *********************************/
394
395 /**
396 * Rendering the content for the publish and review panel in the workspace manager
397 *
398 * @return string HTML content
399 */
400 function moduleContent_publish() {
401 global $LANG;
402
403 // Initialize:
404 $content = '';
405 $details = t3lib_div::_GP('details');
406
407 // Create additional menus:
408 $menu = '';
409 if ($GLOBALS['BE_USER']->workspace===0) {
410 $menu.= t3lib_BEfunc::getFuncMenu(0,'SET[filter]',$this->MOD_SETTINGS['filter'],$this->MOD_MENU['filter']);
411 $menu.= t3lib_BEfunc::getFuncMenu(0,'SET[display]',$this->MOD_SETTINGS['display'],$this->MOD_MENU['display']);
412 }
413 $menu.= t3lib_BEfunc::getFuncMenu(0,'SET[diff]',$this->MOD_SETTINGS['diff'],$this->MOD_MENU['diff']);
414 if ($GLOBALS['BE_USER']->workspace!==0) {
415 $menu.= t3lib_BEfunc::getFuncCheck(0,'SET[expandSubElements]',$this->MOD_SETTINGS['expandSubElements'],'','','id="checkExpandSubElements"').' <label for="checkExpandSubElements">'.$LANG->getLL('label_showsubelements').'</label> ';
416 }
417
418 // Create header:
419 $title = '';
420 $description = '';
421 switch($GLOBALS['BE_USER']->workspace) {
422 case 0:
423 $title = t3lib_iconWorks::getIconImage('sys_workspace', array(), $this->doc->backPath, ' align="top"').'['.$LANG->getLL('shortcut_onlineWS').']';
424 $description = $LANG->getLL('workspace_description_live');
425 break;
426 case -1:
427 $title = t3lib_iconWorks::getIconImage('sys_workspace', array(), $this->doc->backPath, ' align="top"').'['.$LANG->getLL('shortcut_offlineWS').']';
428 $description = $LANG->getLL('workspace_description_draft');
429 break;
430 case -99:
431 $title = $this->doc->icons(3).'[' . $LANG->getLL('shortcut_noWSfound') . ']';
432 $description = $LANG->getLL('workspace_description_no_access');
433 break;
434 default:
435 $title = t3lib_iconWorks::getIconImage('sys_workspace', $GLOBALS['BE_USER']->workspaceRec, $this->doc->backPath, ' align="top"').
436 '['.$GLOBALS['BE_USER']->workspace.'] '.t3lib_BEfunc::getRecordTitle('sys_workspace',$GLOBALS['BE_USER']->workspaceRec,TRUE);
437 $description = ($GLOBALS['BE_USER']->workspaceRec['description'] ? htmlspecialchars($GLOBALS['BE_USER']->workspaceRec['description']) : '<em>[' . $LANG->getLL('shortcut_noWSfound') . ']</em>');
438 break;
439 }
440
441 // Buttons for publish / swap:
442 $actionLinks = '';
443 if ($GLOBALS['BE_USER']->workspace!==0) {
444 if ($this->publishAccess) {
445 $confirmation = $LANG->JScharCode($LANG->getLL(($GLOBALS['BE_USER']->workspaceRec['publish_access'] & 1) ? 'submit_publish_workspace_confirmation_1' : 'submit_publish_workspace_confirmation_2'));
446 $actionLinks.= '<input type="submit" name="_publish" value="' . $LANG->getLL('submit_publish_workspace') . '" onclick="if (confirm(' . $confirmation . ')) window.location.href=\'publish.php?swap=0\';return false"/>';
447 if ($GLOBALS['BE_USER']->workspaceSwapAccess()) {
448 $confirmation = $LANG->JScharCode($LANG->getLL(($GLOBALS['BE_USER']->workspaceRec['publish_access'] & 1) ? 'submit_swap_workspace_confirmation_1' : 'submit_swap_workspace_confirmation_2'));
449 $actionLinks.= '<input type="submit" name="_swap" value="' . $LANG->getLL('submit_swap_workspace') . '" onclick="if (confirm(' . $confirmation . ')) window.location.href=\'publish.php?swap=1\';return false ;" />';
450 }
451 } else {
452 $actionLinks.= $this->doc->icons(1) . $LANG->getLL('no_publish_permission');
453 }
454
455 // Preview of workspace link
456 if (t3lib_div::_POST('_previewLink')) {
457 $ttlHours = intval($GLOBALS['BE_USER']->getTSConfigVal('options.workspaces.previewLinkTTLHours'));
458 $ttlHours = ($ttlHours ? $ttlHours : 24*2);
459 $previewUrl = t3lib_div::getIndpEnv('TYPO3_SITE_URL').'index.php?ADMCMD_prev='.t3lib_BEfunc::compilePreviewKeyword('', $GLOBALS['BE_USER']->user['uid'],60*60*$ttlHours,$GLOBALS['BE_USER']->workspace).'&id='.intval($GLOBALS['BE_USER']->workspaceRec['db_mountpoints']);
460 $actionLinks.= '<br />Any user can browse the workspace frontend using this link for the next ' . $ttlHours . ' hours (does not require backend login):<br /><br /><a target="_blank" href="' . htmlspecialchars($previewUrl) . '">' . $previewUrl . '</a>';
461 } else {
462 $actionLinks.= '<input type="submit" name="_previewLink" value="Generate Workspace Preview Link" />';
463 }
464 }
465
466 $wsAccess = $GLOBALS['BE_USER']->checkWorkspace($GLOBALS['BE_USER']->workspaceRec);
467
468 // Add header to content variable:
469 $content = '
470 <table border="0" cellpadding="1" cellspacing="1" class="lrPadding" style="border: 1px solid black;">
471 <tr>
472 <td class="bgColor2" nowrap="nowrap"><b>' . $LANG->getLL('label_workspace') . '</b>&nbsp;</td>
473 <td class="bgColor4" nowrap="nowrap">'.$title.'</td>
474 </tr>
475 <tr>
476 <td class="bgColor2" nowrap="nowrap"><b>' . $LANG->getLL('label_description') . '</b>&nbsp;</td>
477 <td class="bgColor4">'.$description.'</td>
478 </tr>'.($GLOBALS['BE_USER']->workspace!=-99 && !$details ? '
479 <tr>
480 <td class="bgColor2" nowrap="nowrap"><b>' . $LANG->getLL('label_options') . '</b>&nbsp;</td>
481 <td class="bgColor4">'.$menu.$actionLinks.'</td>
482 </tr>
483 <tr>
484 <td class="bgColor2" nowrap="nowrap"><b>' . $LANG->getLL('label_status') . '</b>&nbsp;</td>
485 <td class="bgColor4">'.$LANG->getLL('label_access_level').' ' . $GLOBALS['LANG']->getLL('workspace_list_access_' . $wsAccess['_ACCESS']) . '</td>
486 </tr>' : '').'
487 </table>
488 <br />
489 ';
490
491 // Add publishing and review overview:
492 if ($GLOBALS['BE_USER']->workspace!=-99) {
493 if ($details) {
494 $content.= $this->displayVersionDetails($details);
495 } else {
496 $content.= $this->displayWorkspaceOverview();
497 }
498 $content .= '<br />';
499 }
500
501 // Return content:
502 return $content;
503 }
504
505 /**
506 * Display details for a single version from workspace
507 *
508 * @param string Version identification, made of table and uid
509 * @return string HTML string
510 */
511 function displayVersionDetails($details) {
512 return 'TODO: Show details for version "'.$details.'"<hr/><a href="index.php">BACK</a>';
513 }
514
515 /**
516 * Rendering the overview of versions in the current workspace
517 *
518 * @return string HTML (table)
519 */
520 function displayWorkspaceOverview() {
521
522 // Initialize Workspace ID and filter-value:
523 if ($GLOBALS['BE_USER']->workspace===0) {
524 $wsid = $this->MOD_SETTINGS['display']; // Set wsid to the value from the menu (displaying content of other workspaces)
525 $filter = $this->MOD_SETTINGS['filter'];
526 } else {
527 $wsid = $GLOBALS['BE_USER']->workspace;
528 $filter = 0;
529 }
530
531 // Instantiate workspace GUI library and generate workspace overview
532 $wslibGuiObj = t3lib_div::makeInstance('wslib_gui');
533 $wslibGuiObj->diff = $this->MOD_SETTINGS['diff'];
534 $wslibGuiObj->expandSubElements = $this->MOD_SETTINGS['expandSubElements'];
535 $wslibGuiObj->alwaysDisplayHeader = true;
536 return $wslibGuiObj->getWorkspaceOverview($this->doc, $wsid, $filter);
537 }
538
539
540
541
542
543
544
545
546
547
548
549
550
551 /********************************
552 *
553 * Module content: Workspace list
554 *
555 ********************************/
556
557 /**
558 * Rendering of the workspace list
559 *
560 * @return string HTML
561 */
562 function moduleContent_workspaceList() {
563 // Original Kasper's TODO: Workspace listing
564 //
565 // - 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.
566 // - SWITCHING: Switching between available workspaces is done by a button shown for each in the list
567 // - 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)
568 // - 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!).
569 return $this->workspaceList_displayUserWorkspaceList();
570 }
571
572 /**
573 * Generates HTML to display a list of workspaces.
574 *
575 * @return string Generated HTML code
576 */
577 function workspaceList_displayUserWorkspaceList() {
578 global $BACK_PATH, $LANG;
579
580 // table header
581 $content = $this->workspaceList_displayUserWorkspaceListHeader();
582
583 // get & walk workspace list generating content
584 $wkspList = $this->workspaceList_getUserWorkspaceList();
585 $rowNum = 1;
586 foreach ($wkspList as $wksp) {
587 $currentWksp = ($GLOBALS['BE_USER']->workspace == $wksp['uid']);
588
589 // Each workspace data occupies two rows:
590 // (1) Folding + Icons + Title + Description
591 // (2) Information about workspace (initially hidden)
592
593 $cssClass = ($currentWksp ? 'bgColor3' : 'bgColor4');
594 // Start first row
595 $content .= '<tr class="' . $cssClass . '">';
596
597 // row #1, column #1: expand icon
598 $content .= '<td>' .
599 '<a href="javascript:expandCollapse(' . $rowNum . ')">' .
600 t3lib_iconWorks::getSpriteIcon('actions-view-table-expand', array(
601 'title' => $LANG->getLL('img_title_show_more'),
602 'id' => 'spanw1_' . $rowNum
603 )) .
604 '</a></td>';
605
606 // row #1, column #2: icon panel
607 $content .= '<td nowrap="nowrap">'; // Mozilla Firefox will attempt wrap due to `width="1"` on topmost column
608 $content .= $this->workspaceList_displayIcons($currentWksp, $wksp);
609 $content .= '</td>';
610
611 // row #1, column #3: current workspace indicator
612 $content .= '<td nowrap="nowrap" style="text-align: center">'; // Mozilla Firefox will attempt wrap due to `width="1"` on topmost column
613 $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') . '" />');
614 $content .= '</td>';
615
616 // row #1, column #4 and 5: title and description
617 $content .= '<td nowrap="nowrap">' . htmlspecialchars($wksp['title']) . '</td>' .
618 '<td>' . nl2br(htmlspecialchars($wksp['description'])) . '</td>';
619 $content .= '</tr>';
620
621 // row #2, column #1 and #2
622 $content .= '<tr id="wl_' . $rowNum . '" class="bgColor" style="display: none">';
623 $content .= '<td colspan="2" style="border-right: none;">&nbsp;</td>';
624
625 // row #2, column #3, #4 and #4
626 $content .= '<td colspan="3" style="border-left: none;">' .
627 $this->workspaceList_formatWorkspaceData($wksp) .
628 '</td>';
629
630 $content .= '</tr>';
631 $rowNum++;
632 }
633 $content .= '</table>';
634
635 return $content;
636 }
637
638
639
640
641
642 /**
643 * Retrieves a list of workspaces where user has access.
644 *
645 * @return array A list of workspaces available to the current BE user
646 */
647 function workspaceList_getUserWorkspaceList() {
648
649 // Get list of all workspaces. Note: system workspaces will be always displayed before custom ones!
650 $workspaces = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*','sys_workspace','pid=0'.t3lib_BEfunc::deleteClause('sys_workspace'),'','title');
651 $availableWorkspaces = array();
652
653 // Live
654 $wksp = $this->workspaceList_createFakeWorkspaceRecord(0);
655 $wksp = $GLOBALS['BE_USER']->checkWorkspace($wksp);
656 if (false !== $wksp) {
657 $availableWorkspaces[] = $wksp;
658 }
659
660 // Draft
661 $wksp = $this->workspaceList_createFakeWorkspaceRecord(-1);
662 $wksp = $GLOBALS['BE_USER']->checkWorkspace($wksp);
663 if (false !== $wksp) {
664 $availableWorkspaces[] = $wksp;
665 }
666
667 // Custom
668 foreach($workspaces as $rec) {
669 // see if user can access this workspace in any way
670 if (false !== ($result = $GLOBALS['BE_USER']->checkWorkspace($rec))) {
671 $availableWorkspaces[] = $result; // `$result` contains `$rec` plus access type through '_ACCESS' key
672 }
673 }
674 return $availableWorkspaces;
675 }
676
677 /**
678 * Create inner information panel for workspace list. This panel is
679 * initially hidden and becomes visible when user click on the expand
680 * icon on the very left of workspace list against the workspace he
681 * wants to explore.
682 *
683 * @param array Workspace information
684 * @return string Formatted workspace information
685 */
686 function workspaceList_formatWorkspaceData(&$wksp) {
687 global $LANG;
688
689 $content = '<table cellspacing="1" cellpadding="1" width="100%" class="ver-wl-details-table">' .
690 '<tr><td class="ver-wl-details-label"><b>' . $LANG->getLL('workspace_list_label_file_mountpoints') . '</b></td>' .
691 '<td class="ver-wl-details">' . $this->workspaceList_getFileMountPoints($wksp) . '</td></tr>' .
692 '<tr><td class="ver-wl-details-label"><b>' . $LANG->getLL('workspace_list_label_db_mountpoints') . '</b></td>' .
693 '<td class="ver-wl-details">' . $this->workspaceList_getWebMountPoints($wksp) . '</td></tr>';
694 if ($wksp['uid'] > 0) {
695 // Displaying information below makes sence only for custom workspaces
696 $content .=
697 '<tr><td class="ver-wl-details-label"><b>' . $LANG->getLL('workspace_list_label_frozen') . '</b></td>' .
698 '<td class="ver-wl-details">' . $LANG->getLL($wksp['freeze'] ? 'workspace_list_label_frozen_yes' : 'workspace_list_label_frozen_no') . '</td></tr>' .
699 '<tr><td class="ver-wl-details-label"><b>' . $LANG->getLL('workspace_list_label_publish_date') . '</b></td>' .
700 '<td class="ver-wl-details">' . ($wksp['publish_time'] == 0 ? '&nbsp;&ndash;' : t3lib_BEfunc::datetime($wksp['publish_time'])) . '</td></tr>' .
701 '<tr><td class="ver-wl-details-label"><b>' . $LANG->getLL('workspace_list_label_unpublish_date') . '</b></td>' .
702 '<td class="ver-wl-details">' . ($wksp['unpublish_time'] == 0 ? '&nbsp;&ndash;' : t3lib_BEfunc::datetime($wksp['unpublish_time'])) . '</td></tr>' .
703 '<tr><td class="ver-wl-details-label"><b>' . $LANG->getLL('workspace_list_label_your_access') . '</b></td>' .
704 '<td class="ver-wl-details">' . $LANG->getLL('workspace_list_access_' . $wksp['_ACCESS']) . '</td></tr>' .
705 '<tr><td class="ver-wl-details-label"><b>' . $LANG->getLL('workspace_list_label_workspace_users') . '</b></td>' .
706 '<td class="ver-wl-details">' . $this->workspaceList_getUserList($wksp) . '</td></tr>';
707 }
708 else if ($GLOBALS['BE_USER']->isAdmin()) {
709 // show users for draft/live workspace only to admin users
710 $content .= '<tr><td class="ver-wl-details-label"><b>' . $LANG->getLL('workspace_list_label_workspace_users') . '</b></td>' .
711 '<td class="ver-wl-details">' . $this->workspaceList_getUserList($wksp) . '</td></tr>';
712 }
713 $content .= '</table>';
714
715 return $content;
716 }
717
718
719
720
721
722 /**
723 * Retrieves and formats database mount points lists.
724 *
725 * @param array &$wksp Workspace record
726 * @return string Generated HTML
727 */
728 function workspaceList_getWebMountPoints(&$wksp) {
729 if ($wksp['uid'] <= 0) {
730 // system workspaces
731 return $GLOBALS['LANG']->getLL($wksp['uid'] == 0 ? 'workspace_list_db_mount_point_live' : 'workspace_list_db_mount_point_draft');
732 }
733
734 // here only if obtaining mount points for custom workspaces
735
736 // Warning: all fields needed for t3lib_iconWorks::getIconImage()!
737 $MPs = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'pages', 'deleted=0 AND uid IN (' . $GLOBALS['TYPO3_DB']->cleanIntList($wksp['db_mountpoints']) . ')', '', 'title');
738 $content_array = array();
739 if (count($MPs) > 0) {
740 $isAdmin = $GLOBALS['BE_USER']->isAdmin();
741 if (!$isAdmin) {
742 // We need to fetch user's mount point list (including MPS mounted from groups).
743 // This list must not be affects by current user's workspace. It means we cannot use
744 // $BE_USER->isInWebMount() to check mount points.
745 $userMPs = explode(',', $GLOBALS['BE_USER']->dataLists['webmount_list']); // includes group data if necessary!
746 }
747 foreach ($MPs as $mp) {
748 if (!$isAdmin && !in_array($mp['uid'], $userMPs)) {
749 // Show warning icon
750 $title = $GLOBALS['LANG']->getLL('workspace_list_mount_point_inaccessible');
751 $str = t3lib_iconWorks::getSpriteIcon('status-warning');
752 $classAttr = 'class="ver-wl-mp-inacessible" ';
753 }
754 else {
755 // normal icon
756 $str = t3lib_iconWorks::getIconImage('pages', $mp, $GLOBALS['BACK_PATH'], ' align="absmiddle"');
757 $classAttr = '';
758 }
759 // Will show UID on hover. Just convinient to user.
760 $content_array[] = $str . '<span ' . $classAttr . 'title="UID: ' . $mp['uid'] . '">' . $mp['title'] . '</span>';
761 }
762 }
763 if (count($content_array) > 0) {
764 return implode('<br />', $content_array);
765 }
766 // no mount points
767 return $GLOBALS['LANG']->getLL('workspace_list_db_mount_point_custom');
768 }
769
770 /**
771 * Retrieves and formats file mount points lists.
772 *
773 * @param array &$wksp Workspace record
774 * @return string Generated HTML
775 */
776 function workspaceList_getFileMountPoints(&$wksp) {
777 if ($wksp['uid'] == -1) {
778 // draft workspace - none!
779 return $GLOBALS['LANG']->getLL('workspace_list_file_mount_point_draft');
780 }
781 else if ($wksp['uid'] == 0) {
782 // live workspace
783 return $GLOBALS['LANG']->getLL('workspace_list_file_mount_point_live');
784 }
785
786 // Here if displaying information for custom workspace
787
788 // Warning: all fields needed for t3lib_iconWorks::getIconImage()!
789 $MPs = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'sys_filemounts', 'deleted=0 AND hidden=0 AND uid IN (' . $GLOBALS['TYPO3_DB']->cleanIntList($wksp['file_mountpoints']) . ')', '', 'title');
790 if (count($MPs) != 0) {
791 // Has mount points
792 $isAdmin = $GLOBALS['BE_USER']->isAdmin();
793 if (!$isAdmin) {
794 // We need to fetch user's mount point list (including MPS mounted from groups).
795 // This list must not be affects by current user's workspace. It means we cannot use
796 // $BE_USER->isInWebMount() to check mount points.
797 $userMPs = explode(',', $GLOBALS['BE_USER']->dataLists['filemount_list']); // includes group data if necessary!
798 }
799 foreach ($MPs as $mp) {
800 if (!$isAdmin && !in_array($mp['uid'], $userMPs)) {
801 // Show warning icon
802 $title = $GLOBALS['LANG']->getLL('workspace_list_mount_point_inaccessible');
803 $str = t3lib_iconWorks::getSpriteIcon('status-warning');
804 $classAttr = 'class="ver-wl-mp-inacessible" ';
805 }
806 else {
807 // normal icon
808 $str = t3lib_iconWorks::getIconImage('sys_filemounts', $mp, $GLOBALS['BACK_PATH'], ' align="absmiddle"');
809 $classAttr = '';
810 }
811 // Will show UID on hover. Just convinient to user.
812 $content_array[] = $str . '<span ' . $classAttr . 'title="UID: ' . $mp['uid'] . '">' . $mp['title'] . '</span>';
813 }
814 }
815 if (count($content_array) > 0) {
816 return implode('<br />', $content_array);
817 }
818 // No file mount points
819 return $GLOBALS['LANG']->getLL('workspace_list_file_mount_point_custom');
820 }
821
822 /**
823 * Creates a header for the workspace list table. This function only makes
824 * <code>workspaceList_displayUserWorkspaceList()</code> smaller.
825 *
826 * @return string Generated content
827 */
828 function workspaceList_displayUserWorkspaceListHeader() {
829 global $LANG;
830 // TODO CSH lables?
831 return '<table border="0" cellpadding="0" cellspacing="1" class="lrPadding workspace-overview ver-wl-table">
832 <tr class="bgColor5 tableheader">
833 <td width="1">&nbsp;</td>
834 <td width="1">&nbsp;</td>
835 <td nowrap="nowrap">' . $LANG->getLL('workspace_list_label_current_workspace') . '</td>
836 <td nowrap="nowrap">' . $LANG->getLL('workspace_list_label_workspace_title') . '</td>
837 <td nowrap="nowrap">' . $LANG->getLL('workspace_list_label_workspace_description') . '</td>
838 </tr>';
839 }
840
841
842 /**
843 * Generates a list of <code>&lt;option&gt;</code> tags with user names.
844 *
845 * @param array Workspace record
846 * @return string Generated content
847 */
848 function workspaceList_getUserList(&$wksp) {
849 global $LANG;
850
851 if ($wksp['uid'] > 0) {
852 // custom workspaces
853 $content = $this->workspaceList_getUserListWithAccess($wksp['adminusers'], $LANG->getLL('workspace_list_label_owners')); // owners
854 $content .= $this->workspaceList_getUserListWithAccess($wksp['members'], $LANG->getLL('workspace_list_label_members')); // members
855 $content .= $this->workspaceList_getUserListWithAccess($wksp['reviewers'], $LANG->getLL('workspace_list_label_reviewers')); // reviewers
856 if ($content != '') {
857 $content = '<table cellpadding="0" cellspacing="1" width="100%" class="lrPadding workspace-overview">' . $content . '</table>';
858 } else {
859 $content = $LANG->getLL($wksp['uid'] > 0 ? 'workspace_list_access_admins_only' : 'workspace_list_access_anyone');
860 }
861 }
862 else {
863 // live and draft workspace
864 $content = $this->workspaceList_getUserListForSysWorkspace($wksp);
865 }
866 return $content;
867 }
868
869 /**
870 * Generates a list of user names that has access to the system workspace.
871 *
872 * @param array &$wksp Workspace record
873 * @return string Generated content
874 */
875 function workspaceList_getUserListForSysWorkspace(&$wksp) {
876 $option = ($wksp['uid'] == 0 ? 1 : 2);
877 $content_array = array();
878 foreach ($this->be_user_Array_full as $uid => $user) {
879 if ($user['admin'] != 0 || 0 != ($user['workspace_perms'] & $option)) {
880 if ($uid == $GLOBALS['BE_USER']->user['uid']) {
881 // highlight current user
882 $tag0 = '<span class="ver-wl-current-user">';
883 $tag1 = '</span>';
884 }
885 else {
886 $tag0 = $tag1 = '';
887 }
888 $content_array[] = $this->doc->wrapClickMenuOnIcon(t3lib_iconWorks::getIconImage('be_users', $uid, $GLOBALS['BACK_PATH'], ' align="middle" alt="UID: ' . $uid . '"'), 'be_users', $uid, 2).
889 $tag0 . htmlspecialchars($user['username']) . $tag1;
890 }
891 }
892 return implode('<br />', $content_array);
893 }
894
895 /**
896 * Generates a list of user names that has access to the workspace.
897 *
898 * @param array A list of user IDs separated by comma
899 * @param string Access string
900 * @return string Generated content
901 */
902 function workspaceList_getUserListWithAccess(&$list, $access) {
903 $content_array = array();
904 if ($list != '') {
905 $userIDs = explode(',', $list);
906
907 // get user names and sort
908 $regExp = '/^(be_[^_]+)_(\d+)$/';
909 $groups = false;
910 foreach ($userIDs as $userUID) {
911 $id = $userUID;
912
913 if (preg_match($regExp, $userUID)) {
914 $table = preg_replace($regExp, '\1', $userUID);
915 $id = intval(preg_replace($regExp, '\2', $userUID));
916 if ($table == 'be_users') {
917 // user
918 $icon = $GLOBALS['TCA']['be_users']['typeicons'][$this->be_user_Array[$id]['admin']];
919 if ($id == $GLOBALS['BE_USER']->user['uid']) {
920 // highlight current user
921 $tag0 = '<span class="ver-wl-current-user">';
922 $tag1 = '</span>';
923 }
924 else {
925 $tag0 = $tag1 = '';
926 }
927 $content_array[] = $this->doc->wrapClickMenuOnIcon(t3lib_iconWorks::getIconImage($table, $this->be_user_Array[$id], $GLOBALS['BACK_PATH'], ' align="middle" alt="UID: ' . $id . '"'), $table, $id, 2) .
928 $tag0 . htmlspecialchars($this->be_user_Array_full[$id]['username']) . $tag1;
929 }
930 else {
931 // group
932 if (false === $groups) {
933 $groups = t3lib_BEfunc::getGroupNames();
934 }
935 $content_array[] = $this->doc->wrapClickMenuOnIcon(t3lib_iconWorks::getIconImage($table, $groups[$id], $GLOBALS['BACK_PATH'], ' align="middle" alt="UID: ' . $id . '"'), $table, $id, 2) .
936 $groups[$id]['title'];
937 }
938 }
939 else {
940 // user id
941 if ($userUID == $GLOBALS['BE_USER']->user['uid']) {
942 // highlight current user
943 $tag0 = '<span class="ver-wl-current-user">';
944 $tag1 = '</span>';
945 }
946 else {
947 $tag0 = $tag1 = '';
948 }
949 $content_array[] = t3lib_iconWorks::getIconImage('be_users', $this->be_user_Array[$id], $GLOBALS['BACK_PATH'], ' align="middle" alt="UID: ' . $id . '"') .
950 $tag0 . htmlspecialchars($this->be_user_Array_full[$userUID]['username']) . $tag1;
951 }
952 }
953 sort($content_array);
954 }
955 else {
956 $content_array[] = '&nbsp;&ndash;';
957 }
958
959 $content = '<tr><td class="ver-wl-details-label ver-wl-details-user-list-label">';
960 // TODO CSH lable explaining access here?
961 $content .= '<b>' . $access . '</b></td>';
962 $content .= '<td class="ver-wl-details">' . implode('<br />', $content_array) . '</td></tr>';
963 return $content;
964 }
965
966
967
968 /**
969 * Creates a list of icons for workspace.
970 *
971 * @param boolean <code>true</code> if current workspace
972 * @param array Workspace record
973 * @return string Generated content
974 */
975 function workspaceList_displayIcons($currentWorkspace, &$wksp) {
976 global $BACK_PATH, $LANG;
977
978 $content = '';
979 // `edit workspace` button
980 if ($this->workspaceList_hasEditAccess($wksp)) {
981 // User can modify workspace parameters, display corresponding link and icon
982 $editUrl = 'workspaceforms.php?action=edit&amp;wkspId=' . $wksp['uid'];
983
984 $content .= '<a href="' . $editUrl . '" title="'. $LANG->getLL('workspace_list_icon_title_edit_workspace') .'"/>' .
985 t3lib_iconWorks::getSpriteIcon('actions-document-open') .
986 '</a>';
987 } else {
988 // User can NOT modify workspace parameters, display space
989 // Get only withdth and height from skinning API
990 $content .= '<img src="clear.gif" ' .
991 t3lib_iconWorks::skinImg($BACK_PATH, 'gfx/edit2.gif', 'width="11" height="12"', 2) .
992 ' border="0" alt="" hspace="1" align="middle" />';
993 }
994 // `switch workspace` button
995 if (!$currentWorkspace) {
996 // Workspace switching button
997 $content .= '<a href="' .
998 t3lib_div::getIndpEnv('SCRIPT_NAME') .
999 '?changeWorkspace=' . $wksp['uid'] . '" title="'. $LANG->getLL('workspace_list_icon_title_switch_workspace') . '"/>' .
1000 t3lib_iconWorks::getSpriteIcon('actions-version-swap-workspace') .
1001 '</a>';
1002 } else {
1003 // Current workspace: empty space instead of workspace switching button
1004 //
1005 // Here get only width and height from skinning API
1006 $content .= '<img src="clear.gif" ' .
1007 t3lib_iconWorks::skinImg($BACK_PATH, 'gfx/switch.png', 'width="18" height="16"', 2) .
1008 ' border="0" alt="" hspace="1" align="middle" alt="" />';
1009 }
1010 return $content;
1011 }
1012
1013 /**
1014 * Checks if user has edit access to workspace. Access is granted if
1015 * workspace is custom and user is admin or the the owner of the workspace.
1016 * This function assumes that <code>$wksp</code> were passed through
1017 * <code>$GLOBALS['BE_USER']->checkWorkspace()</code> function to obtain
1018 * <code>_ACCESS</code> attribute of the workspace.
1019 *
1020 * @param array Workspace record
1021 * @return boolean <code>true</code> if user can modify workspace parameters
1022 */
1023 function workspaceList_hasEditAccess(&$wksp) {
1024 $access = &$wksp['_ACCESS'];
1025 return ($wksp['uid'] > 0 && ($access == 'admin' || $access == 'owner'));
1026 }
1027
1028 /**
1029 * Creates a fake workspace record for system workspaces. Record contains
1030 * all fields found in <code>sys_workspaces</code>.
1031 *
1032 * @param integer System workspace ID. Currently <code>0</code> and <code>-1</code> are accepted.
1033 * @return array Generated record (see <code>sys_workspaces</code> for structure)
1034 */
1035 function workspaceList_createFakeWorkspaceRecord($uid) {
1036 global $BE_USER, $LANG;
1037
1038 $record = array(
1039 'uid' => $uid,
1040 'pid' => 0, // always 0!
1041 'tstamp' => 0, // does not really matter
1042 'deleted' => 0,
1043 'title' => ($uid == 0 ? '['.$LANG->getLL('shortcut_onlineWS').']' : '['.$LANG->getLL('shortcut_offlineWS').']'),
1044 'description' => ($uid == 0 ? $LANG->getLL('shortcut_onlineWS') : $LANG->getLL('shortcut_offlineWS')),
1045 'adminusers' => '',
1046 'members' => '',
1047 'reviewers' => '',
1048 'db_mountpoints' => '', // TODO get mount points from user profile
1049 'file_mountpoints' => '', // TODO get mount points from user profile for live workspace only (uid == 0)
1050 'publish_time' => 0,
1051 'unpublish_time' => 0,
1052 'freeze' => 0,
1053 'live_edit' => ($uid == 0),
1054 'vtypes' => 0,
1055 'disable_autocreate' => 0,
1056 'swap_modes' => 0,
1057 'publish_access' => 0,
1058 'stagechg_notification' => 0
1059 );
1060 return $record;
1061 }
1062 }
1063
1064
1065 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/user/ws/index.php']) {
1066 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/user/ws/index.php']);
1067 }
1068
1069
1070
1071 // Make instance:
1072 $SOBE = t3lib_div::makeInstance('SC_mod_user_ws_index');
1073 $SOBE->execute();
1074 $SOBE->init();
1075 $SOBE->main();
1076 $SOBE->printContent();
1077
1078 ?>