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