71d767394e97057de7f5ba00ee3341c26c17bae5
[Packages/TYPO3.CMS.git] / typo3 / sysext / version / cm1 / index.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2004-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24 /**
25 * Versioning module
26 *
27 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
28 */
29 /**
30 * [CLASS/FUNCTION INDEX of SCRIPT]
31 *
32 *
33 *
34 * 102: class tx_version_cm1 extends t3lib_SCbase
35 *
36 * SECTION: Standard module initialization
37 * 138: function menuConfig()
38 * 175: function main()
39 * 236: function jumpToUrl(URL)
40 * 296: function printContent()
41 *
42 * SECTION: Versioning management
43 * 322: function versioningMgm()
44 * 485: function pageSubContent($pid,$c=0)
45 * 539: function lookForOwnVersions($table,$uid)
46 * 556: function adminLinks($table,$row)
47 *
48 * SECTION: Workspace management
49 * 628: function workspaceMgm()
50 * 688: function displayWorkspaceOverview()
51 * 758: function displayWorkspaceOverview_list($pArray)
52 * 923: function displayWorkspaceOverview_setInPageArray(&$pArray,$table,$row)
53 * 936: function displayWorkspaceOverview_allStageCmd()
54 *
55 * SECTION: Helper functions (REDUNDANT FROM user/ws/index.php - someone could refactor this...)
56 * 986: function formatVerId($verId)
57 * 996: function formatWorkspace($wsid)
58 * 1023: function formatCount($count)
59 * 1050: function versionsInOtherWS($table,$uid)
60 * 1080: function showStageChangeLog($table,$id,$stageCommands)
61 * 1129: function subElements($uid,$treeLevel,$origId=0)
62 * 1232: function subElements_getNonPageRecords($tN, $uid, &$recList)
63 * 1262: function subElements_renderItem(&$tCell,$tN,$uid,$rec,$origId,$iconMode,$HTMLdata)
64 * 1331: function markupNewOriginals()
65 * 1353: function createDiffView($table, $diff_1_record, $diff_2_record)
66 * 1470: function displayWorkspaceOverview_stageCmd($table,&$rec_off)
67 * 1557: function displayWorkspaceOverview_commandLinks($table,&$rec_on,&$rec_off,$vType)
68 * 1627: function displayWorkspaceOverview_commandLinksSub($table,$rec,$origId)
69 *
70 * SECTION: Processing
71 * 1683: function publishAction()
72 *
73 * TOTAL FUNCTIONS: 27
74 * (This index is automatically created/updated by the extension "extdeveval")
75 *
76 */
77
78
79 // DEFAULT initialization of a module [BEGIN]
80 unset($MCONF);
81 require ('conf.php');
82 require ($BACK_PATH.'init.php');
83 require ($BACK_PATH.'template.php');
84 $LANG->includeLLFile('EXT:version/locallang.xml');
85 require_once (PATH_t3lib.'class.t3lib_scbase.php');
86 // DEFAULT initialization of a module [END]
87
88 require_once(PATH_t3lib.'class.t3lib_diff.php');
89 require_once(PATH_typo3.'mod/user/ws/class.wslib.php');
90 require_once(PATH_t3lib.'class.t3lib_pagetree.php');
91 require_once(PATH_t3lib.'class.t3lib_tcemain.php');
92
93
94
95 /**
96 * Versioning module, including workspace management
97 *
98 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
99 * @package TYPO3
100 * @subpackage core
101 */
102 class tx_version_cm1 extends t3lib_SCbase {
103
104 // Default variables for backend modules
105 var $MCONF = array(); // Module configuration
106 var $MOD_MENU = array(); // Module menu items
107 var $MOD_SETTINGS = array(); // Module session settings
108
109 /**
110 * document template object
111 *
112 * @var mediumDoc
113 */
114 var $doc;
115 var $content; // Accumulated content
116
117
118 // Internal:
119 var $showWorkspaceCol = 0;
120 var $formatWorkspace_cache = array();
121 var $formatCount_cache = array();
122 var $targets = array(); // Accumulation of online targets.
123 var $pageModule = ''; // Name of page module
124 var $publishAccess = FALSE;
125 var $be_user_Array = array();
126 var $stageIndex = array();
127 var $recIndex = array();
128
129
130
131
132
133
134 /*********************************
135 *
136 * Standard module initialization
137 *
138 *********************************/
139
140 /**
141 * Initialize menu configuration
142 *
143 * @return void
144 */
145 function menuConfig() {
146
147 // Menu items:
148 $this->MOD_MENU = array(
149 'filter' => array(
150 1 => 'Drafts',
151 2 => 'Archive',
152 0 => 'All',
153 ),
154 'display' => array(
155 0 => '[Live workspace]',
156 -98 => 'Draft Workspaces',
157 -99 => 'All',
158 -1 => '[Default Draft]'
159 ),
160 'diff' => ''
161 );
162
163 // Add workspaces:
164 if ($GLOBALS['BE_USER']->workspace===0) { // Spend time on this only in online workspace because it might take time:
165 $workspaces = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,title,adminusers,members,reviewers','sys_workspace','pid=0'.t3lib_BEfunc::deleteClause('sys_workspace'),'','title');
166 foreach($workspaces as $rec) {
167 if ($GLOBALS['BE_USER']->checkWorkspace($rec)) {
168 $this->MOD_MENU['display'][$rec['uid']] = '['.$rec['uid'].'] '.$rec['title'];
169 }
170 }
171 }
172
173 // CLEANSE SETTINGS
174 $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name'], 'ses');
175 }
176
177 /**
178 * Main function of the module. Write the content to $this->content
179 *
180 * @return void
181 */
182 function main() {
183 global $BE_USER,$LANG,$BACK_PATH,$TCA_DESCR,$TCA,$CLIENT,$TYPO3_CONF_VARS;
184
185 // Setting module configuration:
186 $this->MCONF = $GLOBALS['MCONF'];
187
188 $this->REQUEST_URI = str_replace('&sendToReview=1','',t3lib_div::getIndpEnv('REQUEST_URI'));
189
190 // Draw the header.
191 $this->doc = t3lib_div::makeInstance('mediumDoc');
192 $this->doc->backPath = $BACK_PATH;
193 $this->doc->form='<form action="" method="post">';
194
195 // Add styles
196 $this->doc->inDocStylesArray[$GLOBALS['MCONF']['name']] = '
197 .version-diff-1 { background-color: green; }
198 .version-diff-2 { background-color: red; }
199 ';
200
201 // Setting up the context sensitive menu:
202 $this->doc->getContextMenuCode();
203
204 // Getting input data:
205 $this->id = intval(t3lib_div::_GP('id')); // Page id. If set, indicates activation from Web>Versioning module
206 if (!$this->id) {
207 $this->uid = intval(t3lib_div::_GP('uid')); // Record uid. Goes with table name to indicate specific record
208 $this->table = t3lib_div::_GP('table'); // Record table. Goes with uid to indicate specific record
209 } else {
210 $this->uid = $this->id;
211 $this->table = 'pages';
212 }
213 $this->details = t3lib_div::_GP('details'); // Page id. If set, indicates activation from Web>Versioning module
214 $this->diffOnly = t3lib_div::_GP('diffOnly'); // Flag. If set, shows only the offline version and with diff-view
215
216 // Force this setting:
217 $this->MOD_SETTINGS['expandSubElements'] = TRUE;
218 $this->MOD_SETTINGS['diff'] = $this->details || $this->MOD_SETTINGS['diff']?1:0;
219
220 // Reading the record:
221 $record = t3lib_BEfunc::getRecord($this->table,$this->uid);
222 if ($record['pid']==-1) {
223 $record = t3lib_BEfunc::getRecord($this->table,$record['t3ver_oid']);
224 }
225 $pidValue = $this->table==='pages' ? $this->uid : $record['pid'];
226
227 // Checking access etc.
228 if (is_array($record) && $TCA[$this->table]['ctrl']['versioningWS']) {
229 $this->uid = $record['uid']; // Might have changed if new live record was found!
230
231 // Access check!
232 // The page will show only if there is a valid page and if this page may be viewed by the user
233 $this->pageinfo = t3lib_BEfunc::readPageAccess($pidValue,$this->perms_clause);
234 $access = is_array($this->pageinfo) ? 1 : 0;
235
236 if (($pidValue && $access) || ($BE_USER->user['admin'] && !$pidValue)) {
237
238 // JavaScript
239 $this->doc->JScode.= '
240 <script language="javascript" type="text/javascript">
241 script_ended = 0;
242 function jumpToUrl(URL) {
243 window.location.href = URL;
244 }
245
246 function hlSubelements(origId, verId, over, diffLayer) { //
247 if (over) {
248 document.getElementById(\'orig_\'+origId).attributes.getNamedItem("class").nodeValue = \'typo3-ver-hl\';
249 document.getElementById(\'ver_\'+verId).attributes.getNamedItem("class").nodeValue = \'typo3-ver-hl\';
250 if (diffLayer) {
251 document.getElementById(\'diff_\'+verId).style.visibility = \'visible\';
252 }
253 } else {
254 document.getElementById(\'orig_\'+origId).attributes.getNamedItem("class").nodeValue = \'typo3-ver\';
255 document.getElementById(\'ver_\'+verId).attributes.getNamedItem("class").nodeValue = \'typo3-ver\';
256 if (diffLayer) {
257 document.getElementById(\'diff_\'+verId).style.visibility = \'hidden\';
258 }
259 }
260 }
261 </script>
262 ';
263
264 // If another page module was specified, replace the default Page module with the new one
265 $newPageModule = trim($BE_USER->getTSConfigVal('options.overridePageModule'));
266 $this->pageModule = t3lib_BEfunc::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
267
268 // Setting publish access permission for workspace:
269 $this->publishAccess = $BE_USER->workspacePublishAccess($BE_USER->workspace);
270
271
272 $headerSection = $this->doc->getHeader('pages',$this->pageinfo,$this->pageinfo['_thePath']).'<br/>'.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.path').': '.t3lib_div::fixed_lgd_pre($this->pageinfo['_thePath'],50);
273
274 $this->content.=$this->doc->startPage($LANG->getLL('title'));
275 $this->content.=$this->doc->header($LANG->getLL('title'));
276 $this->content.=$this->doc->spacer(5);
277 $this->content.=$this->doc->section('',$headerSection);
278 $this->content.=$this->doc->divider(5);
279
280 // Render content:
281 if ($this->id) {
282 $this->workspaceMgm();
283 } else {
284 $this->versioningMgm();
285 }
286
287 // ShortCut
288 if ($BE_USER->mayMakeShortcut()) {
289 $this->content.=$this->doc->spacer(20).$this->doc->section('',$this->doc->makeShortcutIcon('id',implode(',',array_keys($this->MOD_MENU)),$this->MCONF['name']));
290 }
291 }
292
293 $this->content.=$this->doc->spacer(10);
294 } else {
295 // If no access or id value, create empty document:
296 $this->content.=$this->doc->startPage($LANG->getLL('title'));
297 $this->content.=$this->doc->section($LANG->getLL('clickAPage_header'),$LANG->getLL('clickAPage_content'),0,1);
298 }
299 }
300
301 /**
302 * Outputs accumulated module content to browser.
303 *
304 * @return void
305 */
306 function printContent() {
307
308 $this->content.=$this->doc->endPage();
309 echo $this->content;
310 }
311
312
313
314
315
316
317
318
319
320
321 /******************************
322 *
323 * Versioning management
324 *
325 ******************************/
326
327 /**
328 * Management of versions for record
329 *
330 * @return void
331 */
332 function versioningMgm() {
333 global $TCA;
334
335 // Diffing:
336 $diff_1 = t3lib_div::_POST('diff_1');
337 $diff_2 = t3lib_div::_POST('diff_2');
338 if (t3lib_div::_POST('do_diff')) {
339 $content='';
340 $content.='<h3>DIFFING:</h3>';
341 if ($diff_1 && $diff_2) {
342 $diff_1_record = t3lib_BEfunc::getRecord($this->table, $diff_1);
343 $diff_2_record = t3lib_BEfunc::getRecord($this->table, $diff_2);
344
345 if (is_array($diff_1_record) && is_array($diff_2_record)) {
346 t3lib_div::loadTCA($this->table);
347 $t3lib_diff_Obj = t3lib_div::makeInstance('t3lib_diff');
348
349 $tRows=array();
350 $tRows[] = '
351 <tr class="bgColor5 tableheader">
352 <td>Fieldname:</td>
353 <td width="98%">Colored diff-view:</td>
354 </tr>
355 ';
356 foreach($diff_1_record as $fN => $fV) {
357 if ($TCA[$this->table]['columns'][$fN] && $TCA[$this->table]['columns'][$fN]['config']['type']!='passthrough' && !t3lib_div::inList('t3ver_label',$fN)) {
358 if (strcmp($diff_1_record[$fN],$diff_2_record[$fN])) {
359
360 $diffres = $t3lib_diff_Obj->makeDiffDisplay(
361 t3lib_BEfunc::getProcessedValue($this->table,$fN,$diff_2_record[$fN],0,1),
362 t3lib_BEfunc::getProcessedValue($this->table,$fN,$diff_1_record[$fN],0,1)
363 );
364
365 $tRows[] = '
366 <tr class="bgColor4">
367 <td>'.$fN.'</td>
368 <td width="98%">'.$diffres.'</td>
369 </tr>
370 ';
371 }
372 }
373 }
374
375 if (count($tRows)>1) {
376 $content.='<table border="0" cellpadding="1" cellspacing="1" width="100%">'.implode('',$tRows).'</table><br/><br/>';
377 } else {
378 $content.='Records matches completely on all editable fields!';
379 }
380 } else $content.='ERROR: Records could strangely not be found!';
381 } else {
382 $content.='ERROR: You didn\'t select two sources for diffing!';
383 }
384 }
385
386 // Element:
387 $record = t3lib_BEfunc::getRecord($this->table,$this->uid);
388 $recordIcon = t3lib_iconWorks::getIconImage($this->table,$record,$this->doc->backPath,'class="absmiddle"');
389 $recTitle = t3lib_BEfunc::getRecordTitle($this->table,$record,TRUE);
390
391 // Display versions:
392 $content.='
393 '.$recordIcon.$recTitle.'
394 <form name="theform" action="'.str_replace('&sendToReview=1','',$this->REQUEST_URI).'" method="post">
395 <table border="0" cellspacing="1" cellpadding="1">';
396 $content.='
397 <tr class="bgColor5 tableheader">
398 <td>&nbsp;</td>
399 <td>&nbsp;</td>
400 <td>Title</td>
401 <td>UID</td>
402 <td title="t3ver_oid - Reference to live version UID">oid</td>
403 <td title="t3ver_id - Version number, incremental integer">id</td>
404 <td title="t3ver_wsid - Workspace ID. There can be only one version of an element per ID (except ID zero).">wsid</td>
405 <td title="t3ver_state - Special states of a version: 1=Placeholder for &quot;New&quot;. 2=Marked deleted.">state</td>
406 <td title="t3ver_stage - Publishing stage: Editing (0), review (1), publish (10), rejected (-1).">stage</td>
407 <td title="t3ver_count - Life cycle counter. Incremented each time element is unpublished.">count</td>
408 <td>pid</td>
409 <td>t3ver_label</td>
410 <td colspan="2"><input type="submit" name="do_diff" value="Diff" /></td>
411 </tr>';
412
413 $versions = t3lib_BEfunc::selectVersionsOfRecord($this->table, $this->uid, '*', $GLOBALS['BE_USER']->workspace);
414 foreach($versions as $row) {
415 $adminLinks = $this->adminLinks($this->table,$row);
416
417 $content.='
418 <tr class="'.($row['uid']!=$this->uid ? 'bgColor4' : 'bgColor2 tableheader').'">
419 <td>'.($row['uid']!=$this->uid ? '<a href="'.$this->doc->issueCommand('&cmd['.$this->table.']['.$this->uid.'][version][swapWith]='.$row['uid'].'&cmd['.$this->table.']['.$this->uid.'][version][action]=swap').'">'.
420 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert1.gif','width="14" height="14"').' alt="" title="SWAP with current" />'.
421 '</a>' /* (
422 $this->table == 'pages' ?
423 '<a href="'.$this->doc->issueCommand('&cmd['.$this->table.']['.$this->uid.'][version][action]=swap&cmd['.$this->table.']['.$this->uid.'][version][swapWith]='.$row['uid'].'&cmd['.$this->table.']['.$this->uid.'][version][swapContent]=1').'">'.
424 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert2.gif','width="14" height="14"').' alt="" title="Publish page AND content!" />'.
425 '</a>'.
426 '<a href="'.$this->doc->issueCommand('&cmd['.$this->table.']['.$this->uid.'][version][action]=swap&cmd['.$this->table.']['.$this->uid.'][version][swapWith]='.$row['uid'].'&cmd['.$this->table.']['.$this->uid.'][version][swapContent]=ALL').'">'.
427 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert4.gif','width="14" height="14"').' alt="" title="Publish page AND content! - AND ALL SUBPAGES!" />'.
428 '</a>' : '') */ : '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/blinkarrow_left.gif','width="5" height="9"').' alt="" title="CURRENT ONLINE VERSION!"/>').'</td>
429 <td nowrap="nowrap">'.$adminLinks.'</td>
430 <td nowrap="nowrap">'.t3lib_BEfunc::getRecordTitle($this->table,$row,TRUE).'</td>
431 <td>'.$row['uid'].'</td>
432 <td>'.$row['t3ver_oid'].'</td>
433 <td>'.$row['t3ver_id'].'</td>
434 <td>'.$row['t3ver_wsid'].'</td>
435 <td>'.$row['t3ver_state'].'</td>
436 <td>'.$row['t3ver_stage'].'</td>
437 <td>'.$row['t3ver_count'].'</td>
438 <td>'.$row['pid'].'</td>
439 <td nowrap="nowrap"><a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick('&edit['.$this->table.']['.$row['uid'].']=edit&columnsOnly=t3ver_label',$this->doc->backPath)).'"><img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/edit2.gif','width="11" height="12"').' alt="" title="Edit"/></a>'.htmlspecialchars($row['t3ver_label']).'</td>
440 <td class="version-diff-1"><input type="radio" name="diff_1" value="'.$row['uid'].'"'.($diff_1==$row['uid'] ? ' checked="checked"':'').'/></td>
441 <td class="version-diff-2"><input type="radio" name="diff_2" value="'.$row['uid'].'"'.($diff_2==$row['uid'] ? ' checked="checked"':'').'/></td>
442 </tr>';
443
444 // Show sub-content if the table is pages AND it is not the online branch (because that will mostly render the WHOLE tree below - not smart;)
445 if ($this->table == 'pages' && $row['uid']!=$this->uid) {
446 $sub = $this->pageSubContent($row['uid']);
447
448 if ($sub) {
449 $content.='
450 <tr>
451 <td></td>
452 <td></td>
453 <td colspan="10">'.$sub.'</td>
454 <td colspan="2"></td>
455 </tr>';
456 }
457 }
458 }
459 $content.='</table></form>';
460
461 $this->content.=$this->doc->section('',$content,0,1);
462
463
464 // Create new:
465 $content='
466
467 <form action="'.$this->doc->backPath.'tce_db.php" method="post">
468 Label: <input type="text" name="cmd['.$this->table.']['.$this->uid.'][version][label]" /><br/>
469 '.($this->table == 'pages' ? '<select name="cmd['.$this->table.']['.$this->uid.'][version][treeLevels]">
470 '.($GLOBALS['BE_USER']->workspaceVersioningTypeAccess(0) ? '<option value="0">Page: Page + content</option>' : '').'
471 '.($GLOBALS['BE_USER']->workspaceVersioningTypeAccess(1) ? '<option value="100">Branch: All subpages</option>' : '').'
472 '.($GLOBALS['BE_USER']->workspaceVersioningTypeAccess(-1) ? '<option value="-1">Element: Just record</option>' : '').'
473 </select>' : '').'
474 <br/><input type="hidden" name="cmd['.$this->table.']['.$this->uid.'][version][action]" value="new" />
475 <input type="hidden" name="prErr" value="1" />
476 <input type="hidden" name="redirect" value="'.htmlspecialchars($this->REQUEST_URI).'" />
477 <input type="submit" name="_" value="Create new version" />
478
479 </form>
480
481 ';
482
483 $this->content.=$this->doc->spacer(15);
484 $this->content.=$this->doc->section('Create new version',$content,0,1);
485
486 }
487
488 /**
489 * Recursively look for children for page version with $pid
490 *
491 * @param integer UID of page record for which to look up sub-elements following that version
492 * @param integer Counter, do not set (limits to 100 levels)
493 * @return string Table with content if any
494 */
495 function pageSubContent($pid,$c=0) {
496 global $TCA;
497
498 $tableNames = t3lib_div::removeArrayEntryByValue(array_keys($TCA),'pages');
499 $tableNames[] = 'pages';
500
501 foreach($tableNames as $tN) {
502 // Basically list ALL tables - not only those being copied might be found!
503 #if ($TCA[$tN]['ctrl']['versioning_followPages'] || $tN=='pages') {
504 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $tN, 'pid='.intval($pid).t3lib_BEfunc::deleteClause($tN), '', ($TCA[$tN]['ctrl']['sortby'] ? $TCA[$tN]['ctrl']['sortby'] : ''));
505
506 if ($GLOBALS['TYPO3_DB']->sql_num_rows($mres)) {
507 $content.='
508 <tr>
509 <td colspan="4" class="'.($TCA[$tN]['ctrl']['versioning_followPages'] ? 'bgColor6' : ($tN=='pages' ? 'bgColor5' : 'bgColor-10')).'"'.(!$TCA[$tN]['ctrl']['versioning_followPages'] && $tN!='pages' ? ' style="color: #666666; font-style:italic;"':'').'>'.$tN.'</td>
510 </tr>';
511 while ($subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) {
512 $ownVer = $this->lookForOwnVersions($tN,$subrow['uid']);
513 $content.='
514 <tr>
515 <td>'.$this->adminLinks($tN,$subrow).'</td>
516 <td>'.$subrow['uid'].'</td>
517 '.($ownVer>1 ? '<td style="font-weight: bold; background-color: yellow;"><a href="index.php?table='.rawurlencode($tN).'&uid='.$subrow['uid'].'">'.($ownVer-1).'</a></td>' : '<td></td>').'
518 <td width="98%">'.t3lib_BEfunc::getRecordTitle($tN,$subrow,TRUE).'</td>
519 </tr>';
520
521 if ($tN == 'pages' && $c<100) {
522 $sub = $this->pageSubContent($subrow['uid'],$c+1);
523
524 if ($sub) {
525 $content.='
526 <tr>
527 <td></td>
528 <td></td>
529 <td></td>
530 <td width="98%">'.$sub.'</td>
531 </tr>';
532 }
533 }
534 }
535 }
536 #}
537 }
538
539 return $content ? '<table border="1" cellpadding="1" cellspacing="0" width="100%">'.$content.'</table>' : '';
540 }
541
542 /**
543 * Look for number of versions of a record
544 *
545 * @param string Table name
546 * @param integer Record uid
547 * @return integer Number of versions for record, false if none.
548 */
549 function lookForOwnVersions($table,$uid) {
550 global $TCA;
551
552 $versions = t3lib_BEfunc::selectVersionsOfRecord($table, $uid, 'uid');
553 if (is_array($versions)) {
554 return count($versions);
555 }
556 return FALSE;
557 }
558
559 /**
560 * Administrative links for a table / record
561 *
562 * @param string Table name
563 * @param array Record for which administrative links are generated.
564 * @return string HTML link tags.
565 */
566 function adminLinks($table,$row) {
567 global $BE_USER;
568
569 // Edit link:
570 $adminLink = '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick('&edit['.$table.']['.$row['uid'].']=edit',$this->doc->backPath)).'">'.
571 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/edit2.gif','width="11" height="12"').' alt="" title="Edit"/>'.
572 '</a>';
573
574 // Delete link:
575 $adminLink.= '<a href="'.htmlspecialchars($this->doc->issueCommand('&cmd['.$table.']['.$row['uid'].'][delete]=1')).'">'.
576 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/garbage.gif','width="11" height="12"').' alt="" title="Delete"/>'.
577 '</a>';
578
579
580
581 if ($table == 'pages') {
582
583 // If another page module was specified, replace the default Page module with the new one
584 $newPageModule = trim($BE_USER->getTSConfigVal('options.overridePageModule'));
585 $pageModule = t3lib_BEfunc::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
586
587 // Perform some acccess checks:
588 $a_wl = $BE_USER->check('modules','web_list');
589 $a_wp = t3lib_extMgm::isLoaded('cms') && $BE_USER->check('modules',$pageModule);
590
591 $adminLink.='<a href="#" onclick="top.loadEditId('.$row['uid'].');top.goToModule(\''.$pageModule.'\'); return false;">'.
592 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,t3lib_extMgm::extRelPath('cms').'layout/layout.gif','width="14" height="12"').' title="" alt="" />'.
593 '</a>';
594 $adminLink.='<a href="#" onclick="top.loadEditId('.$row['uid'].');top.goToModule(\'web_list\'); return false;">'.
595 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'mod/web/list/list.gif','width="14" height="12"').' title="" alt="" />'.
596 '</a>';
597
598 // "View page" icon is added:
599 $adminLink.='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($row['uid'],$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($row['uid']))).'">'.
600 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/zoom.gif','width="12" height="12"').' title="" alt="" />'.
601 '</a>';
602 } else {
603 if ($row['pid']==-1) {
604 $getVars = '&ADMCMD_vPrev['.rawurlencode($table.':'.$row['t3ver_oid']).']='.$row['uid'];
605
606 // "View page" icon is added:
607 $adminLink.='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($row['_REAL_PID'],$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($row['_REAL_PID']),'','',$getVars)).'">'.
608 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/zoom.gif','width="12" height="12"').' title="" alt="" />'.
609 '</a>';
610 }
611 }
612
613 return $adminLink;
614 }
615
616
617
618
619
620
621
622
623
624
625
626 /******************************
627 *
628 * Workspace management
629 *
630 ******************************/
631
632 /**
633 * Management of workspace for page ID
634 * Called when $this->id is set.
635 *
636 * @return void
637 */
638 function workspaceMgm() {
639
640 $menu = '';
641 if ($GLOBALS['BE_USER']->workspace===0) {
642 $menu.= t3lib_BEfunc::getFuncMenu($this->id,'SET[filter]',$this->MOD_SETTINGS['filter'],$this->MOD_MENU['filter']);
643 $menu.= t3lib_BEfunc::getFuncMenu($this->id,'SET[display]',$this->MOD_SETTINGS['display'],$this->MOD_MENU['display']);
644 }
645 if (!$this->details && $GLOBALS['BE_USER']->workspace && !$this->diffOnly) {
646 $menu.= t3lib_BEfunc::getFuncCheck($this->id,'SET[diff]',$this->MOD_SETTINGS['diff'],'','','id="checkDiff"').' <label for="checkDiff">Show difference view</label>';
647 }
648
649 if ($menu) {
650 $this->content.=$this->doc->section('',$menu,0,1);
651 }
652
653 // Perform workspace publishing action if buttons are pressed:
654 $errors = $this->publishAction();
655
656 // Generate workspace overview:
657 $WSoverview = $this->displayWorkspaceOverview();
658
659 // Buttons for publish / swap:
660 $actionLinks = '<br/>';
661 if ($GLOBALS['BE_USER']->workspace!==0) {
662 if ($this->publishAccess) {
663 $actionLinks.= '<input type="submit" name="_publish" value="Publish page" onclick="return confirm(\'Are you sure you want to publish all content '.($GLOBALS['BE_USER']->workspaceRec['publish_access']&1 ? 'in &quot;Publish&quot; stage ':'').'from this page?\');"/>';
664 if ($GLOBALS['BE_USER']->workspaceSwapAccess()) {
665 $actionLinks.= '<input type="submit" name="_swap" value="Swap page" onclick="return confirm(\'Are you sure you want to publish (swap) all content '.($GLOBALS['BE_USER']->workspaceRec['publish_access']&1 ? 'in &quot;Publish&quot; stage ':'').'from this page?\');" />';
666 }
667 } else {
668 $actionLinks.= $this->doc->icons(1).'You are not permitted to publish from this workspace';
669 }
670 }
671 $actionLinks.= '<input type="submit" name="_" value="Refresh" />';
672 $actionLinks.= '<input type="submit" name="_previewLink" value="Preview Link" />';
673 $actionLinks.= $this->displayWorkspaceOverview_allStageCmd();
674
675 if ($actionLinks || count($errors)) {
676 $this->content.= $this->doc->section('',$actionLinks.(count($errors) ? '<h3>Errors:</h3><br/>'.implode('<br/>',$errors).'<hr/>' : ''),0,1);
677 }
678
679 if (t3lib_div::_POST('_previewLink')) {
680 $params = 'id='.$this->id.'&ADMCMD_previewWS='.$GLOBALS['BE_USER']->workspace;
681 $previewUrl = t3lib_div::getIndpEnv('TYPO3_SITE_URL').'index.php?ADMCMD_prev='.t3lib_BEfunc::compilePreviewKeyword($params, $GLOBALS['BE_USER']->user['uid']);
682
683 $this->content.= $this->doc->section('Preview Url:','You can preview this page from the workspace using this link for the next 48 hours (does not require backend login):<br/><br/><a target="_blank" href="'.htmlspecialchars($previewUrl).'">'.$previewUrl.'</a>',0,1);
684 }
685
686 // Output overview content:
687 $this->content.= $this->doc->spacer(15);
688 $this->content.= $this->doc->section($this->details ? 'Details for version' : 'Workspace management', $WSoverview,0,1);
689
690 }
691
692 /**
693 * Rendering the overview of versions in the current workspace
694 *
695 * @return string HTML (table)
696 * @see typo3/mod/user/ws/index.php for sister function!
697 */
698 function displayWorkspaceOverview() {
699
700 // Initialize variables:
701 $this->showWorkspaceCol = $GLOBALS['BE_USER']->workspace===0 && $this->MOD_SETTINGS['display']<=-98;
702
703 // Get usernames and groupnames
704 $be_group_Array = t3lib_BEfunc::getListGroupNames('title,uid');
705 $groupArray = array_keys($be_group_Array);
706 $this->be_user_Array = t3lib_BEfunc::getUserNames();
707 if (!$GLOBALS['BE_USER']->isAdmin()) $this->be_user_Array = t3lib_BEfunc::blindUserNames($this->be_user_Array,$groupArray,1);
708
709 // Initialize Workspace ID and filter-value:
710 if ($GLOBALS['BE_USER']->workspace===0) {
711 $wsid = $this->details ? -99 : $this->MOD_SETTINGS['display']; // Set wsid to the value from the menu (displaying content of other workspaces)
712 $filter = $this->details ? 0 : $this->MOD_SETTINGS['filter'];
713 } else {
714 $wsid = $GLOBALS['BE_USER']->workspace;
715 $filter = 0;
716 }
717
718 // Initialize workspace object and request all pending versions:
719 $wslibObj = t3lib_div::makeInstance('wslib');
720
721 // Selecting ALL versions belonging to the workspace:
722 $versions = $wslibObj->selectVersionsInWorkspace($wsid, $filter, -99, $this->uid); // $this->uid is the page id of LIVE record.
723
724 // Traverse versions and build page-display array:
725 $pArray = array();
726 foreach($versions as $table => $records) {
727 foreach($records as $rec) {
728 $pageIdField = $table==='pages' ? 't3ver_oid' : 'realpid';
729 $this->displayWorkspaceOverview_setInPageArray(
730 $pArray,
731 $table,
732 $rec
733 );
734 }
735 }
736
737 // Make header of overview:
738 $tableRows = array();
739 if (count($pArray)) {
740 $tableRows[] = '
741 <tr class="bgColor5 tableheader">
742 '.($this->diffOnly?'':'<td nowrap="nowrap" colspan="2">Live Version:</td>').'
743 <td nowrap="nowrap" colspan="2">Workspace Versions:</td>
744 <td nowrap="nowrap"'.($this->diffOnly?' colspan="2"':' colspan="4"').'>Controls:</td>
745 </tr>';
746
747 // Add lines from overview:
748 $tableRows = array_merge($tableRows, $this->displayWorkspaceOverview_list($pArray));
749
750 $table = '<table border="0" cellpadding="0" cellspacing="1" class="lrPadding workspace-overview">'.implode('',$tableRows).'</table>';
751 } else $table = '';
752
753 $linkBack = t3lib_div::_GP('returnUrl') ? '<a href="'.htmlspecialchars(t3lib_div::_GP('returnUrl')).'" class="typo3-goBack"><img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/goback.gif','width="14" height="14"').' alt="" />Click here to go back</a><br/><br/>' : '';
754 $resetDiffOnly = $this->diffOnly ? '<a href="index.php?id='.intval($this->id).'" class="typo3-goBack">Show all information</a><br/><br/>' : '';
755
756 $versionSelector = $GLOBALS['BE_USER']->workspace ? $this->doc->getVersionSelector($this->id) : '';
757
758 return $versionSelector.$linkBack.$resetDiffOnly.$table.$this->markupNewOriginals();
759 }
760
761 /**
762 * Rendering the content for the publish / review overview:
763 * (Made for internal recursive calling)
764 *
765 * @param array Storage of the elements to display (see displayWorkspaceOverview() / displayWorkspaceOverview_setInPageArray())
766 * @return array Table rows, see displayWorkspaceOverview()
767 */
768 function displayWorkspaceOverview_list($pArray) {
769 global $TCA;
770
771 // If there ARE elements on this level, print them:
772 $warnAboutVersions_nonPages = FALSE;
773 $warnAboutVersions_page = FALSE;
774 if (is_array($pArray)) {
775 foreach($pArray as $table => $oidArray) {
776 foreach($oidArray as $oid => $recs) {
777
778 // Get CURRENT online record and icon based on "t3ver_oid":
779 $rec_on = t3lib_BEfunc::getRecord($table,$oid);
780 $icon = t3lib_iconWorks::getIconImage($table, $rec_on, $this->doc->backPath,' align="top" title="'.t3lib_BEfunc::getRecordIconAltText($rec_on,$table).'"');
781 if ($GLOBALS['BE_USER']->workspace===0) { // Only edit online records if in ONLINE workspace:
782 $icon = $this->doc->wrapClickMenuOnIcon($icon, $table, $rec_on['uid'], 1, '', '+edit,view,info,delete');
783 }
784
785 // Online version display:
786 // Create the main cells which will span over the number of versions there is.
787 $verLinkUrl = $TCA[$table]['ctrl']['versioningWS'];
788 $origElement = $icon.
789 ($verLinkUrl ? '<a href="'.htmlspecialchars('index.php?table='.$table.'&uid='.$rec_on['uid']).'">' : '').
790 t3lib_BEfunc::getRecordTitle($table,$rec_on,TRUE).
791 ($verLinkUrl ? '</a>' : '');
792 $mainCell_rowSpan = count($recs)>1 ? ' rowspan="'.count($recs).'"' : '';
793 $mainCell = '
794 <td align="center"'.$mainCell_rowSpan.'>'.$this->formatVerId($rec_on['t3ver_id']).'</td>
795 <td nowrap="nowrap"'.$mainCell_rowSpan.'>'.
796 $origElement.
797 '###SUB_ELEMENTS###'. // For substitution with sub-elements, if any.
798 '</td>';
799
800 // Offline versions display:
801 // Traverse the versions of the element
802 foreach($recs as $rec) {
803
804 // Get the offline version record and icon:
805 $rec_off = t3lib_BEfunc::getRecord($table,$rec['uid']);
806
807 // Prepare swap-mode values:
808 if ($table==='pages' && $rec_off['t3ver_swapmode']!=-1) {
809 if ($rec_off['t3ver_swapmode']>0) {
810 $vType = 'branch';
811 } else {
812 $vType = 'page';
813 }
814 } else {
815 $vType = 'element';
816 }
817
818 // Get icon
819 $icon = t3lib_iconWorks::getIconImage($table, $rec_off, $this->doc->backPath, ' align="top" title="'.t3lib_BEfunc::getRecordIconAltText($rec_off,$table).'"');
820 $tempUid = ($table != 'pages' || $vType==='branch' || $GLOBALS['BE_USER']->workspace===0 ? $rec_off['uid'] : $rec_on['uid']);
821 $icon = $this->doc->wrapClickMenuOnIcon($icon, $table, $tempUid, 1, '', '+edit,' . ($table == 'pages' ? 'view,info,' : '') . 'delete');
822
823 // Prepare diff-code:
824 if ($this->MOD_SETTINGS['diff'] || $this->diffOnly) {
825 $diffCode = '';
826 list($diffHTML,$diffPct) = $this->createDiffView($table, $rec_off, $rec_on);
827 if ($rec_on['t3ver_state']==1) { // New record:
828 $diffCode.= $this->doc->icons(1).'New element<br/>'; // TODO Localize?
829 $diffCode.= $diffHTML;
830 } elseif ($rec_off['t3ver_state']==2) {
831 $diffCode.= $this->doc->icons(2).'Deleted element<br/>';
832 } elseif ($rec_on['t3ver_state']==3) {
833 $diffCode.= $this->doc->icons(1).'Move-to placeholder (destination)<br/>';
834 } elseif ($rec_off['t3ver_state']==4) {
835 $diffCode.= $this->doc->icons(1).'Move-to pointer (source)<br/>';
836 } else {
837 $diffCode.= ($diffPct<0 ? 'N/A' : ($diffPct ? $diffPct.'% change:' : ''));
838 $diffCode.= $diffHTML;
839 }
840 } else $diffCode = '';
841
842 switch($vType) {
843 case 'element':
844 $swapLabel = ' [Element]';
845 $swapClass = 'ver-element';
846 $warnAboutVersions_nonPages = $warnAboutVersions_page; // Setting this if sub elements are found with a page+content (must be rendered prior to this of course!)
847 break;
848 case 'page':
849 $swapLabel = ' [Page]';
850 $swapClass = 'ver-page';
851 $warnAboutVersions_page = !$this->showWorkspaceCol; // This value is true only if multiple workspaces are shown and we need the opposite here.
852 break;
853 case 'branch':
854 $swapLabel = ' [Branch]';
855 $swapClass = 'ver-branch';
856 break;
857 }
858
859 // Modify main cell based on first version shown:
860 $subElements = array();
861 if ($table==='pages' && $rec_off['t3ver_swapmode']!=-1 && $mainCell) { // For "Page" and "Branch" swap modes where $mainCell is still carrying content (only first version)
862 $subElements['on'] = $this->subElements($rec_on['uid'], $rec_off['t3ver_swapmode']);
863 $subElements['off'] = $this->subElements($rec_off['uid'],$rec_off['t3ver_swapmode'],$rec_on['uid']);
864 }
865 $mainCell = str_replace('###SUB_ELEMENTS###', $subElements['on'], $mainCell);
866
867 // Create version element:
868 $versionsInOtherWS = $this->versionsInOtherWS($table, $rec_on['uid']);
869 $versionsInOtherWSWarning = $versionsInOtherWS && $GLOBALS['BE_USER']->workspace!==0 ? '<br/>'.$this->doc->icons(2).'Other version(s) in workspace '.$versionsInOtherWS : '';
870 $multipleWarning = (!$mainCell && $GLOBALS['BE_USER']->workspace!==0? '<br/>'.$this->doc->icons(3).'<b>Multiple versions in same workspace!</b>' : '');
871 $verWarning = $warnAboutVersions || ($warnAboutVersions_nonPages && $GLOBALS['TCA'][$table]['ctrl']['versioning_followPages'])? '<br/>'.$this->doc->icons(3).'<b>Version inside version!</b>' : '';
872 $verElement = $icon.
873 (!$this->details ? '<a href="'.htmlspecialchars($this->doc->backPath.t3lib_extMgm::extRelPath('version').'cm1/index.php?id='.($table==='pages'?$rec_on['uid']:$rec_on['pid']).'&details='.rawurlencode($table.':'.$rec_off['uid']).'&returnUrl='.rawurlencode($this->REQUEST_URI)).'">' : '').
874 t3lib_BEfunc::getRecordTitle($table,$rec_off,TRUE).
875 (!$this->details ? '</a>' : '').
876 $versionsInOtherWSWarning.
877 $multipleWarning.
878 $verWarning;
879
880 $ctrlTable = '
881 <td nowrap="nowrap">'.$this->showStageChangeLog($table,$rec_off['uid'],$this->displayWorkspaceOverview_stageCmd($table,$rec_off)).'</td>
882 <td nowrap="nowrap" class="'.$swapClass.'">'.
883 $this->displayWorkspaceOverview_commandLinks($table,$rec_on,$rec_off,$vType).
884 htmlspecialchars($swapLabel).
885 '&nbsp;&nbsp;</td>
886 '.(!$this->diffOnly?'<td nowrap="nowrap"><b>Lifecycle:</b> '.htmlspecialchars($this->formatCount($rec_off['t3ver_count'])).'</td>'. // Lifecycle
887 ($this->showWorkspaceCol ? '
888 <td nowrap="nowrap">&nbsp;&nbsp;<b>Workspace:</b> '.htmlspecialchars($this->formatWorkspace($rec_off['t3ver_wsid'])).'</td>' : ''):'');
889
890 if ($diffCode) {
891 $verElement = $verElement.'
892 <br/><b>Difference to live element:</b>
893 <table border="0" cellpadding="0" cellspacing="0" class="ver-verElement">
894 <tr>
895 <td class="c-diffCell">'.$diffCode.'</td>
896 </tr>
897 </table>';
898 }
899
900
901 // Create version cell:
902 $verCell = '
903 <td align="center">'.$this->formatVerId($rec_off['t3ver_id']).'</td>
904 <td nowrap="nowrap">'.
905 $verElement.
906 $subElements['off'].
907 '</td>
908 ';
909
910 // Compile table row:
911 $tableRows[] = '
912 <tr class="bgColor4">
913 '.
914 ($this->diffOnly?'':$mainCell).
915 $verCell.
916 $ctrlTable.
917 '
918 </tr>';
919
920 // Reset the main cell:
921 $mainCell = '';
922
923 }
924 }
925 }
926 }
927
928 return $tableRows;
929 }
930
931 /**
932 * Building up of the $pArray
933 * (Internal)
934 *
935 * @param array Array that is built up with the page tree structure
936 * @param string Table name
937 * @param array Table row
938 * @return void $pArray is passed by reference and modified internally
939 */
940 function displayWorkspaceOverview_setInPageArray(&$pArray,$table,$row) {
941 if (!$this->details || $this->details==$table.':'.$row['uid']) {
942 $pArray[$table][$row['t3ver_oid']][] = $row;
943 }
944 }
945
946 /**
947 * Links to stage change of a version
948 *
949 * @param string Table name
950 * @param array Offline record (version)
951 * @return string HTML content, mainly link tags and images.
952 */
953 function displayWorkspaceOverview_allStageCmd() {
954
955 $table = t3lib_div::_GP('table');
956 if ($table && $table!='pages') {
957 $uid = t3lib_div::_GP('uid');
958 if ($rec_off = t3lib_BEfunc::getRecordWSOL($table,$uid)) {
959 $uid = $rec_off['_ORIG_uid'];
960 }
961 } else $table = '';
962
963 if ($table) {
964 if ($uid && $this->recIndex[$table][$uid]) {
965 $sId = $this->recIndex[$table][$uid];
966 switch($sId) {
967 case 1:
968 $label = 'Comment for Reviewer:';
969 break;
970 case 10:
971 $label = 'Comment for Publisher:';
972 break;
973 }
974 } else $sId = 0;
975 } else {
976 if (count($this->stageIndex[1])) { // Review:
977 $sId = 1;
978 $color = '#666666';
979 $label = 'Sending %s item(s) to review. Comment for Reviewer:';
980 $titleAttrib = 'Send all to Review';
981 } elseif(count($this->stageIndex[10])) { // Publish:
982 $sId = 10;
983 $color = '#6666cc';
984 $label = 'Approving %s item(s) to publishing. Comment for Publisher:';
985 $titleAttrib = 'Approve all for Publishing';
986 } else {
987 $sId = 0;
988 }
989 }
990
991 if ($sId>0) {
992 $issueCmd = '';
993 $itemCount = 0;
994
995 if ($table && $uid && $this->recIndex[$table][$uid]) {
996 $issueCmd.='&cmd['.$table.']['.$uid.'][version][action]=setStage';
997 $issueCmd.='&cmd['.$table.']['.$uid.'][version][stageId]='.$this->recIndex[$table][$uid];
998 } else {
999 foreach($this->stageIndex[$sId] as $table => $uidArray) {
1000 $issueCmd.='&cmd['.$table.']['.implode(',',$uidArray).'][version][action]=setStage';
1001 $issueCmd.='&cmd['.$table.']['.implode(',',$uidArray).'][version][stageId]='.$sId;
1002 $itemCount+=count($uidArray);
1003 }
1004 }
1005
1006 $onClick = 'var commentTxt=window.prompt("'.sprintf($label,$itemCount).'","");
1007 if (commentTxt!=null) {window.location.href="'.$this->doc->issueCommand($issueCmd,$this->REQUEST_URI).'&generalComment="+escape(commentTxt);}';
1008
1009 if (t3lib_div::_GP('sendToReview')) {
1010 $onClick.= ' else {window.location.href = "'.$this->REQUEST_URI.'"}';
1011 $actionLinks.=
1012 $this->doc->wrapScriptTags($onClick);
1013 } else {
1014 $onClick.= ' return false;';
1015 $actionLinks.=
1016 '<input type="submit" name="_" value="'.htmlspecialchars($titleAttrib).'" onclick="'.htmlspecialchars($onClick).'" />';
1017 }
1018 } elseif (t3lib_div::_GP('sendToReview')) {
1019 $onClick = 'window.location.href = "'.$this->REQUEST_URI.'";';
1020 $actionLinks.=
1021 $this->doc->wrapScriptTags($onClick);
1022 } else $actionLinks = '';
1023
1024 return $actionLinks;
1025 }
1026
1027
1028
1029
1030
1031
1032 /**************************************
1033 *
1034 * Helper functions (REDUNDANT FROM user/ws/index.php - someone could refactor this...)
1035 *
1036 *************************************/
1037
1038 /**
1039 * Formatting the version number for HTML output
1040 *
1041 * @param integer Version number
1042 * @return string Version number for output
1043 */
1044 function formatVerId($verId) {
1045 return '1.'.$verId;
1046 }
1047
1048 /**
1049 * Formatting workspace ID into a visual label
1050 *
1051 * @param integer Workspace ID
1052 * @return string Workspace title
1053 */
1054 function formatWorkspace($wsid) {
1055
1056 // Render, if not cached:
1057 if (!isset($this->formatWorkspace_cache[$wsid])) {
1058 switch($wsid) {
1059 case -1:
1060 $this->formatWorkspace_cache[$wsid] = '[Offline]';
1061 break;
1062 case 0:
1063 $this->formatWorkspace_cache[$wsid] = ''; // Does not output anything for ONLINE because it might confuse people to think that the elemnet IS online which is not the case - only that it exists as an offline version in the online workspace...
1064 break;
1065 default:
1066 list($titleRec) = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('title','sys_workspace','uid='.intval($wsid).t3lib_BEfunc::deleteClause('sys_workspace'));
1067 $this->formatWorkspace_cache[$wsid] = '['.$wsid.'] '.$titleRec['title'];
1068 break;
1069 }
1070 }
1071
1072 return $this->formatWorkspace_cache[$wsid];
1073 }
1074
1075 /**
1076 * Format publishing count for version (lifecycle state)
1077 *
1078 * @param integer t3ver_count value (number of times it has been online)
1079 * @return string String translation of count.
1080 */
1081 function formatCount($count) {
1082
1083 // Render, if not cached:
1084 if (!isset($this->formatCount_cache[$count])) {
1085 switch($count) {
1086 case 0:
1087 $this->formatCount_cache[$count] = 'Draft';
1088 break;
1089 case 1:
1090 $this->formatCount_cache[$count] = 'Archive';
1091 break;
1092 default:
1093 $this->formatCount_cache[$count] = 'Published '.$count.' times';
1094 break;
1095 }
1096 }
1097
1098 return $this->formatCount_cache[$count];
1099 }
1100
1101 /**
1102 * Looking for versions of a record in other workspaces than the current
1103 *
1104 * @param string Table name
1105 * @param integer Record uid
1106 * @return string List of other workspace IDs
1107 */
1108 function versionsInOtherWS($table,$uid) {
1109
1110 // Check for duplicates:
1111 // Select all versions of record NOT in this workspace:
1112 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1113 't3ver_wsid',
1114 $table,
1115 'pid=-1
1116 AND t3ver_oid='.intval($uid).'
1117 AND t3ver_wsid!='.intval($GLOBALS['BE_USER']->workspace).'
1118 AND (t3ver_wsid=-1 OR t3ver_wsid>0)'.
1119 t3lib_BEfunc::deleteClause($table),
1120 '',
1121 't3ver_wsid',
1122 '',
1123 't3ver_wsid'
1124 );
1125 if (count($rows)) {
1126 return implode(',',array_keys($rows));
1127 }
1128 }
1129
1130 /**
1131 * Looks up stage changes for version and displays a formatted view on mouseover.
1132 *
1133 * @param string Table name
1134 * @param integer Record ID
1135 * @param string HTML string to wrap the mouseover around (should be stage change links)
1136 * @return string HTML code.
1137 */
1138 function showStageChangeLog($table,$id,$stageCommands) {
1139 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1140 'log_data,tstamp,userid',
1141 'sys_log',
1142 'action=6 and details_nr=30
1143 AND tablename='.$GLOBALS['TYPO3_DB']->fullQuoteStr($table,'sys_log').'
1144 AND recuid='.intval($id)
1145 );
1146
1147 $entry = array();
1148 foreach($rows as $dat) {
1149 $data = unserialize($dat['log_data']);
1150 $username = $this->be_user_Array[$dat['userid']] ? $this->be_user_Array[$dat['userid']]['username'] : '['.$dat['userid'].']';
1151
1152 switch($data['stage']) {
1153 case 1:
1154 $text = 'sent element to "Review"';
1155 break;
1156 case 10:
1157 $text = 'approved for "Publish"';
1158 break;
1159 case -1:
1160 $text = 'rejected element!';
1161 break;
1162 case 0:
1163 $text = 'reset to "Editing"';
1164 break;
1165 default:
1166 $text = '[undefined]';
1167 break;
1168 }
1169 $text = t3lib_BEfunc::dateTime($dat['tstamp']).': "'.$username.'" '.$text;
1170 $text.= ($data['comment']?'<br/>User Comment: <em>'.htmlspecialchars($data['comment']).'</em>':'');
1171
1172 $entry[] = $text;
1173 }
1174
1175 return count($entry) ? '<span onmouseover="document.getElementById(\'log_'.$table.$id.'\').style.visibility = \'visible\';" onmouseout="document.getElementById(\'log_'.$table.$id.'\').style.visibility = \'hidden\';">'.$stageCommands.' ('.count($entry).')</span>'.
1176 '<div class="logLayer" style="visibility: hidden; position: absolute;" id="log_'.$table.$id.'">'.implode('<hr/>',array_reverse($entry)).'</div>' : $stageCommands;
1177 }
1178
1179 /**
1180 * Creates display of sub elements of a page when the swap mode is either "Page" or "Branch" (0 / ALL)
1181 *
1182 * @param integer Page uid (for either online or offline version, but it MUST have swapmode/treeLevel set to >0 (not -1 indicating element versioning)
1183 * @param integer The treeLevel value, >0 indicates "branch" while 0 means page+content. (-1 would have meant element versioning, but that should never happen for a call to this function!)
1184 * @param integer For offline versions; This is t3ver_oid, the original ID of the online page.
1185 * @return string HTML content.
1186 */
1187 function subElements($uid,$treeLevel,$origId=0) {
1188 global $TCA;
1189
1190 if (!$this->details && ($GLOBALS['BE_USER']->workspace===0 || !$this->MOD_SETTINGS['expandSubElements'])) { // In online workspace we have a reduced view because otherwise it will bloat the listing:
1191 return '<br/>
1192 <img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/ol/joinbottom.gif','width="18" height="16"').' align="top" alt="" title="" />'.
1193 ($origId ?
1194 '<a href="'.htmlspecialchars($this->doc->backPath.t3lib_extMgm::extRelPath('version').'cm1/index.php?id='.$uid.'&details='.rawurlencode('pages:'.$uid).'&returnUrl='.rawurlencode($this->REQUEST_URI)).'">'.
1195 '<span class="typo3-dimmed"><em>[Sub elements, click for details]</em><span></a>' :
1196 '<span class="typo3-dimmed"><em>[Sub elements]</em><span>');
1197 } else { // For an offline workspace, show sub elements:
1198
1199 $tCell = array();
1200
1201 // Find records that follow pages when swapping versions:
1202 $recList = array();
1203 foreach($TCA as $tN => $tCfg) {
1204 if ($tN!='pages' && ($treeLevel>0 || $TCA[$tN]['ctrl']['versioning_followPages'])) {
1205 $this->subElements_getNonPageRecords($tN, $uid, $recList);
1206 }
1207 }
1208
1209 // Render records collected above:
1210 $elCount = count($recList)-1;
1211 foreach($recList as $c => $comb) {
1212 list($tN,$rec) = $comb;
1213
1214 $this->subElements_renderItem(
1215 $tCell,
1216 $tN,
1217 $uid,
1218 $rec,
1219 $origId,
1220 $c==$elCount && $treeLevel==0 ? 1 : 0, // If true, will show bottom-join icon.
1221 ''
1222 );
1223 }
1224
1225 // For branch, dive into the subtree:
1226 if ($treeLevel>0) {
1227
1228 // Drawing tree:
1229 $tree = t3lib_div::makeInstance('t3lib_pageTree');
1230 $tree->init('AND '.$GLOBALS['BE_USER']->getPagePermsClause(1));
1231 $tree->makeHTML = 2; // 2=Also rendering depth-data into the result array
1232 $tree->getTree($uid, 99, '');
1233
1234 // Traverse page tree:
1235 foreach($tree->tree as $data) {
1236
1237 // Render page in table cell:
1238 $this->subElements_renderItem(
1239 $tCell,
1240 'pages',
1241 $uid,
1242 t3lib_BEfunc::getRecord('pages',$data['row']['uid']), // Needs all fields, at least more than what is given in $data['row']...
1243 $origId,
1244 2, // 2=the join icon and icon for the record is not rendered for pages (where all is in $data['HTML']
1245 $data['HTML']
1246 );
1247
1248 // Find all records from page and collect in $recList:
1249 $recList = array();
1250 foreach($TCA as $tN => $tCfg) {
1251 if ($tN!=='pages') {
1252 $this->subElements_getNonPageRecords($tN, $data['row']['uid'], $recList);
1253 }
1254 }
1255
1256 // Render records collected above:
1257 $elCount = count($recList)-1;
1258 foreach($recList as $c => $comb) {
1259 list($tN,$rec) = $comb;
1260
1261 $this->subElements_renderItem(
1262 $tCell,
1263 $tN,
1264 $uid,
1265 $rec,
1266 $origId,
1267 $c==$elCount?1:0, // If true, will show bottom-join icon.
1268 $data['HTML_depthData']
1269 );
1270 }
1271 }
1272 }
1273
1274 return '
1275 <!-- Sub-element tree for versions -->
1276 <table border="0" cellpadding="0" cellspacing="1" class="ver-subtree">
1277 '.implode('',$tCell).'
1278 </table>';
1279 }
1280 }
1281
1282 /**
1283 * Select records from a table and add them to recList
1284 *
1285 * @param string Table name (from TCA)
1286 * @param integer PID to select records from
1287 * @param array Array where records are accumulated, passed by reference
1288 * @return void
1289 */
1290 function subElements_getNonPageRecords($tN, $uid, &$recList) {
1291 global $TCA;
1292
1293 $records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1294 '*',
1295 $tN,
1296 'pid='.intval($uid).
1297 ($TCA[$tN]['ctrl']['versioningWS'] ? ' AND t3ver_state=0' : '').
1298 t3lib_BEfunc::deleteClause($tN),
1299 '',
1300 $TCA[$tN]['ctrl']['sortby'] ? $TCA[$tN]['ctrl']['sortby'] : $GLOBALS['TYPO3_DB']->stripOrderBy($TCA[$tN]['ctrl']['default_sortby'])
1301 );
1302
1303 foreach($records as $rec) {
1304 $recList[] = array($tN,$rec);
1305 }
1306 }
1307
1308 /**
1309 * Render a single item in a subelement list into a table row:
1310 *
1311 * @param array Table rows, passed by reference
1312 * @param string Table name
1313 * @param integer Page uid for which the subelements are selected/shown
1314 * @param array Row of element in list
1315 * @param integer The uid of the online version of $uid. If zero it means we are drawing a row for the online version itself while a value means we are drawing display for an offline version.
1316 * @param integer Mode of icon display: 0=not the last, 1= is the last in list (make joinbottom icon then), 2=do not shown icons are all (for pages from the page tree already rendered)
1317 * @param string Prefix HTML data (icons for tree rendering)
1318 * @return void (Content accumulated in $tCell!)
1319 */
1320 function subElements_renderItem(&$tCell,$tN,$uid,$rec,$origId,$iconMode,$HTMLdata) {
1321 global $TCA;
1322
1323 // Initialize:
1324 $origUidFields = $TCA[$tN]['ctrl']['origUid'];
1325 $diffCode = '';
1326
1327 if ($origUidFields) { // If there is a field for this table with original uids we will use that to connect records:
1328 if (!$origId) { // In case we are displaying the online originals:
1329 $this->targets['orig_'.$uid.'_'.$tN.'_'.$rec['uid']] = $rec; // Build up target array (important that
1330 $tdParams = ' id="orig_'.$uid.'_'.$tN.'_'.$rec['uid'].'" class="typo3-ver"'; // Setting ID of the table row
1331 } else { // Version branch:
1332 if ($this->targets['orig_'.$origId.'_'.$tN.'_'.$rec[$origUidFields]]) { // If there IS a corresponding original record...:
1333
1334 // Prepare Table row parameters:
1335 $tdParams = ' onmouseover="hlSubelements(\''.$origId.'_'.$tN.'_'.$rec[$origUidFields].'\', \''.$uid.'_'.$tN.'_'.$rec[$origUidFields].'\', 1, '.($this->MOD_SETTINGS['diff']==2?1:0).');"'.
1336 ' onmouseout="hlSubelements(\''.$origId.'_'.$tN.'_'.$rec[$origUidFields].'\', \''.$uid.'_'.$tN.'_'.$rec[$origUidFields].'\', 0, '.($this->MOD_SETTINGS['diff']==2?1:0).');"'.
1337 ' id="ver_'.$uid.'_'.$tN.'_'.$rec[$origUidFields].'" class="typo3-ver"';
1338
1339 // Create diff view:
1340 if ($this->MOD_SETTINGS['diff']) {
1341 list($diffHTML,$diffPct) = $this->createDiffView($tN, $rec, $this->targets['orig_'.$origId.'_'.$tN.'_'.$rec[$origUidFields]]);
1342
1343 if ($this->MOD_SETTINGS['diff']==2) {
1344 $diffCode =
1345 ($diffPct ? '<span class="nobr">'.$diffPct.'% change</span>' : '-').
1346 '<div style="visibility: hidden; position: absolute;" id="diff_'.$uid.'_'.$tN.'_'.$rec[$origUidFields].'" class="diffLayer">'.
1347 $diffHTML.
1348 '</div>';
1349 } else {
1350 $diffCode =
1351 ($diffPct<0 ? 'N/A' : ($diffPct ? $diffPct.'% change:' : '')).
1352 $diffHTML;
1353 }
1354 }
1355
1356 // Unsetting the target fields allows us to mark all originals without a version in the subtree (see ->markupNewOriginals())
1357 unset($this->targets['orig_'.$origId.'_'.$tN.'_'.$rec[$origUidFields]]);
1358 } else { // No original record, so must be new:
1359 $tdParams = ' class="typo3-ver-new"';
1360 }
1361 }
1362 } else { // If no original uid column is supported for this table we are forced NOT to display any diff or highlighting.
1363 $tdParams = ' class="typo3-ver-noComp"';
1364 }
1365
1366 // Compile the cell:
1367 $tCell[] = '
1368 <tr'.$tdParams.'>
1369 <td class="iconTitle">'.
1370 $HTMLdata.
1371 ($iconMode < 2 ?
1372 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/ol/join'.($iconMode ? 'bottom' : '').'.gif','width="18" height="16"').' alt="" />'.
1373 t3lib_iconWorks::getIconImage($tN, $rec, $this->doc->backPath,'') : '').
1374 t3lib_BEfunc::getRecordTitle($tN, $rec, TRUE).
1375 '</td>
1376 <td class="cmdCell">'.
1377 $this->displayWorkspaceOverview_commandLinksSub($tN,$rec,$origId).
1378 '</td>'.($origId ? '<td class="diffCell">'.
1379 $diffCode.
1380 '</td>':'').'
1381 </tr>';
1382 }
1383
1384 /**
1385 * JavaScript code to mark up new records that are online (in sub element lists)
1386 *
1387 * @return string HTML javascript section
1388 */
1389 function markupNewOriginals() {
1390
1391 if (count($this->targets)) {
1392 $scriptCode = '';
1393 foreach($this->targets as $key => $rec) {
1394 $scriptCode.='
1395 document.getElementById(\''.$key.'\').attributes.getNamedItem("class").nodeValue = \'typo3-ver-new\';
1396 ';
1397 }
1398
1399 return $this->doc->wrapScriptTags($scriptCode);
1400 }
1401 }
1402
1403 /**
1404 * Create visual difference view of two records. Using t3lib_diff library
1405 *
1406 * @param string Table name
1407 * @param array New version record (green)
1408 * @param array Old version record (red)
1409 * @return array Array with two keys (0/1) with HTML content / percentage integer (if -1, then it means N/A) indicating amount of change
1410 */
1411 function createDiffView($table, $diff_1_record, $diff_2_record) {
1412 global $TCA;
1413
1414 // Initialize:
1415 $pctChange = 'N/A';
1416
1417 // Check that records are arrays:
1418 if (is_array($diff_1_record) && is_array($diff_2_record)) {
1419
1420 // Load full table description and initialize diff-object:
1421 t3lib_div::loadTCA($table);
1422 $t3lib_diff_Obj = t3lib_div::makeInstance('t3lib_diff');
1423
1424 // Add header row:
1425 $tRows = array();
1426 $tRows[] = '
1427 <tr class="bgColor5 tableheader">
1428 <td>Fieldname:</td>
1429 <td width="98%" nowrap="nowrap">Colored diff-view:</td>
1430 </tr>
1431 ';
1432
1433 // Initialize variables to pick up string lengths in:
1434 $allStrLen = 0;
1435 $diffStrLen = 0;
1436
1437 // Traversing the first record and process all fields which are editable:
1438 foreach($diff_1_record as $fN => $fV) {
1439 if ($TCA[$table]['columns'][$fN] && $TCA[$table]['columns'][$fN]['config']['type']!='passthrough' && !t3lib_div::inList('t3ver_label',$fN)) {
1440
1441 // Check if it is files:
1442 $isFiles = FALSE;
1443 if (strcmp(trim($diff_1_record[$fN]),trim($diff_2_record[$fN])) &&
1444 $TCA[$table]['columns'][$fN]['config']['type']=='group' &&
1445 $TCA[$table]['columns'][$fN]['config']['internal_type']=='file') {
1446
1447 // Initialize:
1448 $uploadFolder = $TCA[$table]['columns'][$fN]['config']['uploadfolder'];
1449 $files1 = array_flip(t3lib_div::trimExplode(',', $diff_1_record[$fN],1));
1450 $files2 = array_flip(t3lib_div::trimExplode(',', $diff_2_record[$fN],1));
1451
1452 // Traverse filenames and read their md5 sum:
1453 foreach($files1 as $filename => $tmp) {
1454 $files1[$filename] = @is_file(PATH_site.$uploadFolder.'/'.$filename) ? md5(t3lib_div::getUrl(PATH_site.$uploadFolder.'/'.$filename)) : $filename;
1455 }
1456 foreach($files2 as $filename => $tmp) {
1457 $files2[$filename] = @is_file(PATH_site.$uploadFolder.'/'.$filename) ? md5(t3lib_div::getUrl(PATH_site.$uploadFolder.'/'.$filename)) : $filename;
1458 }
1459
1460 // Implode MD5 sums and set flag:
1461 $diff_1_record[$fN] = implode(' ',$files1);
1462 $diff_2_record[$fN] = implode(' ',$files2);
1463 $isFiles = TRUE;
1464 }
1465
1466 // If there is a change of value:
1467 if (strcmp(trim($diff_1_record[$fN]),trim($diff_2_record[$fN]))) {
1468
1469
1470 // Get the best visual presentation of the value and present that:
1471 $val1 = t3lib_BEfunc::getProcessedValue($table,$fN,$diff_2_record[$fN],0,1);
1472 $val2 = t3lib_BEfunc::getProcessedValue($table,$fN,$diff_1_record[$fN],0,1);
1473
1474 // Make diff result and record string lenghts:
1475 $diffres = $t3lib_diff_Obj->makeDiffDisplay($val1,$val2,$isFiles?'div':'span');
1476 $diffStrLen+= $t3lib_diff_Obj->differenceLgd;
1477 $allStrLen+= strlen($val1.$val2);
1478
1479 // If the compared values were files, substituted MD5 hashes:
1480 if ($isFiles) {
1481 $allFiles = array_merge($files1,$files2);
1482 foreach($allFiles as $filename => $token) {
1483 if (strlen($token)==32 && strstr($diffres,$token)) {
1484 $filename =
1485 t3lib_BEfunc::thumbCode(array($fN=>$filename),$table,$fN,$this->doc->backPath).
1486 $filename;
1487 $diffres = str_replace($token,$filename,$diffres);
1488 }
1489 }
1490 }
1491
1492 // Add table row with result:
1493 $tRows[] = '
1494 <tr class="bgColor4">
1495 <td>'.htmlspecialchars($GLOBALS['LANG']->sL(t3lib_BEfunc::getItemLabel($table,$fN))).'</td>
1496 <td width="98%">'.$diffres.'</td>
1497 </tr>
1498 ';
1499 } else {
1500 // Add string lengths even if value matched - in this was the change percentage is not high if only a single field is changed:
1501 $allStrLen+=strlen($diff_1_record[$fN].$diff_2_record[$fN]);
1502 }
1503 }
1504 }
1505
1506 // Calculate final change percentage:
1507 $pctChange = $allStrLen ? ceil($diffStrLen*100/$allStrLen) : -1;
1508
1509 // Create visual representation of result:
1510 if (count($tRows)>1) {
1511 $content.= '<table border="0" cellpadding="1" cellspacing="1" class="diffTable">'.implode('',$tRows).'</table>';
1512 } else {
1513 $content.= '<span class="nobr">'.$this->doc->icons(1).'Complete match on editable fields.</span>';
1514 }
1515 } else $content.= $this->doc->icons(3).'ERROR: Records could strangely not be found!';
1516
1517 // Return value:
1518 return array($content,$pctChange);
1519 }
1520
1521 /**
1522 * Links to stage change of a version
1523 *
1524 * @param string Table name
1525 * @param array Offline record (version)
1526 * @return string HTML content, mainly link tags and images.
1527 */
1528 function displayWorkspaceOverview_stageCmd($table,&$rec_off) {
1529 #debug($rec_off['t3ver_stage']);
1530 switch((int)$rec_off['t3ver_stage']) {
1531 case 0:
1532 $sId = 1;
1533 $sLabel = 'Editing';
1534 $color = '#666666';
1535 $label = 'Comment for Reviewer:';
1536 $titleAttrib = 'Send to Review';
1537 break;
1538 case 1:
1539 $sId = 10;
1540 $sLabel = 'Review';
1541 $color = '#6666cc';
1542 $label = 'Comment for Publisher:';
1543 $titleAttrib = 'Approve for Publishing';
1544 break;
1545 case 10:
1546 $sLabel = 'Publish';
1547 $color = '#66cc66';
1548 break;
1549 case -1:
1550 $sLabel = $this->doc->icons(2).'Rejected';
1551 $sId = 0;
1552 $color = '#ff0000';
1553 $label = 'Comment:';
1554 $titleAttrib = 'Reset stage';
1555 break;
1556 default:
1557 $sLabel = 'Undefined';
1558 $sId = 0;
1559 $color = '';
1560 break;
1561 }
1562 #debug($sId);
1563
1564 $raiseOk = !$GLOBALS['BE_USER']->workspaceCannotEditOfflineVersion($table,$rec_off);
1565
1566 if ($raiseOk && $rec_off['t3ver_stage']!=-1) {
1567 $onClick = 'var commentTxt=window.prompt("Please explain why you reject:","");
1568 if (commentTxt!=null) {window.location.href="'.$this->doc->issueCommand(
1569 '&cmd['.$table.']['.$rec_off['uid'].'][version][action]=setStage'.
1570 '&cmd['.$table.']['.$rec_off['uid'].'][version][stageId]=-1'
1571 ).'&cmd['.$table.']['.$rec_off['uid'].'][version][comment]="+escape(commentTxt);}'.
1572 ' return false;';
1573 // Reject:
1574 $actionLinks.=
1575 '<a href="#" onclick="'.htmlspecialchars($onClick).'">'.
1576 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/down.gif','width="14" height="14"').' alt="" align="top" title="Reject" />'.
1577 '</a>';
1578 } else {
1579 // Reject:
1580 $actionLinks.=
1581 '<img src="'.$this->doc->backPath.'gfx/clear.gif" width="14" height="14" alt="" align="top" title="" />';
1582 }
1583
1584 $actionLinks.= '<span style="background-color: '.$color.'; color: white;">'.$sLabel.'</span>';
1585
1586 // Raise
1587 if ($raiseOk) {
1588 $onClick = 'var commentTxt=window.prompt("'.$label.'","");
1589 if (commentTxt!=null) {window.location.href="'.$this->doc->issueCommand(
1590 '&cmd['.$table.']['.$rec_off['uid'].'][version][action]=setStage'.
1591 '&cmd['.$table.']['.$rec_off['uid'].'][version][stageId]='.$sId
1592 ).'&cmd['.$table.']['.$rec_off['uid'].'][version][comment]="+escape(commentTxt);}'.
1593 ' return false;';
1594 if ($rec_off['t3ver_stage']!=10) {
1595 $actionLinks.=
1596 '<a href="#" onclick="'.htmlspecialchars($onClick).'">'.
1597 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/up.gif','width="14" height="14"').' alt="" align="top" title="'.htmlspecialchars($titleAttrib).'" />'.
1598 '</a>';
1599
1600 $this->stageIndex[$sId][$table][] = $rec_off['uid'];
1601 $this->recIndex[$table][$rec_off['uid']] = $sId;
1602 }
1603 }
1604 return $actionLinks;
1605 }
1606
1607 /**
1608 * Links to publishing etc of a version
1609 *
1610 * @param string Table name
1611 * @param array Online record
1612 * @param array Offline record (version)
1613 * @param string Swap type, "branch", "page" or "element"
1614 * @return string HTML content, mainly link tags and images.
1615 */
1616 function displayWorkspaceOverview_commandLinks($table,&$rec_on,&$rec_off,$vType) {
1617 if ($this->publishAccess && (!($GLOBALS['BE_USER']->workspaceRec['publish_access']&1) || (int)$rec_off['t3ver_stage']===10)) {
1618 $actionLinks =
1619 '<a href="'.htmlspecialchars($this->doc->issueCommand(
1620 '&cmd['.$table.']['.$rec_on['uid'].'][version][action]=swap'.
1621 '&cmd['.$table.']['.$rec_on['uid'].'][version][swapWith]='.$rec_off['uid']
1622 )).'">'.
1623 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert1.gif','width="14" height="14"').' alt="" align="top" title="Publish" />'.
1624 '</a>';
1625 if ($GLOBALS['BE_USER']->workspaceSwapAccess()) {
1626 $actionLinks.=
1627 '<a href="'.htmlspecialchars($this->doc->issueCommand(
1628 '&cmd['.$table.']['.$rec_on['uid'].'][version][action]=swap'.
1629 '&cmd['.$table.']['.$rec_on['uid'].'][version][swapWith]='.$rec_off['uid'].
1630 '&cmd['.$table.']['.$rec_on['uid'].'][version][swapIntoWS]=1'
1631 )).'">'.
1632 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/swap.png','width="14" height="14"').' alt="" align="top" title="Swap" />'.
1633 '</a>';
1634 }
1635 }
1636
1637 if (!$GLOBALS['BE_USER']->workspaceCannotEditOfflineVersion($table,$rec_off)) {
1638 // Release
1639 $actionLinks.=
1640 '<a href="'.htmlspecialchars($this->doc->issueCommand('&cmd['.$table.']['.$rec_off['uid'].'][version][action]=clearWSID')).'" onclick="return confirm(\'Remove from workspace?\');">'.
1641 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/group_clear.gif','width="14" height="14"').' alt="" align="top" title="Remove from workspace" />'.
1642 '</a>';
1643
1644 // Edit
1645 if ($table==='pages' && $vType!=='element') {
1646 $tempUid = ($vType==='branch' || $GLOBALS['BE_USER']->workspace===0 ? $rec_off['uid'] : $rec_on['uid']);
1647 $actionLinks.=
1648 '<a href="#" onclick="top.loadEditId('.$tempUid.');top.goToModule(\''.$this->pageModule.'\'); return false;">'.
1649 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,t3lib_extMgm::extRelPath('cms').'layout/layout.gif','width="14" height="12"').' title="Edit page" alt="" />'.
1650 '</a>';
1651 } else {
1652 $params = '&edit['.$table.']['.$rec_off['uid'].']=edit';
1653 $actionLinks.=
1654 '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->doc->backPath)).'">'.
1655 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/edit2.gif','width="12" height="12"').' title="Edit element" alt="" />'.
1656 '</a>';
1657 }
1658 }
1659
1660 // History/Log
1661 $actionLinks.=
1662 '<a href="'.htmlspecialchars($this->doc->backPath.'show_rechis.php?element='.rawurlencode($table.':'.$rec_off['uid']).'&returnUrl='.rawurlencode($this->REQUEST_URI)).'">'.
1663 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/history2.gif','width="13" height="12"').' title="Show Log" alt="" />'.
1664 '</a>';
1665
1666 // View
1667 if ($table==='pages') {
1668 $tempUid = ($vType==='branch' || $GLOBALS['BE_USER']->workspace===0 ? $rec_off['uid'] : $rec_on['uid']);
1669 $actionLinks.=
1670 '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($tempUid,$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($tempUid))).'">'.
1671 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/zoom.gif','width="12" height="12"').' title="" alt="" />'.
1672 '</a>';
1673 }
1674
1675 return $actionLinks;
1676 }
1677
1678 /**
1679 * Links to publishing etc of a version
1680 *
1681 * @param string Table name
1682 * @param array Record
1683 * @param integer The uid of the online version of $uid. If zero it means we are drawing a row for the online version itself while a value means we are drawing display for an offline version.
1684 * @return string HTML content, mainly link tags and images.
1685 */
1686 function displayWorkspaceOverview_commandLinksSub($table,$rec,$origId) {
1687 $uid = $rec['uid'];
1688 if ($origId || $GLOBALS['BE_USER']->workspace===0) {
1689 if (!$GLOBALS['BE_USER']->workspaceCannotEditRecord($table,$rec)) {
1690 // Edit
1691 if ($table==='pages') {
1692 $actionLinks.=
1693 '<a href="#" onclick="top.loadEditId('.$uid.');top.goToModule(\''.$this->pageModule.'\'); return false;">'.
1694 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,t3lib_extMgm::extRelPath('cms').'layout/layout.gif','width="14" height="12"').' title="Edit page" alt="" />'.
1695 '</a>';
1696 } else {
1697 $params = '&edit['.$table.']['.$uid.']=edit';
1698 $actionLinks.=
1699 '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->doc->backPath)).'">'.
1700 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/edit2.gif','width="12" height="12"').' title="Edit element" alt="" />'.
1701 '</a>';
1702 }
1703 }
1704
1705 // History/Log
1706 $actionLinks.=
1707 '<a href="'.htmlspecialchars($this->doc->backPath.'show_rechis.php?element='.rawurlencode($table.':'.$uid).'&returnUrl='.rawurlencode($this->REQUEST_URI)).'">'.
1708 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/history2.gif','width="13" height="12"').' title="Show Log" alt="" />'.
1709 '</a>';
1710 }
1711
1712 // View
1713 if ($table==='pages') {
1714 $actionLinks.=
1715 '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($uid,$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($uid))).'">'.
1716 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/zoom.gif','width="12" height="12"').' title="" alt="" />'.
1717 '</a>';
1718 }
1719
1720 return $actionLinks;
1721 }
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731 /**********************************
1732 *
1733 * Processing
1734 *
1735 **********************************/
1736
1737 /**
1738 * Will publish workspace if buttons are pressed
1739 *
1740 * @return void
1741 */
1742 function publishAction() {
1743
1744 // If "Publish" or "Swap" buttons are pressed:
1745 if (t3lib_div::_POST('_publish') || t3lib_div::_POST('_swap')) {
1746
1747 if ($this->table==='pages') { // Making sure ->uid is a page ID!
1748 // Initialize workspace object and request all pending versions:
1749 $wslibObj = t3lib_div::makeInstance('wslib');
1750 $cmd = $wslibObj->getCmdArrayForPublishWS($GLOBALS['BE_USER']->workspace, t3lib_div::_POST('_swap'),$this->uid);
1751
1752 // Execute the commands:
1753 $tce = t3lib_div::makeInstance('t3lib_TCEmain');
1754 $tce->stripslashes_values = 0;
1755 $tce->start(array(), $cmd);
1756 $tce->process_cmdmap();
1757
1758 t3lib_BEfunc::getSetUpdateSignal('updatePageTree');
1759
1760 return $tce->errorLog;
1761 }
1762 }
1763 }
1764 }
1765
1766
1767
1768 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/version/cm1/index.php']) {
1769 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/version/cm1/index.php']);
1770 }
1771
1772
1773
1774
1775 // Make instance:
1776 $SOBE = t3lib_div::makeInstance('tx_version_cm1');
1777 $SOBE->init();
1778
1779
1780 $SOBE->main();
1781 $SOBE->printContent();
1782
1783 ?>