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