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