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