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