index.php 39.8 KB
Newer Older
1
2
3
4
<?php
/***************************************************************
*  Copyright notice
*
5
*  (c) 1999-2010 Kasper Skaarhoj (kasperYYYY@typo3.com)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
*  All rights reserved
*
*  This script is part of the TYPO3 project. The TYPO3 project is
*  free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  The GNU General Public License can be found at
*  http://www.gnu.org/copyleft/gpl.html.
*  A copy is found in the textfile GPL.txt and important notices to the license
*  from the author is found in LICENSE.txt distributed with these scripts.
*
*
*  This script is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
 * Module: Workspace manager
 *
 * $Id$
 *
 * @author	Kasper Skaarhoj <kasperYYYY@typo3.com>
33
 * @author	Dmitry Dulepov <typo3@accio.lv>
34
35
36
37
38
39
 */
/**
 * [CLASS/FUNCTION INDEX of SCRIPT]
 *
 *
 *
40
 *  101: class SC_mod_user_ws_index extends t3lib_SCbase
41
42
 *
 *              SECTION: Standard module initialization
43
44
45
46
 *  128:     function menuConfig()
 *  175:     function init()
 *  233:     function main()
 *  280:     function printContent()
47
48
 *
 *              SECTION: Module content: Publish
49
50
51
 *  310:     function moduleContent_publish()
 *  411:     function displayVersionDetails($details)
 *  420:     function displayWorkspaceOverview()
52
53
 *
 *              SECTION: Module content: Workspace list
54
55
56
57
58
59
60
61
62
63
64
65
66
 *  461:     function moduleContent_workspaceList()
 *  476:     function workspaceList_displayUserWorkspaceList()
 *  553:     function workspaceList_getUserWorkspaceList()
 *  592:     function workspaceList_formatWorkspaceData(&$wksp)
 *  634:     function workspaceList_getWebMountPoints(&$wksp)
 *  683:     function workspaceList_getFileMountPoints(&$wksp)
 *  736:     function workspaceList_displayUserWorkspaceListHeader()
 *  756:     function workspaceList_getUserList(&$wksp)
 *  783:     function workspaceList_getUserListForSysWorkspace(&$wksp)
 *  810:     function workspaceList_getUserListWithAccess(&$list, $access)
 *  883:     function workspaceList_displayIcons($currentWorkspace, &$wksp)
 *  931:     function workspaceList_hasEditAccess(&$wksp)
 *  943:     function workspaceList_createFakeWorkspaceRecord($uid)
67
 *
68
 * TOTAL FUNCTIONS: 20
69
70
71
72
73
74
75
76
77
78
79
80
81
 * (This index is automatically created/updated by the extension "extdeveval")
 *
 */

	// Initialize module:
unset($MCONF);
require ('conf.php');
require ($BACK_PATH.'init.php');
require ($BACK_PATH.'template.php');
$BE_USER->modAccess($MCONF,1);

	// Include libraries of various kinds used inside:
$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
91
92
93
94
95
96
97
98
99
100
101




/**
 * Module: Workspace manager
 *
 * @author	Kasper Skaarhoj <kasperYYYY@typo3.com>
 * @package TYPO3
 * @subpackage core
 */
class SC_mod_user_ws_index extends t3lib_SCbase {

		// Default variables for backend modules
	var $MCONF = array();				// Module configuration
	var $MOD_MENU = array();			// Module menu items
	var $MOD_SETTINGS = array();		// Module session settings
102
103
104
105
106
107
108

	/**
	 * Document Template Object
	 *
	 * @var noDoc
	 */
	var $doc;
109
110
111
112
	var $content;						// Accumulated content


		// Internal:
Kasper Skårhøj's avatar
   
Kasper Skårhøj committed
113
	var $publishAccess = FALSE;
Kasper Skårhøj's avatar
Kasper Skårhøj committed
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
122
123
124
125
126
127
128
129
130


	/*********************************
	 *
	 * Standard module initialization
	 *
	 *********************************/

	/**
	 * Initialize menu configuration
	 *
	 * @return	void
	 */
	function menuConfig()	{
131
		global	$LANG;
132

133
134
135
136
137
138
139
			// fetches the configuration of the version extension
		$versionExtconf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['version']);
			// show draft workspace only if enabled in the version extensions config
		if($versionExtconf['showDraftWorkspace']) {
			$this->showDraftWorkspace = TRUE;
		}

140
141
142
			// Menu items:
		$this->MOD_MENU = array(
			'function' => array(
143
144
				'publish' => $LANG->getLL('menuitem_review'),
				'workspaces' => $LANG->getLL('menuitem_workspaces'),
145
146
			),
			'filter' => array(
147
148
149
				1 => $LANG->getLL('filter_drafts'),
				2 => $LANG->getLL('filter_archive'),
				0 => $LANG->getLL('filter_all'),
150
151
			),
			'display' => array(
152
153
				0 => '['.$LANG->getLL('shortcut_onlineWS').']',
				-98 => $LANG->getLL('label_offlineWSes'),
154
				-99 => $LANG->getLL('label_allWSes')
155
156
			),
			'diff' => array(
157
158
159
				0 => $LANG->getLL('diff_no_diff'),
				1 => $LANG->getLL('diff_show_inline'),
				2 => $LANG->getLL('diff_show_popup'),
160
161
162
			),
			'expandSubElements' => '',
		);
163
		
164
165
			// check if draft workspace was enabled, and if the user has access to it
		if ($this->showDraftWorkspace === TRUE && $GLOBALS['BE_USER']->checkWorkspace(array('uid' => -1))) {
166
167
			$this->MOD_MENU['display'][-1] = '[' . $LANG->getLL('shortcut_offlineWS') . ']';
		}
168

169
170
171
172
173
			// Add workspaces:
		if ($GLOBALS['BE_USER']->workspace===0)	{	// Spend time on this only in online workspace because it might take time:
			$workspaces = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,title,adminusers,members,reviewers','sys_workspace','pid=0'.t3lib_BEfunc::deleteClause('sys_workspace'),'','title');
			foreach($workspaces as $rec)	{
				if ($GLOBALS['BE_USER']->checkWorkspace($rec))	{
174
					$this->MOD_MENU['display'][$rec['uid']] = '[' . $rec['uid'] . '] ' . htmlspecialchars($rec['title']);
175
176
177
178
179
180
181
				}
			}
		}

			// CLEANSE SETTINGS
		$this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name'], 'ses');
	}
Ingo Renner's avatar
Ingo Renner committed
182

183
184
185
186
187
188
189
190
191
192
193
	/**
	 * Executes action for selected elements, if any is sent:
	 */
	function execute()	{
		$post = t3lib_div::_POST();

#		debug($post);

		if ($post['_with_selected_do'])	{
			if (is_array($post['items']) && count($post['items']))	{
				$cmdArray = array();
Ingo Renner's avatar
Ingo Renner committed
194

195
196
				foreach($post['items'] as $item => $v)	{
					list($table,$uid) = explode(':',$item,2);
Ingo Renner's avatar
Ingo Renner committed
197

198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
					if ($GLOBALS['TCA'][$table] && t3lib_div::testInt($uid))	{
						switch($post['_with_selected_do'])	{
							case "stage_-1":
								$cmdArray[$table][$uid]['version']['action'] = 'setStage';
								$cmdArray[$table][$uid]['version']['stageId'] = -1;
							break;
							case "stage_0":
								$cmdArray[$table][$uid]['version']['action'] = 'setStage';
								$cmdArray[$table][$uid]['version']['stageId'] = 0;
							break;
							case "stage_1":
								$cmdArray[$table][$uid]['version']['action'] = 'setStage';
								$cmdArray[$table][$uid]['version']['stageId'] = 1;
							break;
							case "stage_10":
								$cmdArray[$table][$uid]['version']['action'] = 'setStage';
								$cmdArray[$table][$uid]['version']['stageId'] = 10;
							break;
							case "publish":
								if ($onlineRec = t3lib_BEfunc::getLiveVersionOfRecord($table,$uid,'uid'))	{
									$cmdArray[$table][$onlineRec['uid']]['version']['action'] = 'swap';
									$cmdArray[$table][$onlineRec['uid']]['version']['swapWith'] = $uid;
								}
							break;
							case "swap":
							if ($onlineRec = t3lib_BEfunc::getLiveVersionOfRecord($table,$uid,'uid'))	{
								$cmdArray[$table][$onlineRec['uid']]['version']['action'] = 'swap';
								$cmdArray[$table][$onlineRec['uid']]['version']['swapWith'] = $uid;
								$cmdArray[$table][$onlineRec['uid']]['version']['swapIntoWS'] = 1;
							}
							break;
							case "release":
								$cmdArray[$table][$uid]['version']['action'] = 'clearWSID';
							break;
							case "flush":
								$cmdArray[$table][$uid]['version']['action'] = 'flush';
							break;
						}
					}
				}

		#		debug($cmdArray);

				$tce = t3lib_div::makeInstance('t3lib_TCEmain');
				$tce->stripslashes_values = 0;
				$tce->start(array(), $cmdArray);
				$tce->process_cmdmap();
			}
		}
	}
248
249
250
251
252
253
254

	/**
	 * Standard init function of a module.
	 *
	 * @return	void
	 */
	function init()	{
Kasper Skårhøj's avatar
   
Kasper Skårhøj committed
255
		global $BACK_PATH, $BE_USER;
256
257
258
259
260

			// Setting module configuration:
		$this->MCONF = $GLOBALS['MCONF'];

			// Initialize Document Template object:
261
		$this->doc = t3lib_div::makeInstance('template');
262
		$this->doc->backPath = $BACK_PATH;
263
		$this->doc->setModuleTemplate('templates/ws.html');
264

265
			// JavaScript
266
267
268
		$this->doc->JScode = $this->doc->wrapScriptTags('
			script_ended = 0;
			function jumpToUrl(URL)	{	//
269
				window.location.href = URL;
270
271
			}

272
273
			function expandCollapse(rowNumber) {
				elementId = "wl_" + rowNumber;
274
				element = document.getElementById(elementId);
275
				image = document.getElementById("spanw1_" + rowNumber);
276
				if (element.style)	{
277
					if (element.style.display == "none")	{
278
						element.style.display = "table-row";
279
						image.className = "t3-icon t3-icon-actions t3-icon-actions-view t3-icon-view-table-collapse";
280
					} else {
281
282
						element.style.display = "none";
						image.className = "t3-icon t3-icon-actions t3-icon-actions-view t3-icon-view-table-expand";
283
284
285
					}
				}
			}
286
287
288
289
		');
		$this->doc->form = '<form action="index.php" method="post" name="pageform">';

			// Setting up the context sensitive menu:
290
		$this->doc->getContextMenuCode();
291
292
293
294

			// Add JS for dynamic tabs:
		$this->doc->JScode.= $this->doc->getDynTabMenuJScode();

Kasper Skårhøj's avatar
   
Kasper Skårhøj committed
295
296
297
			// Setting publish access permission for workspace:
		$this->publishAccess = $BE_USER->workspacePublishAccess($BE_USER->workspace);

298
299
300
301
302
303
304
305
306
307
			// Parent initialization:
		parent::init();
	}

	/**
	 * Main function for Workspace Manager module.
	 *
	 * @return	void
	 */
	function main()	{
308
309
310
311
312
313
		global $LANG, $BE_USER, $BACK_PATH;

		// See if we need to switch workspace
		$changeWorkspace = t3lib_div::_GET('changeWorkspace');
		if ($changeWorkspace != '') {
			$BE_USER->setWorkspace($changeWorkspace);
314
			$this->content .= $this->doc->wrapScriptTags('top.location.href="' . $BACK_PATH . t3lib_BEfunc::getBackendScript() . '";');
315
		} else {
316
317
318
319
				// Starting page:
			$this->content.=$this->doc->header($LANG->getLL('title'));
			$this->content.=$this->doc->spacer(5);

320
321
322
323
324
325
326
327
328
329
			// Get usernames and groupnames
			$be_group_Array = t3lib_BEfunc::getListGroupNames('title,uid');
			$groupArray = array_keys($be_group_Array);
			// Need 'admin' field for t3lib_iconWorks::getIconImage()
			$this->be_user_Array_full = $this->be_user_Array = t3lib_BEfunc::getUserNames('username,usergroup,usergroup_cached_list,uid,admin,workspace_perms');
			if (!$GLOBALS['BE_USER']->isAdmin()) {
				$this->be_user_Array = t3lib_BEfunc::blindUserNames($this->be_user_Array,$groupArray,1);
			}

			// Build top menu:
330
331
332
			$menuItems = array();
			$menuItems[] = array(
				'label' => $LANG->getLL('menuitem_review'),
333
				'content' => $this->moduleContent_publish()
334
335
336
337
338
339
340
341
342
			);
			$menuItems[] = array(
				'label' => $LANG->getLL('menuitem_workspaces'),
				'content' => $this->moduleContent_workspaceList()
			);

				// Add hidden fields and create tabs:
			$content = $this->doc->getDynTabMenu($menuItems,'user_ws');
			$this->content.=$this->doc->section('',$content,0,1);
Ingo Renner's avatar
Ingo Renner committed
343

344
345
346
				// Setting up the buttons and markers for docheader
			$docHeaderButtons = $this->getButtons();
			// $markers['CSH'] = $docHeaderButtons['csh'];
Ingo Renner's avatar
Ingo Renner committed
347

348
		}
349
		$markers['CONTENT'] = $this->content;
Ingo Renner's avatar
Ingo Renner committed
350

351
352
353
354
355
			// Build the <body> for the module
		$this->content = $this->doc->startPage($LANG->getLL('title'));
		$this->content.= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
		$this->content.= $this->doc->endPage();
		$this->content = $this->doc->insertStylesAndJS($this->content);
Ingo Renner's avatar
Ingo Renner committed
356

357
358
359
360
361
362
363
364
365
366
367
	}

	/**
	 * Print module content. Called as last thing in the global scope.
	 *
	 * @return	void
	 */
	function printContent()	{
		echo $this->content;
	}

368
369
370
371
372
	/**
	 * Create the panel of buttons for submitting the form or otherwise perform operations.
	 *
	 * @return	array	all available buttons as an assoc. array
	 */
373
	protected function getButtons()	{
374
		global $LANG, $BACK_PATH;
Ingo Renner's avatar
Ingo Renner committed
375

376
377
378
		$buttons = array(
			'new_record' => '',
		);
379

380
381
382
383
384
		$newWkspUrl = 'workspaceforms.php?action=new';

			// workspace creation link
		if ($GLOBALS['BE_USER']->isAdmin() || 0 != ($GLOBALS['BE_USER']->groupData['workspace_perms'] & 4))	{
			$buttons['new_record'] = '<a href="' . $newWkspUrl . '">' .
385
						'<img ' . t3lib_iconWorks::skinImg($BACK_PATH, 'gfx/add_workspaces.gif') . ' alt="' . $LANG->getLL('img_title_create_new_workspace') . '" id="ver-wl-new-workspace-icon" />' .
386
387
388
389
						'</a>';
		}
		return $buttons;
	}
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412











	/*********************************
	 *
	 * Module content: Publish
	 *
	 *********************************/

	/**
	 * Rendering the content for the publish and review panel in the workspace manager
	 *
	 * @return	string		HTML content
	 */
	function moduleContent_publish()	{
413
		global	$LANG;
414
415
416
417
418
419
420
421
422
423

			// Initialize:
		$content = '';
		$details = t3lib_div::_GP('details');

			// Create additional menus:
		$menu = '';
		if ($GLOBALS['BE_USER']->workspace===0)	{
			$menu.= t3lib_BEfunc::getFuncMenu(0,'SET[filter]',$this->MOD_SETTINGS['filter'],$this->MOD_MENU['filter']);
			$menu.= t3lib_BEfunc::getFuncMenu(0,'SET[display]',$this->MOD_SETTINGS['display'],$this->MOD_MENU['display']);
Kasper Skårhøj's avatar
   
Kasper Skårhøj committed
424
425
426
		}
		$menu.= t3lib_BEfunc::getFuncMenu(0,'SET[diff]',$this->MOD_SETTINGS['diff'],$this->MOD_MENU['diff']);
		if ($GLOBALS['BE_USER']->workspace!==0)	{
427
			$menu.= t3lib_BEfunc::getFuncCheck(0,'SET[expandSubElements]',$this->MOD_SETTINGS['expandSubElements'],'','','id="checkExpandSubElements"').' <label for="checkExpandSubElements">'.$LANG->getLL('label_showsubelements').'</label> ';
428
429
430
431
432
433
434
		}

			// Create header:
		$title = '';
		$description = '';
		switch($GLOBALS['BE_USER']->workspace)	{
			case 0:
435
				$title = t3lib_iconWorks::getIconImage('sys_workspace', array(), $this->doc->backPath, ' align="top"').'['.$LANG->getLL('shortcut_onlineWS').']';
436
				$description = $LANG->getLL('workspace_description_live');
437
438
			break;
			case -1:
439
				$title = t3lib_iconWorks::getIconImage('sys_workspace', array(), $this->doc->backPath, ' align="top"').'['.$LANG->getLL('shortcut_offlineWS').']';
440
				$description = $LANG->getLL('workspace_description_draft');
441
442
			break;
			case -99:
443
				$title = $this->doc->icons(3).'[' . $LANG->getLL('shortcut_noWSfound') . ']';
444
				$description = $LANG->getLL('workspace_description_no_access');
445
446
447
448
			break;
			default:
				$title = t3lib_iconWorks::getIconImage('sys_workspace', $GLOBALS['BE_USER']->workspaceRec, $this->doc->backPath, ' align="top"').
							'['.$GLOBALS['BE_USER']->workspace.'] '.t3lib_BEfunc::getRecordTitle('sys_workspace',$GLOBALS['BE_USER']->workspaceRec,TRUE);
449
				$description = $GLOBALS['BE_USER']->workspaceRec['description'];
450
451
452
453
454
455
			break;
		}

			// Buttons for publish / swap:
		$actionLinks = '';
		if ($GLOBALS['BE_USER']->workspace!==0)	{
Kasper Skårhøj's avatar
   
Kasper Skårhøj committed
456
			if ($this->publishAccess)	{
457
				$confirmation = $LANG->JScharCode($LANG->getLL(($GLOBALS['BE_USER']->workspaceRec['publish_access'] & 1) ? 'submit_publish_workspace_confirmation_1' :  'submit_publish_workspace_confirmation_2'));
458
				$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"/>';
Kasper Skårhøj's avatar
   
Kasper Skårhøj committed
459
				if ($GLOBALS['BE_USER']->workspaceSwapAccess())	{
460
					$confirmation = $LANG->JScharCode($LANG->getLL(($GLOBALS['BE_USER']->workspaceRec['publish_access'] & 1) ? 'submit_swap_workspace_confirmation_1' :  'submit_swap_workspace_confirmation_2'));
461
					$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 ;" />';
Kasper Skårhøj's avatar
   
Kasper Skårhøj committed
462
463
				}
			} else {
464
				$actionLinks.= $this->doc->icons(1) . $LANG->getLL('no_publish_permission');
Kasper Skårhøj's avatar
   
Kasper Skårhøj committed
465
			}
Ingo Renner's avatar
Ingo Renner committed
466

467
468
				// Preview of workspace link
			if (t3lib_div::_POST('_previewLink'))	{
469
470
				$ttlHours = intval($GLOBALS['BE_USER']->getTSConfigVal('options.workspaces.previewLinkTTLHours'));
				$ttlHours = ($ttlHours ? $ttlHours : 24*2);
471
				$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']);
472
				$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>';
473
474
475
			} else {
				$actionLinks.= '<input type="submit" name="_previewLink" value="Generate Workspace Preview Link" />';
			}
476
477
		}

Kasper Skårhøj's avatar
   
Kasper Skårhøj committed
478
479
		$wsAccess = $GLOBALS['BE_USER']->checkWorkspace($GLOBALS['BE_USER']->workspaceRec);

480
481
			// Add header to content variable:
		$content = '
482
		<table border="0" cellpadding="0" cellspacing="0" id="t3-user-ws-wsinfotable" class="t3-table t3-table-info">
483
			<tr>
484
485
				<td class="t3-col-header" nowrap="nowrap">' . $LANG->getLL('label_workspace') . '&nbsp;</th>
				<td nowrap="nowrap">' . $title . '</td>
486
			</tr>
487
			<tr>' . ($description ? '
488
489
				<td class="t3-col-header" nowrap="nowrap">' . $LANG->getLL('label_description') . '&nbsp;</td>
				<td>' . $description . '</td>
490
			</tr>' : '') . ($GLOBALS['BE_USER']->workspace!=-99 && !$details ? '
491
			<tr>
492
493
				<td class="t3-col-header" nowrap="nowrap">' . $LANG->getLL('label_options') . '&nbsp;</td>
				<td>' . $menu . $actionLinks . '</td>
Kasper Skårhøj's avatar
   
Kasper Skårhøj committed
494
495
			</tr>
			<tr>
496
497
				<td class="t3-col-header" nowrap="nowrap">' . $LANG->getLL('label_status') . '&nbsp;</td>
				<td>' . $LANG->getLL('label_access_level') . ' ' . $GLOBALS['LANG']->getLL('workspace_list_access_' . $wsAccess['_ACCESS']) . '</td>
498
499
			</tr>' : '').'
		</table>
500
		<br />
501
502
503
504
505
506
507
508
509
		';

			// Add publishing and review overview:
		if ($GLOBALS['BE_USER']->workspace!=-99)	{
			if ($details)	{
				$content.= $this->displayVersionDetails($details);
			} else {
				$content.= $this->displayWorkspaceOverview();
			}
510
			$content .= '<br />';
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
		}

			// Return content:
		return $content;
	}

	/**
	 * Display details for a single version from workspace
	 *
	 * @param	string		Version identification, made of table and uid
	 * @return	string		HTML string
	 */
	function displayVersionDetails($details)	{
		return 'TODO: Show details for version "'.$details.'"<hr/><a href="index.php">BACK</a>';
	}

	/**
	 * Rendering the overview of versions in the current workspace
	 *
	 * @return	string		HTML (table)
	 */
	function displayWorkspaceOverview()	{
Kasper Skårhøj's avatar
Kasper Skårhøj committed
533

534
535
536
537
538
539
540
541
542
			// Initialize Workspace ID and filter-value:
		if ($GLOBALS['BE_USER']->workspace===0)	{
			$wsid = $this->MOD_SETTINGS['display'];		// Set wsid to the value from the menu (displaying content of other workspaces)
			$filter = $this->MOD_SETTINGS['filter'];
		} else {
			$wsid = $GLOBALS['BE_USER']->workspace;
			$filter = 0;
		}

543
544
545
546
547
548
			// Instantiate workspace GUI library and generate workspace overview
		$wslibGuiObj = t3lib_div::makeInstance('wslib_gui');
		$wslibGuiObj->diff = $this->MOD_SETTINGS['diff'];
		$wslibGuiObj->expandSubElements = $this->MOD_SETTINGS['expandSubElements'];
		$wslibGuiObj->alwaysDisplayHeader = true;
		return $wslibGuiObj->getWorkspaceOverview($this->doc, $wsid, $filter);
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
	}













	/********************************
	 *
	 * Module content: Workspace list
	 *
	 ********************************/

	/**
	 * Rendering of the workspace list
	 *
	 * @return	string		HTML
	 */
	function moduleContent_workspaceList()	{
575
576
577
578
579
580
581
		// Original Kasper's TODO: Workspace listing
		//
		//	- 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.
		//	- SWITCHING: Switching between available workspaces is done by a button shown for each in the list
		//	- 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)
		//	- 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!).
		return $this->workspaceList_displayUserWorkspaceList();
582
583
584
585
	}

	/**
	 * Generates HTML to display a list of workspaces.
586
587
	 *
	 * @return	string		Generated HTML code
588
	 */
589
	function workspaceList_displayUserWorkspaceList()	{
590
		global	$BACK_PATH, $LANG;
591

592
			// table header
593
594
		$content = $this->workspaceList_displayUserWorkspaceListHeader();

595
			// get & walk workspace list generating content
596
		$wkspList = $this->workspaceList_getUserWorkspaceList();
597
598
		$rowNum = 1;
		foreach ($wkspList as $wksp)	{
599
			$currentWksp = ($GLOBALS['BE_USER']->workspace == $wksp['uid']);
600

601
602
603
604
			// Each workspace data occupies two rows:
			// (1) Folding + Icons + Title + Description
			// (2) Information about workspace (initially hidden)

605
			$cssClass = ($currentWksp ? 't3-row t3-row-active bgColor3' : 't3-row bgColor4');
606
				// Start first row
607
			$content .= '<tr class="' . $cssClass . '">';
608
609

				// row #1, column #1: expand icon
610
611
			$content .= '<td>' .
						'<a href="javascript:expandCollapse(' . $rowNum . ')">' .
612
613
614
615
						t3lib_iconWorks::getSpriteIcon('actions-view-table-expand', array(
							'title' => $LANG->getLL('img_title_show_more'),
							'id' => 'spanw1_' . $rowNum
						)) .
616
617
						'</a></td>';

618
619
				// row #1, column #2: icon panel
			$content .= '<td nowrap="nowrap">';	// Mozilla Firefox will attempt wrap due to `width="1"` on topmost column
620
621
622
			$content .= $this->workspaceList_displayIcons($currentWksp, $wksp);
			$content .= '</td>';

623
624
				// row #1, column #3: current workspace indicator
			$content .= '<td nowrap="nowrap" style="text-align: center">';	// Mozilla Firefox will attempt wrap due to `width="1"` on topmost column
625
			$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') . '" />');
626
627
			$content .= '</td>';

628
				// row #1, column #4 and 5: title and description
629
630
			$content .= '<td nowrap="nowrap">' . htmlspecialchars($wksp['title']) . '</td>' .
						'<td>' . nl2br(htmlspecialchars($wksp['description'])) . '</td>';
631
632
			$content .= '</tr>';

633
				// row #2, column #1 and #2
634
635
636
			$content .= '<tr id="wl_' . $rowNum . '" class="bgColor" style="display: none">';
			$content .= '<td colspan="2" style="border-right: none;">&nbsp;</td>';

637
				// row #2, column #3, #4 and #4
638
			$content .= '<td colspan="3" style="border-left: none;">' .
639
						$this->workspaceList_formatWorkspaceData($wksp) .
640
						'</td>';
641

642
643
644
645
646
			$content .= '</tr>';
			$rowNum++;
		}
		$content .= '</table>';

647
		return $content;
648
649
	}

650
651
652
653




654
655
	/**
	 * Retrieves a list of workspaces where user has access.
656
657
	 *
	 * @return	array		A list of workspaces available to the current BE user
658
	 */
659
	function workspaceList_getUserWorkspaceList()	{
660

661
			// Get list of all workspaces. Note: system workspaces will be always displayed before custom ones!
662
663
664
		$workspaces = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*','sys_workspace','pid=0'.t3lib_BEfunc::deleteClause('sys_workspace'),'','title');
		$availableWorkspaces = array();

665
			// Live
666
667
		$wksp = $this->workspaceList_createFakeWorkspaceRecord(0);
		$wksp = $GLOBALS['BE_USER']->checkWorkspace($wksp);
668
669
670
		if (false !== $wksp) {
			$availableWorkspaces[] = $wksp;
		}
671

672
			// Draft
673
674
		$wksp = $this->workspaceList_createFakeWorkspaceRecord(-1);
		$wksp = $GLOBALS['BE_USER']->checkWorkspace($wksp);
675
676
677
		if (false !== $wksp) {
			$availableWorkspaces[] = $wksp;
		}
678
679
680
681
682
683

			// Custom
		foreach($workspaces as $rec)	{
				// see if user can access this workspace in any way
			if (false !== ($result = $GLOBALS['BE_USER']->checkWorkspace($rec)))	{
				$availableWorkspaces[] = $result;	// `$result` contains `$rec` plus access type through '_ACCESS' key
684
685
686
687
			}
		}
		return $availableWorkspaces;
	}
688

689
690
691
692
693
	/**
	 * Create inner information panel for workspace list. This panel is
	 * initially hidden and becomes visible when user click on the expand
	 * icon on the very left of workspace list against the workspace he
	 * wants to explore.
694
695
696
	 *
	 * @param	array		Workspace information
	 * @return	string		Formatted workspace information
697
	 */
698
	function workspaceList_formatWorkspaceData(&$wksp)	{
699
		global $LANG;
700

701
		$content = '<table cellspacing="0" cellpadding="0" width="100%" class="ver-wl-details-table">' .
702
				'<tr><td class="ver-wl-details-label"><strong>' . $LANG->getLL('workspace_list_label_file_mountpoints') . '</strong></td>' .
703
				'<td class="ver-wl-details">' . $this->workspaceList_getFileMountPoints($wksp) . '</td></tr>' .
704
				'<tr><td class="ver-wl-details-label"><strong>' . $LANG->getLL('workspace_list_label_db_mountpoints') . '</strong></td>' .
705
706
707
708
				'<td class="ver-wl-details">' . $this->workspaceList_getWebMountPoints($wksp) . '</td></tr>';
		if ($wksp['uid'] > 0) {
			// Displaying information below makes sence only for custom workspaces
			$content .=
709
				'<tr><td class="ver-wl-details-label"><strong>' . $LANG->getLL('workspace_list_label_frozen') . '</strong></td>' .
710
				'<td class="ver-wl-details">' . $LANG->getLL($wksp['freeze'] ? 'workspace_list_label_frozen_yes' : 'workspace_list_label_frozen_no') . '</td></tr>' .
711
				'<tr><td class="ver-wl-details-label"><strong>' . $LANG->getLL('workspace_list_label_publish_date') . '</strong></td>' .
712
				'<td class="ver-wl-details">' . ($wksp['publish_time'] == 0 ? '&nbsp;&ndash;' : t3lib_BEfunc::datetime($wksp['publish_time'])) . '</td></tr>' .
713
				'<tr><td class="ver-wl-details-label"><strong>' . $LANG->getLL('workspace_list_label_unpublish_date') . '</strong></td>' .
714
				'<td class="ver-wl-details">' . ($wksp['unpublish_time'] == 0 ? '&nbsp;&ndash;' : t3lib_BEfunc::datetime($wksp['unpublish_time'])) . '</td></tr>' .
715
				'<tr><td class="ver-wl-details-label"><strong>' . $LANG->getLL('workspace_list_label_your_access') . '</strong></td>' .
716
				'<td class="ver-wl-details">' . $LANG->getLL('workspace_list_access_' . $wksp['_ACCESS']) . '</td></tr>' .
717
				'<tr><td class="ver-wl-details-label"><strong>' . $LANG->getLL('workspace_list_label_workspace_users') . '</strong></td>' .
718
719
720
721
				'<td class="ver-wl-details">' . $this->workspaceList_getUserList($wksp) . '</td></tr>';
		}
		else if ($GLOBALS['BE_USER']->isAdmin()) {
			// show users for draft/live workspace only to admin users
722
			$content .=	'<tr><td class="ver-wl-details-label"><strong>' . $LANG->getLL('workspace_list_label_workspace_users') . '</strong></td>' .
723
724
725
726
				'<td class="ver-wl-details">' . $this->workspaceList_getUserList($wksp) . '</td></tr>';
		}
		$content .= '</table>';

727
728
729
		return $content;
	}

730

731
732
733



734
	/**
735
	 * Retrieves and formats database mount points lists.
736
	 *
737
	 * @param	array		&$wksp	Workspace record
738
	 * @return	string		Generated HTML
739
	 */
740
741
742
743
	function workspaceList_getWebMountPoints(&$wksp)	{
		if ($wksp['uid'] <= 0) {
			// system workspaces
			return $GLOBALS['LANG']->getLL($wksp['uid'] == 0 ? 'workspace_list_db_mount_point_live' : 'workspace_list_db_mount_point_draft');
744
		}
745
746
747
748
749

		// here only if obtaining mount points for custom workspaces

		// Warning: all fields needed for t3lib_iconWorks::getIconImage()!
		$MPs = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'pages', 'deleted=0 AND uid IN (' . $GLOBALS['TYPO3_DB']->cleanIntList($wksp['db_mountpoints']) . ')', '', 'title');
750
		$content_array = array();
751
752
753
754
755
756
757
758
759
760
761
762
		if (count($MPs) > 0)	{
			$isAdmin = $GLOBALS['BE_USER']->isAdmin();
			if (!$isAdmin) {
				// We need to fetch user's mount point list (including MPS mounted from groups).
				// This list must not be affects by current user's workspace. It means we cannot use
				// $BE_USER->isInWebMount() to check mount points.
				$userMPs = explode(',', $GLOBALS['BE_USER']->dataLists['webmount_list']); // includes group data if necessary!
			}
			foreach ($MPs as $mp)	{
				if (!$isAdmin && !in_array($mp['uid'], $userMPs)) {
					// Show warning icon
					$title = $GLOBALS['LANG']->getLL('workspace_list_mount_point_inaccessible');
763
					$str = t3lib_iconWorks::getSpriteIcon('status-warning');
764
765
766
767
768
769
770
					$classAttr = 'class="ver-wl-mp-inacessible" ';
				}
				else {
					// normal icon
					$str = t3lib_iconWorks::getIconImage('pages', $mp, $GLOBALS['BACK_PATH'], ' align="absmiddle"');
					$classAttr = '';
				}
771
				// Will show UID on hover. Just convinient to user.
772
773
				$content_array[] = $str . '<span ' . $classAttr . 'title="UID: ' . $mp['uid'] . '">' . $mp['title'] . '</span>';
			}
774
		}
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
		if (count($content_array) > 0) {
			return implode('<br />', $content_array);
		}
		// no mount points
		return $GLOBALS['LANG']->getLL('workspace_list_db_mount_point_custom');
	}

	/**
	 * Retrieves and formats file mount points lists.
	 *
	 * @param	array		&$wksp	Workspace record
	 * @return	string		Generated HTML
	 */
	function workspaceList_getFileMountPoints(&$wksp)	{
		if ($wksp['uid'] == -1) {
			// draft workspace - none!
			return $GLOBALS['LANG']->getLL('workspace_list_file_mount_point_draft');
		}
		else if ($wksp['uid'] == 0) {
			// live workspace
			return $GLOBALS['LANG']->getLL('workspace_list_file_mount_point_live');
		}

		// Here if displaying information for custom workspace

		// Warning: all fields needed for t3lib_iconWorks::getIconImage()!
		$MPs = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'sys_filemounts', 'deleted=0 AND hidden=0 AND uid IN (' . $GLOBALS['TYPO3_DB']->cleanIntList($wksp['file_mountpoints']) . ')', '', 'title');
		if (count($MPs) != 0)	{
			// Has mount points
			$isAdmin = $GLOBALS['BE_USER']->isAdmin();
			if (!$isAdmin) {
				// We need to fetch user's mount point list (including MPS mounted from groups).
				// This list must not be affects by current user's workspace. It means we cannot use
				// $BE_USER->isInWebMount() to check mount points.
				$userMPs = explode(',', $GLOBALS['BE_USER']->dataLists['filemount_list']); // includes group data if necessary!
			}
			foreach ($MPs as $mp)	{
				if (!$isAdmin && !in_array($mp['uid'], $userMPs)) {
					// Show warning icon
					$title = $GLOBALS['LANG']->getLL('workspace_list_mount_point_inaccessible');
815
					$str = t3lib_iconWorks::getSpriteIcon('status-warning');
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
					$classAttr = 'class="ver-wl-mp-inacessible" ';
				}
				else {
					// normal icon
					$str = t3lib_iconWorks::getIconImage('sys_filemounts', $mp, $GLOBALS['BACK_PATH'], ' align="absmiddle"');
					$classAttr = '';
				}
				// Will show UID on hover. Just convinient to user.
				$content_array[] = $str . '<span ' . $classAttr . 'title="UID: ' . $mp['uid'] . '">' . $mp['title'] . '</span>';
			}
		}
		if (count($content_array) > 0) {
			return implode('<br />', $content_array);
		}
		// No file mount points
		return $GLOBALS['LANG']->getLL('workspace_list_file_mount_point_custom');
832
833
	}

834
835
836
	/**
	 * Creates a header for the workspace list table. This function only makes
	 * <code>workspaceList_displayUserWorkspaceList()</code> smaller.
837
838
	 *
	 * @return	string		Generated content
839
	 */
840
	function workspaceList_displayUserWorkspaceListHeader()	{
841
		global	$LANG;
842
		// TODO CSH lables?
843
844
		return '<table border="0" cellpadding="0" cellspacing="0" class="workspace-overview">
			<tr class="t3-row-header">
845
846
				<td width="1">&nbsp;</td>
				<td width="1">&nbsp;</td>
847
848
849
				<td nowrap="nowrap">' . $LANG->getLL('workspace_list_label_current_workspace') . '</td>
				<td nowrap="nowrap">' . $LANG->getLL('workspace_list_label_workspace_title') . '</td>
				<td nowrap="nowrap">' . $LANG->getLL('workspace_list_label_workspace_description') . '</td>
850
851
			</tr>';
	}
852

853

854
855
	/**
	 * Generates a list of <code>&lt;option&gt;</code> tags with user names.
856
857
858
	 *
	 * @param	array		Workspace record
	 * @return	string		Generated content
859
	 */
860
	function workspaceList_getUserList(&$wksp) {
861
862
		global	$LANG;

863
864
865
866
867
868
869
870
871
872
873
874
875
876
		if ($wksp['uid'] > 0) {
			// custom workspaces
			$content = $this->workspaceList_getUserListWithAccess($wksp['adminusers'], $LANG->getLL('workspace_list_label_owners')); // owners
			$content .= $this->workspaceList_getUserListWithAccess($wksp['members'], $LANG->getLL('workspace_list_label_members')); // members
			$content .= $this->workspaceList_getUserListWithAccess($wksp['reviewers'], $LANG->getLL('workspace_list_label_reviewers')); // reviewers
			if ($content != '')	{
				$content = '<table cellpadding="0" cellspacing="1" width="100%" class="lrPadding workspace-overview">' . $content . '</table>';
			} else {
				$content = $LANG->getLL($wksp['uid'] > 0 ? 'workspace_list_access_admins_only' : 'workspace_list_access_anyone');
			}
		}
		else {
			// live and draft workspace
			$content = $this->workspaceList_getUserListForSysWorkspace($wksp);
877
878
879
880
881
		}
		return $content;
	}

	/**
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
	 * Generates a list of user names that has access to the system workspace.
	 *
	 * @param	array		&$wksp	Workspace record
	 * @return	string		Generated content
	 */
	function workspaceList_getUserListForSysWorkspace(&$wksp) {
		$option = ($wksp['uid'] == 0 ? 1 : 2);
		$content_array = array();
		foreach ($this->be_user_Array_full as $uid => $user) {
			if ($user['admin'] != 0 || 0 != ($user['workspace_perms'] & $option)) {
				if ($uid == $GLOBALS['BE_USER']->user['uid']) {
					// highlight current user
					$tag0 = '<span class="ver-wl-current-user">';
					$tag1 = '</span>';
				}
				else {
					$tag0 = $tag1 = '';
				}
Kasper Skårhøj's avatar
   
Kasper Skårhøj committed
900
				$content_array[] = $this->doc->wrapClickMenuOnIcon(t3lib_iconWorks::getIconImage('be_users', $uid, $GLOBALS['BACK_PATH'], ' align="middle" alt="UID: ' . $uid . '"'), 'be_users', $uid, 2).
901
					$tag0 . htmlspecialchars($user['username']) . $tag1;
902
903
904
905
906
907
908
			}
		}
		return implode('<br />', $content_array);
	}

	/**
	 * Generates a list of user names that has access to the workspace.
909
910
911
912
	 *
	 * @param	array		A list of user IDs separated by comma
	 * @param	string		Access string
	 * @return	string		Generated content
913
	 */
914
	function workspaceList_getUserListWithAccess(&$list, $access)	{
915
		$content_array = array();
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
		if ($list != '')	{
			$userIDs = explode(',', $list);

				// get user names and sort
			$regExp = '/^(be_[^_]+)_(\d+)$/';
			$groups = false;
			foreach ($userIDs as $userUID)	{
				$id = $userUID;

				if (preg_match($regExp, $userUID)) {
					$table = preg_replace($regExp, '\1', $userUID);
					$id = intval(preg_replace($regExp, '\2', $userUID));
					if ($table == 'be_users') {
						// user
						$icon = $GLOBALS['TCA']['be_users']['typeicons'][$this->be_user_Array[$id]['admin']];
931
932
933
934
935
936
937
938
						if ($id == $GLOBALS['BE_USER']->user['uid']) {
							// highlight current user
							$tag0 = '<span class="ver-wl-current-user">';
							$tag1 = '</span>';
						}
						else {
							$tag0 = $tag1 = '';
						}
Kasper Skårhøj's avatar
   
Kasper Skårhøj committed
939
						$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) .
940
											$tag0 . htmlspecialchars($this->be_user_Array_full[$id]['username']) . $tag1;
941
942
943
944
945
946
					}
					else {
						// group
						if (false === $groups) {
							$groups = t3lib_BEfunc::getGroupNames();
						}
Kasper Skårhøj's avatar
   
Kasper Skårhøj committed
947
						$content_array[] = $this->doc->wrapClickMenuOnIcon(t3lib_iconWorks::getIconImage($table, $groups[$id], $GLOBALS['BACK_PATH'], ' align="middle" alt="UID: ' . $id . '"'), $table, $id, 2) .
948
949
950
951
952
											$groups[$id]['title'];
					}
				}
				else {
					// user id
953
954
955
956
957
958
959
960
961
					if ($userUID == $GLOBALS['BE_USER']->user['uid']) {
						// highlight current user
						$tag0 = '<span class="ver-wl-current-user">';
						$tag1 = '</span>';
					}
					else {
						$tag0 = $tag1 = '';
					}
					$content_array[] = t3lib_iconWorks::getIconImage('be_users', $this->be_user_Array[$id], $GLOBALS['BACK_PATH'], ' align="middle" alt="UID: ' . $id . '"') .
962
										$tag0 . htmlspecialchars($this->be_user_Array_full[$userUID]['username']) . $tag1;
963
964
965
966
967
968
				}
			}
			sort($content_array);
		}
		else {
			$content_array[] = '&nbsp;&ndash;';
969
970
		}

971
		$content = '<tr><td class="ver-wl-details-label ver-wl-details-user-list-label">';
972
		// TODO CSH lable explaining access here?
973
		$content .= '<strong>' . $access . '</strong></td>';
974
		$content .= '<td class="ver-wl-details">' . implode('<br />', $content_array) . '</td></tr>';
975
976
977
		return $content;
	}

978
979


980
981
	/**
	 * Creates a list of icons for workspace.
982
983
984
985
	 *
	 * @param	boolean		<code>true</code> if current workspace
	 * @param	array		Workspace record
	 * @return	string		Generated content
986
	 */
987
	function workspaceList_displayIcons($currentWorkspace, &$wksp)	{
988
		global	$BACK_PATH, $LANG;
989
990

		$content = '';
991
992
993
			// `edit workspace` button
		if ($this->workspaceList_hasEditAccess($wksp))	{
				// User can modify workspace parameters, display corresponding link and icon
994
			$editUrl = 'workspaceforms.php?action=edit&amp;wkspId=' . $wksp['uid'];
995

996
997
998
			$content .= '<a href="' . $editUrl . '" title="'. $LANG->getLL('workspace_list_icon_title_edit_workspace') .'"/>' .
					t3lib_iconWorks::getSpriteIcon('actions-document-open') .
			'</a>';
999
1000
		} else {
				// User can NOT modify workspace parameters, display space
For faster browsing, not all history is shown. View entire blame