index_old.php

Administrator Admin, 2009-08-07 17:47

Download (66.6 KB)

 
1
<?php
2
/***************************************************************
3
*  Copyright notice
4
*
5
*  (c) 2004-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
6
*  All rights reserved
7
*
8
*  This script is part of the TYPO3 project. The TYPO3 project is
9
*  free software; you can redistribute it and/or modify
10
*  it under the terms of the GNU General Public License as published by
11
*  the Free Software Foundation; either version 2 of the License, or
12
*  (at your option) any later version.
13
*
14
*  The GNU General Public License can be found at
15
*  http://www.gnu.org/copyleft/gpl.html.
16
*
17
*  This script is distributed in the hope that it will be useful,
18
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
19
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
*  GNU General Public License for more details.
21
*
22
*  This copyright notice MUST APPEAR in all copies of the script!
23
***************************************************************/
24
/**
25
 * Versioning module
26
 *
27
 * @author        Kasper Skaarhoj <kasperYYYY@typo3.com>
28
 */
29
/**
30
 * [CLASS/FUNCTION INDEX of SCRIPT]
31
 *
32
 *
33
 *
34
 *  102: class tx_version_cm1 extends t3lib_SCbase
35
 *
36
 *              SECTION: Standard module initialization
37
 *  138:     function menuConfig()
38
 *  175:     function main()
39
 *  236:     function jumpToUrl(URL)
40
 *  296:     function printContent()
41
 *
42
 *              SECTION: Versioning management
43
 *  322:     function versioningMgm()
44
 *  485:     function pageSubContent($pid,$c=0)
45
 *  539:     function lookForOwnVersions($table,$uid)
46
 *  556:     function adminLinks($table,$row)
47
 *
48
 *              SECTION: Workspace management
49
 *  628:     function workspaceMgm()
50
 *  688:     function displayWorkspaceOverview()
51
 *  758:     function displayWorkspaceOverview_list($pArray)
52
 *  923:     function displayWorkspaceOverview_setInPageArray(&$pArray,$table,$row)
53
 *  936:     function displayWorkspaceOverview_allStageCmd()
54
 *
55
 *              SECTION: Helper functions (REDUNDANT FROM user/ws/index.php - someone could refactor this...)
56
 *  986:     function formatVerId($verId)
57
 *  996:     function formatWorkspace($wsid)
58
 * 1023:     function formatCount($count)
59
 * 1050:     function versionsInOtherWS($table,$uid)
60
 * 1080:     function showStageChangeLog($table,$id,$stageCommands)
61
 * 1129:     function subElements($uid,$treeLevel,$origId=0)
62
 * 1232:     function subElements_getNonPageRecords($tN, $uid, &$recList)
63
 * 1262:     function subElements_renderItem(&$tCell,$tN,$uid,$rec,$origId,$iconMode,$HTMLdata)
64
 * 1331:     function markupNewOriginals()
65
 * 1353:     function createDiffView($table, $diff_1_record, $diff_2_record)
66
 * 1470:     function displayWorkspaceOverview_stageCmd($table,&$rec_off)
67
 * 1557:     function displayWorkspaceOverview_commandLinks($table,&$rec_on,&$rec_off,$vType)
68
 * 1627:     function displayWorkspaceOverview_commandLinksSub($table,$rec,$origId)
69
 *
70
 *              SECTION: Processing
71
 * 1683:     function publishAction()
72
 *
73
 * TOTAL FUNCTIONS: 27
74
 * (This index is automatically created/updated by the extension "extdeveval")
75
 *
76
 */
77

    
78

    
79
        // DEFAULT initialization of a module [BEGIN]
80
unset($MCONF);
81
require ('conf.php');
82
require ($BACK_PATH.'init.php');
83
require ($BACK_PATH.'template.php');
84
$LANG->includeLLFile('EXT:version/locallang.xml');
85
require_once (PATH_t3lib.'class.t3lib_scbase.php');
86
        // DEFAULT initialization of a module [END]
87

    
88
require_once(PATH_t3lib.'class.t3lib_diff.php');
89
require_once(PATH_typo3.'mod/user/ws/class.wslib.php');
90
require_once(PATH_t3lib.'class.t3lib_pagetree.php');
91
require_once(PATH_t3lib.'class.t3lib_tcemain.php');
92

    
93

    
94

    
95
/**
96
 * Versioning module, including workspace management
97
 *
98
 * @author        Kasper Skaarhoj <kasperYYYY@typo3.com>
99
 * @package TYPO3
100
 * @subpackage core
101
 */
102
class tx_version_cm1 extends t3lib_SCbase {
103

    
104
                // Default variables for backend modules
105
        var $MCONF = array();                                // Module configuration
106
        var $MOD_MENU = array();                        // Module menu items
107
        var $MOD_SETTINGS = array();                // Module session settings
108
        var $doc;                                                        // Document Template Object
109
        var $content;                                                // Accumulated content
110

    
111

    
112
                // Internal:
113
        var $showWorkspaceCol = 0;
114
        var $formatWorkspace_cache = array();
115
        var $formatCount_cache = array();
116
        var $targets = array();                // Accumulation of online targets.
117
        var $pageModule = '';                        // Name of page module
118
        var $publishAccess = FALSE;
119
        var $be_user_Array = array();
120
        var $stageIndex = array();
121
        var $recIndex = array();
122

    
123

    
124

    
125

    
126

    
127

    
128
        /*********************************
129
         *
130
         * Standard module initialization
131
         *
132
         *********************************/
133

    
134
        /**
135
         * Initialize menu configuration
136
         *
137
         * @return        void
138
         */
139
        function menuConfig()        {
140

    
141
                        // Menu items:
142
                $this->MOD_MENU = array(
143
                        'filter' => array(
144
                                1 => 'Drafts',
145
                                2 => 'Archive',
146
                                0 => 'All',
147
                        ),
148
                        'display' => array(
149
                                0 => '[Live workspace]',
150
                                -98 => 'Draft Workspaces',
151
                                -99 => 'All',
152
                                -1 => '[Default Draft]'
153
                        ),
154
                        'diff' => ''
155
                );
156

    
157
                        // Add workspaces:
158
                if ($GLOBALS['BE_USER']->workspace===0)        {        // Spend time on this only in online workspace because it might take time:
159
                        $workspaces = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,title,adminusers,members,reviewers','sys_workspace','pid=0'.t3lib_BEfunc::deleteClause('sys_workspace'),'','title');
160
                        foreach($workspaces as $rec)        {
161
                                if ($GLOBALS['BE_USER']->checkWorkspace($rec))        {
162
                                        $this->MOD_MENU['display'][$rec['uid']] = '['.$rec['uid'].'] '.$rec['title'];
163
                                }
164
                        }
165
                }
166

    
167
                        // CLEANSE SETTINGS
168
                $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name'], 'ses');
169
        }
170

    
171
        /**
172
         * Main function of the module. Write the content to $this->content
173
         *
174
         * @return        void
175
         */
176
        function main()        {
177
                global $BE_USER,$LANG,$BACK_PATH,$TCA_DESCR,$TCA,$CLIENT,$TYPO3_CONF_VARS;
178

    
179
                        // Setting module configuration:
180
                $this->MCONF = $GLOBALS['MCONF'];
181
                
182
                $this->REQUEST_URI = str_replace('&sendToReview=1','',t3lib_div::getIndpEnv('REQUEST_URI'));
183

    
184
                        // Draw the header.
185
                $this->doc = t3lib_div::makeInstance('mediumDoc');
186
                $this->doc->backPath = $BACK_PATH;
187
                $this->doc->form='<form action="" method="post">';
188

    
189
                // Add styles
190
                $this->doc->inDocStylesArray[$GLOBALS['MCONF']['name']] = '
191
.version-diff-1 { background-color: green; }
192
.version-diff-2 { background-color: red; }
193
';
194

    
195
                        // Setting up the context sensitive menu:
196
                $CMparts = $this->doc->getContextMenuCode();
197
                $this->doc->JScode.= $CMparts[0];
198
                $this->doc->bodyTagAdditions = $CMparts[1];
199
                $this->doc->postCode.= $CMparts[2];
200

    
201
                        // Getting input data:
202
                $this->id = intval(t3lib_div::_GP('id'));                // Page id. If set, indicates activation from Web>Versioning module
203
                if (!$this->id)        {
204
                        $this->uid = intval(t3lib_div::_GP('uid'));                // Record uid. Goes with table name to indicate specific record
205
                        $this->table = t3lib_div::_GP('table');                        // Record table. Goes with uid to indicate specific record
206
                } else {
207
                        $this->uid = $this->id;
208
                        $this->table = 'pages';
209
                }
210
                $this->details = t3lib_div::_GP('details');                // Page id. If set, indicates activation from Web>Versioning module
211
                $this->diffOnly = t3lib_div::_GP('diffOnly');                // Flag. If set, shows only the offline version and with diff-view
212

    
213
                        // Force this setting:
214
                $this->MOD_SETTINGS['expandSubElements'] = TRUE;
215
                $this->MOD_SETTINGS['diff'] = $this->details || $this->MOD_SETTINGS['diff']?1:0;
216

    
217
                        // Reading the record:
218
                $record = t3lib_BEfunc::getRecord($this->table,$this->uid);
219
                if ($record['pid']==-1)        {
220
                        $record = t3lib_BEfunc::getRecord($this->table,$record['t3ver_oid']);
221
                }
222
                $pidValue = $this->table==='pages' ? $this->uid : $record['pid'];
223

    
224
                        // Checking access etc.
225
                if (is_array($record) && $TCA[$this->table]['ctrl']['versioningWS'])        {
226
                        $this->uid = $record['uid'];         // Might have changed if new live record was found!
227

    
228
                                // Access check!
229
                                // The page will show only if there is a valid page and if this page may be viewed by the user
230
                        $this->pageinfo = t3lib_BEfunc::readPageAccess($pidValue,$this->perms_clause);
231
                        $access = is_array($this->pageinfo) ? 1 : 0;
232

    
233
                        if (($pidValue && $access) || ($BE_USER->user['admin'] && !$pidValue))        {
234

    
235
                                        // JavaScript
236
                                $this->doc->JScode.= '
237
                                        <script language="javascript" type="text/javascript">
238
                                                script_ended = 0;
239
                                                function jumpToUrl(URL)        {
240
                                                        window.location.href = URL;
241
                                                }
242

243
                                                function hlSubelements(origId, verId, over, diffLayer)        {        //
244
                                                        if (over)        {
245
                                                                document.getElementById(\'orig_\'+origId).attributes.getNamedItem("class").nodeValue = \'typo3-ver-hl\';
246
                                                                document.getElementById(\'ver_\'+verId).attributes.getNamedItem("class").nodeValue = \'typo3-ver-hl\';
247
                                                                if (diffLayer)        {
248
                                                                        document.getElementById(\'diff_\'+verId).style.visibility = \'visible\';
249
                                                                }
250
                                                        } else {
251
                                                                document.getElementById(\'orig_\'+origId).attributes.getNamedItem("class").nodeValue = \'typo3-ver\';
252
                                                                document.getElementById(\'ver_\'+verId).attributes.getNamedItem("class").nodeValue = \'typo3-ver\';
253
                                                                if (diffLayer)        {
254
                                                                        document.getElementById(\'diff_\'+verId).style.visibility = \'hidden\';
255
                                                                }
256
                                                        }
257
                                                }
258
                                        </script>
259
                                ';
260

    
261
                                        // If another page module was specified, replace the default Page module with the new one
262
                                $newPageModule = trim($BE_USER->getTSConfigVal('options.overridePageModule'));
263
                                $this->pageModule = t3lib_BEfunc::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
264

    
265
                                        // Setting publish access permission for workspace:
266
                                $this->publishAccess = $BE_USER->workspacePublishAccess($BE_USER->workspace);
267

    
268

    
269
                                $headerSection = $this->doc->getHeader('pages',$this->pageinfo,$this->pageinfo['_thePath']).'<br/>'.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.path').': '.t3lib_div::fixed_lgd_pre($this->pageinfo['_thePath'],50);
270

    
271
                                $this->content.=$this->doc->startPage($LANG->getLL('title'));
272
                                $this->content.=$this->doc->header($LANG->getLL('title'));
273
                                $this->content.=$this->doc->spacer(5);
274
                                $this->content.=$this->doc->section('',$headerSection);
275
                                $this->content.=$this->doc->divider(5);
276

    
277
                                        // Render content:
278
                                if ($this->id)        {
279
                                        $this->workspaceMgm();
280
                                } else {
281
                                        $this->versioningMgm();
282
                                }
283

    
284
                                        // ShortCut
285
                                if ($BE_USER->mayMakeShortcut())        {
286
                                        $this->content.=$this->doc->spacer(20).$this->doc->section('',$this->doc->makeShortcutIcon('id',implode(',',array_keys($this->MOD_MENU)),$this->MCONF['name']));
287
                                }
288
                        }
289

    
290
                        $this->content.=$this->doc->spacer(10);
291
                } else {
292
                                // If no access or id value, create empty document:
293
                        $this->content.=$this->doc->startPage($LANG->getLL('title'));
294
                        $this->content.=$this->doc->section($LANG->getLL('clickAPage_header'),$LANG->getLL('clickAPage_content'),0,1);
295
                }
296
        }
297

    
298
        /**
299
         * Outputs accumulated module content to browser.
300
         *
301
         * @return        void
302
         */
303
        function printContent()        {
304

    
305
                $this->content.=$this->doc->endPage();
306
                echo $this->content;
307
        }
308

    
309

    
310

    
311

    
312

    
313

    
314

    
315

    
316

    
317

    
318
        /******************************
319
         *
320
         * Versioning management
321
         *
322
         ******************************/
323

    
324
        /**
325
         * Management of versions for record
326
         *
327
         * @return        void
328
         */
329
        function versioningMgm()        {
330
                global $TCA;
331

    
332
                        // Diffing:
333
                $diff_1 = t3lib_div::_POST('diff_1');
334
                $diff_2 = t3lib_div::_POST('diff_2');
335
                if (t3lib_div::_POST('do_diff'))        {
336
                        $content='';
337
                        $content.='<h3>DIFFING:</h3>';
338
                        if ($diff_1 && $diff_2)        {
339
                                $diff_1_record = t3lib_BEfunc::getRecord($this->table, $diff_1);
340
                                $diff_2_record = t3lib_BEfunc::getRecord($this->table, $diff_2);
341

    
342
                                if (is_array($diff_1_record) && is_array($diff_2_record))        {
343
                                        t3lib_div::loadTCA($this->table);
344
                                        $t3lib_diff_Obj = t3lib_div::makeInstance('t3lib_diff');
345

    
346
                                        $tRows=array();
347
                                                                $tRows[] = '
348
                                                                        <tr class="bgColor5 tableheader">
349
                                                                                <td>Fieldname:</td>
350
                                                                                <td width="98%">Colored diff-view:</td>
351
                                                                        </tr>
352
                                                                ';
353
                                        foreach($diff_1_record as $fN => $fV)        {
354
                                                if ($TCA[$this->table]['columns'][$fN] && $TCA[$this->table]['columns'][$fN]['config']['type']!='passthrough' && !t3lib_div::inList('t3ver_label',$fN))        {
355
                                                        if (strcmp($diff_1_record[$fN],$diff_2_record[$fN]))        {
356

    
357
                                                                $diffres = $t3lib_diff_Obj->makeDiffDisplay(
358
                                                                        t3lib_BEfunc::getProcessedValue($this->table,$fN,$diff_2_record[$fN],0,1),
359
                                                                        t3lib_BEfunc::getProcessedValue($this->table,$fN,$diff_1_record[$fN],0,1)
360
                                                                );
361

    
362
                                                                $tRows[] = '
363
                                                                        <tr class="bgColor4">
364
                                                                                <td>'.$fN.'</td>
365
                                                                                <td width="98%">'.$diffres.'</td>
366
                                                                        </tr>
367
                                                                ';
368
                                                        }
369
                                                }
370
                                        }
371

    
372
                                        if (count($tRows)>1)        {
373
                                                $content.='<table border="0" cellpadding="1" cellspacing="1" width="100%">'.implode('',$tRows).'</table><br/><br/>';
374
                                        } else {
375
                                                $content.='Records matches completely on all editable fields!';
376
                                        }
377
                                } else $content.='ERROR: Records could strangely not be found!';
378
                        } else {
379
                                $content.='ERROR: You didn\'t select two sources for diffing!';
380
                        }
381
                }
382

    
383
                        // Element:
384
                $record = t3lib_BEfunc::getRecord($this->table,$this->uid);
385
                $recordIcon = t3lib_iconWorks::getIconImage($this->table,$record,$this->doc->backPath,'class="absmiddle"');
386
                $recTitle = t3lib_BEfunc::getRecordTitle($this->table,$record,TRUE);
387

    
388
                        // Display versions:
389
                $content.='
390
                        '.$recordIcon.$recTitle.'
391
                        <form name="theform" action="'.str_replace('&sendToReview=1','',$this->REQUEST_URI).'" method="post">
392
                        <table border="0" cellspacing="1" cellpadding="1">';
393
                        $content.='
394
                                <tr class="bgColor5 tableheader">
395
                                        <td>&nbsp;</td>
396
                                        <td>&nbsp;</td>
397
                                        <td>Title</td>
398
                                        <td>UID</td>
399
                                        <td title="t3ver_oid - Reference to live version UID">oid</td>
400
                                        <td title="t3ver_id - Version number, incremental integer">id</td>
401
                                        <td title="t3ver_wsid - Workspace ID. There can be only one version of an element per ID (except ID zero).">wsid</td>
402
                                        <td title="t3ver_state - Special states of a version: 1=Placeholder for &quot;New&quot;. 2=Marked deleted.">state</td>
403
                                        <td title="t3ver_stage - Publishing stage: Editing (0), review (1), publish (10), rejected (-1).">stage</td>
404
                                        <td title="t3ver_count - Life cycle counter. Incremented each time element is unpublished.">count</td>
405
                                        <td>pid</td>
406
                                        <td>t3ver_label</td>
407
                                        <td colspan="2"><input type="submit" name="do_diff" value="Diff" /></td>
408
                                </tr>';
409

    
410
                $versions = t3lib_BEfunc::selectVersionsOfRecord($this->table, $this->uid, '*', $GLOBALS['BE_USER']->workspace);
411
                foreach($versions as $row)        {
412
                        $adminLinks = $this->adminLinks($this->table,$row);
413

    
414
                        $content.='
415
                                <tr class="'.($row['uid']!=$this->uid ? 'bgColor4' : 'bgColor2 tableheader').'">
416
                                        <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').'">'.
417
                                                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert1.gif','width="14" height="14"').' alt="" title="SWAP with current" />'.
418
                                                '</a>' /* (
419
                                                        $this->table == 'pages' ?
420
                                                        '<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').'">'.
421
                                                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert2.gif','width="14" height="14"').' alt="" title="Publish page AND content!" />'.
422
                                                '</a>'.
423
                                                        '<a href="'.$this->doc->issueCommand('&cmd['.$this->table.']['.$this->uid.'][version][action]=swap&cmd['.$this->table.']['.$this->uid.'][version][swapWith]='.$row['uid'].'&cmd['.$this->table.']['.$this->uid.'][version][swapContent]=ALL').'">'.
424
                                                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert4.gif','width="14" height="14"').' alt="" title="Publish page AND content! - AND ALL SUBPAGES!" />'.
425
                                                '</a>' : '') */ : '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/blinkarrow_left.gif','width="5" height="9"').' alt="" title="CURRENT ONLINE VERSION!"/>').'</td>
426
                                        <td nowrap="nowrap">'.$adminLinks.'</td>
427
                                        <td nowrap="nowrap">'.t3lib_BEfunc::getRecordTitle($this->table,$row,TRUE).'</td>
428
                                        <td>'.$row['uid'].'</td>
429
                                        <td>'.$row['t3ver_oid'].'</td>
430
                                        <td>'.$row['t3ver_id'].'</td>
431
                                        <td>'.$row['t3ver_wsid'].'</td>
432
                                        <td>'.$row['t3ver_state'].'</td>
433
                                        <td>'.$row['t3ver_stage'].'</td>
434
                                        <td>'.$row['t3ver_count'].'</td>
435
                                        <td>'.$row['pid'].'</td>
436
                                        <td nowrap="nowrap"><a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick('&edit['.$this->table.']['.$row['uid'].']=edit&columnsOnly=t3ver_label',$this->doc->backPath)).'"><img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/edit2.gif','width="11" height="12"').' alt="" title="Edit"/></a>'.htmlspecialchars($row['t3ver_label']).'</td>
437
                                        <td class="version-diff-1"><input type="radio" name="diff_1" value="'.$row['uid'].'"'.($diff_1==$row['uid'] ? ' checked="checked"':'').'/></td>
438
                                        <td class="version-diff-2"><input type="radio" name="diff_2" value="'.$row['uid'].'"'.($diff_2==$row['uid'] ? ' checked="checked"':'').'/></td>
439
                                </tr>';
440

    
441
                                // 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;)
442
                        if ($this->table == 'pages' && $row['uid']!=$this->uid)        {
443
                                $sub = $this->pageSubContent($row['uid']);
444

    
445
                                if ($sub)        {
446
                                        $content.='
447
                                                <tr>
448
                                                        <td></td>
449
                                                        <td></td>
450
                                                        <td colspan="10">'.$sub.'</td>
451
                                                        <td colspan="2"></td>
452
                                                </tr>';
453
                                }
454
                        }
455
                }
456
                $content.='</table></form>';
457

    
458
                $this->content.=$this->doc->section('',$content,0,1);
459

    
460

    
461
                        // Create new:
462
                $content='
463

464
                        <form action="'.$this->doc->backPath.'tce_db.php" method="post">
465
                        Label: <input type="text" name="cmd['.$this->table.']['.$this->uid.'][version][label]" /><br/>
466
                        '.($this->table == 'pages' ? '<select name="cmd['.$this->table.']['.$this->uid.'][version][treeLevels]">
467
                                '.($GLOBALS['BE_USER']->workspaceVersioningTypeAccess(0) ? '<option value="0">Page: Page + content</option>' : '').'
468
                                '.($GLOBALS['BE_USER']->workspaceVersioningTypeAccess(1) ? '<option value="100">Branch: All subpages</option>' : '').'
469
                                '.($GLOBALS['BE_USER']->workspaceVersioningTypeAccess(-1) ? '<option value="-1">Element: Just record</option>' : '').'
470
                        </select>' : '').'
471
                        <br/><input type="hidden" name="cmd['.$this->table.']['.$this->uid.'][version][action]" value="new" />
472
                        <input type="hidden" name="prErr" value="1" />
473
                        <input type="hidden" name="redirect" value="'.htmlspecialchars($this->REQUEST_URI).'" />
474
                        <input type="submit" name="_" value="Create new version" />
475

476
                        </form>
477

478
                ';
479

    
480
                $this->content.=$this->doc->spacer(15);
481
                $this->content.=$this->doc->section('Create new version',$content,0,1);
482

    
483
        }
484

    
485
        /**
486
         * Recursively look for children for page version with $pid
487
         *
488
         * @param        integer                UID of page record for which to look up sub-elements following that version
489
         * @param        integer                Counter, do not set (limits to 100 levels)
490
         * @return        string                Table with content if any
491
         */
492
        function pageSubContent($pid,$c=0)        {
493
                global $TCA;
494

    
495
                $tableNames = t3lib_div::removeArrayEntryByValue(array_keys($TCA),'pages');
496
                $tableNames[] = 'pages';
497

    
498
                foreach($tableNames as $tN)        {
499
                                // Basically list ALL tables - not only those being copied might be found!
500
                        #if ($TCA[$tN]['ctrl']['versioning_followPages'] || $tN=='pages')        {
501
                                $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $tN, 'pid='.intval($pid).t3lib_BEfunc::deleteClause($tN), '', ($TCA[$tN]['ctrl']['sortby'] ? $TCA[$tN]['ctrl']['sortby'] : ''));
502

    
503
                                if ($GLOBALS['TYPO3_DB']->sql_num_rows($mres))        {
504
                                        $content.='
505
                                                <tr>
506
                                                        <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>
507
                                                </tr>';
508
                                        while ($subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres))        {
509
                                                $ownVer = $this->lookForOwnVersions($tN,$subrow['uid']);
510
                                                $content.='
511
                                                        <tr>
512
                                                                <td>'.$this->adminLinks($tN,$subrow).'</td>
513
                                                                <td>'.$subrow['uid'].'</td>
514
                                                                '.($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>').'
515
                                                                <td width="98%">'.t3lib_BEfunc::getRecordTitle($tN,$subrow,TRUE).'</td>
516
                                                        </tr>';
517

    
518
                                                if ($tN == 'pages' && $c<100)        {
519
                                                        $sub = $this->pageSubContent($subrow['uid'],$c+1);
520

    
521
                                                        if ($sub)        {
522
                                                                $content.='
523
                                                                        <tr>
524
                                                                                <td></td>
525
                                                                                <td></td>
526
                                                                                <td></td>
527
                                                                                <td width="98%">'.$sub.'</td>
528
                                                                        </tr>';
529
                                                        }
530
                                                }
531
                                        }
532
                                }
533
                        #}
534
                }
535

    
536
                return $content ? '<table border="1" cellpadding="1" cellspacing="0" width="100%">'.$content.'</table>' : '';
537
        }
538

    
539
        /**
540
         * Look for number of versions of a record
541
         *
542
         * @param        string                Table name
543
         * @param        integer                Record uid
544
         * @return        integer                Number of versions for record, false if none.
545
         */
546
        function lookForOwnVersions($table,$uid)        {
547
                global $TCA;
548

    
549
                $versions = t3lib_BEfunc::selectVersionsOfRecord($table, $uid, 'uid');
550
                if (is_array($versions))        {
551
                        return count($versions);
552
                }
553
                return FALSE;
554
        }
555

    
556
        /**
557
         * Administrative links for a table / record
558
         *
559
         * @param        string                Table name
560
         * @param        array                Record for which administrative links are generated.
561
         * @return        string                HTML link tags.
562
         */
563
        function adminLinks($table,$row)        {
564
                global $BE_USER;
565

    
566
                        // Edit link:
567
                $adminLink = '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick('&edit['.$table.']['.$row['uid'].']=edit',$this->doc->backPath)).'">'.
568
                                                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/edit2.gif','width="11" height="12"').' alt="" title="Edit"/>'.
569
                                                '</a>';
570

    
571
                        // Delete link:
572
                $adminLink.= '<a href="'.htmlspecialchars($this->doc->issueCommand('&cmd['.$table.']['.$row['uid'].'][delete]=1')).'">'.
573
                                                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/garbage.gif','width="11" height="12"').' alt="" title="Delete"/>'.
574
                                                '</a>';
575

    
576

    
577

    
578
                if ($table == 'pages')        {
579

    
580
                                // If another page module was specified, replace the default Page module with the new one
581
                        $newPageModule = trim($BE_USER->getTSConfigVal('options.overridePageModule'));
582
                        $pageModule = t3lib_BEfunc::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
583

    
584
                                // Perform some acccess checks:
585
                        $a_wl = $BE_USER->check('modules','web_list');
586
                        $a_wp = t3lib_extMgm::isLoaded('cms') && $BE_USER->check('modules',$pageModule);
587

    
588
                        $adminLink.='<a href="#" onclick="top.loadEditId('.$row['uid'].');top.goToModule(\''.$pageModule.'\'); return false;">'.
589
                                                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,t3lib_extMgm::extRelPath('cms').'layout/layout.gif','width="14" height="12"').' title="" alt="" />'.
590
                                                '</a>';
591
                        $adminLink.='<a href="#" onclick="top.loadEditId('.$row['uid'].');top.goToModule(\'web_list\'); return false;">'.
592
                                                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'mod/web/list/list.gif','width="14" height="12"').' title="" alt="" />'.
593
                                                '</a>';
594

    
595
                                // "View page" icon is added:
596
                        $adminLink.='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($row['uid'],$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($row['uid']))).'">'.
597
                                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/zoom.gif','width="12" height="12"').' title="" alt="" />'.
598
                                '</a>';
599
                } else {
600
                        if ($row['pid']==-1)        {
601
                                $getVars = '&ADMCMD_vPrev['.rawurlencode($table.':'.$row['t3ver_oid']).']='.$row['uid'];
602

    
603
                                        // "View page" icon is added:
604
                                $adminLink.='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($row['_REAL_PID'],$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($row['_REAL_PID']),'','',$getVars)).'">'.
605
                                        '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/zoom.gif','width="12" height="12"').' title="" alt="" />'.
606
                                        '</a>';
607
                        }
608
                }
609

    
610
                return $adminLink;
611
        }
612

    
613

    
614

    
615

    
616

    
617

    
618

    
619

    
620

    
621

    
622

    
623
        /******************************
624
         *
625
         * Workspace management
626
         *
627
         ******************************/
628

    
629
        /**
630
         * Management of workspace for page ID
631
         * Called when $this->id is set.
632
         *
633
         * @return        void
634
         */
635
        function workspaceMgm()        {
636

    
637
                $menu = '';
638
                if ($GLOBALS['BE_USER']->workspace===0)        {
639
                        $menu.= t3lib_BEfunc::getFuncMenu($this->id,'SET[filter]',$this->MOD_SETTINGS['filter'],$this->MOD_MENU['filter']);
640
                        $menu.= t3lib_BEfunc::getFuncMenu($this->id,'SET[display]',$this->MOD_SETTINGS['display'],$this->MOD_MENU['display']);
641
                }
642
                if (!$this->details && $GLOBALS['BE_USER']->workspace && !$this->diffOnly)        {
643
                        $menu.= t3lib_BEfunc::getFuncCheck($this->id,'SET[diff]',$this->MOD_SETTINGS['diff'],'','','id="checkDiff"').' <label for="checkDiff">Show difference view</label>';
644
                }
645

    
646
                if ($menu)        {
647
                        $this->content.=$this->doc->section('',$menu,0,1);
648
                }
649

    
650
                        // Perform workspace publishing action if buttons are pressed:
651
                $errors = $this->publishAction();
652

    
653
                        // Generate workspace overview:
654
                $WSoverview = $this->displayWorkspaceOverview();
655

    
656
                        // Buttons for publish / swap:
657
                $actionLinks = '<br/>';
658
                if ($GLOBALS['BE_USER']->workspace!==0)        {
659
                        if ($this->publishAccess)        {
660
                                $actionLinks.= '<input type="submit" name="_publish" value="Publish page" onclick="return confirm(\'Are you sure you want to publish all content '.($GLOBALS['BE_USER']->workspaceRec['publish_access']&1 ? 'in &quot;Publish&quot; stage ':'').'from this page?\');"/>';
661
                                if ($GLOBALS['BE_USER']->workspaceSwapAccess())        {
662
                                        $actionLinks.= '<input type="submit" name="_swap" value="Swap page" onclick="return confirm(\'Are you sure you want to publish (swap) all content '.($GLOBALS['BE_USER']->workspaceRec['publish_access']&1 ? 'in &quot;Publish&quot; stage ':'').'from this page?\');" />';
663
                                }
664
                        } else {
665
                                $actionLinks.= $this->doc->icons(1).'You are not permitted to publish from this workspace';
666
                        }
667
                }
668
                $actionLinks.= '<input type="submit" name="_" value="Refresh" />';
669
                $actionLinks.= '<input type="submit" name="_previewLink" value="Preview Link" />';
670
                $actionLinks.= $this->displayWorkspaceOverview_allStageCmd();
671

    
672
                if ($actionLinks || count($errors))        {
673
                        $this->content.= $this->doc->section('',$actionLinks.(count($errors) ? '<h3>Errors:</h3><br/>'.implode('<br/>',$errors).'<hr/>' : ''),0,1);
674
                }
675

    
676
                if (t3lib_div::_POST('_previewLink'))        {
677
                        $params = 'id='.$this->id.'&ADMCMD_view=1&ADMCMD_editIcons=1&ADMCMD_previewWS='.$GLOBALS['BE_USER']->workspace;
678
                        $previewUrl = t3lib_div::getIndpEnv('TYPO3_SITE_URL').'index.php?ADMCMD_prev='.t3lib_BEfunc::compilePreviewKeyword($params, $GLOBALS['BE_USER']->user['uid']);
679

    
680
                        $this->content.= $this->doc->section('Preview Url:','You can preview this page from the workspace using this link for the next 48 hours (does not require backend login):<br/><br/><a target="_blank" href="'.htmlspecialchars($previewUrl).'">'.$previewUrl.'</a>',0,1);
681
                }
682

    
683
                        // Output overview content:
684
                $this->content.= $this->doc->spacer(15);
685
                $this->content.= $this->doc->section($this->details ? 'Details for version' : 'Workspace management', $WSoverview,0,1);
686

    
687
        }
688

    
689
        /**
690
         * Rendering the overview of versions in the current workspace
691
         *
692
         * @return        string                HTML (table)
693
         * @see typo3/mod/user/ws/index.php for sister function!
694
         */
695
        function displayWorkspaceOverview()        {
696

    
697
                        // Initialize variables:
698
                $this->showWorkspaceCol = $GLOBALS['BE_USER']->workspace===0 && $this->MOD_SETTINGS['display']<=-98;
699

    
700
                        // Get usernames and groupnames
701
                $be_group_Array = t3lib_BEfunc::getListGroupNames('title,uid');
702
                $groupArray = array_keys($be_group_Array);
703
                $this->be_user_Array = t3lib_BEfunc::getUserNames();
704
                if (!$GLOBALS['BE_USER']->isAdmin())                $this->be_user_Array = t3lib_BEfunc::blindUserNames($this->be_user_Array,$groupArray,1);
705

    
706
                        // Initialize Workspace ID and filter-value:
707
                if ($GLOBALS['BE_USER']->workspace===0)        {
708
                        $wsid = $this->details ? -99 : $this->MOD_SETTINGS['display'];                // Set wsid to the value from the menu (displaying content of other workspaces)
709
                        $filter = $this->details ? 0 : $this->MOD_SETTINGS['filter'];
710
                } else {
711
                        $wsid = $GLOBALS['BE_USER']->workspace;
712
                        $filter = 0;
713
                }
714

    
715
                        // Initialize workspace object and request all pending versions:
716
                $wslibObj = t3lib_div::makeInstance('wslib');
717

    
718
                        // Selecting ALL versions belonging to the workspace:
719
                $versions = $wslibObj->selectVersionsInWorkspace($wsid, $filter, -99, $this->uid);        // $this->uid is the page id of LIVE record.
720

    
721
                        // Traverse versions and build page-display array:
722
                $pArray = array();
723
                foreach($versions as $table => $records)        {
724
                        foreach($records as $rec)        {
725
                                $pageIdField = $table==='pages' ? 't3ver_oid' : 'realpid';
726
                                $this->displayWorkspaceOverview_setInPageArray(
727
                                        $pArray,
728
                                        $table,
729
                                        $rec
730
                                );
731
                        }
732
                }
733

    
734
                        // Make header of overview:
735
                $tableRows = array();
736
                if (count($pArray))        {
737
                        $tableRows[] = '
738
                                <tr class="bgColor5 tableheader">
739
                                        '.($this->diffOnly?'':'<td nowrap="nowrap" colspan="2">Live Version:</td>').'
740
                                        <td nowrap="nowrap" colspan="2">Draft Versions:</td>
741
                                        <td nowrap="nowrap"'.($this->diffOnly?' colspan="2"':' colspan="4"').'>Controls:</td>
742
                                </tr>';
743

    
744
                                // Add lines from overview:
745
                        $tableRows = array_merge($tableRows, $this->displayWorkspaceOverview_list($pArray));
746

    
747
                        $table = '<table border="0" cellpadding="0" cellspacing="1" class="lrPadding workspace-overview">'.implode('',$tableRows).'</table>';
748
                } else $table = '';
749

    
750
                $linkBack = t3lib_div::_GP('returnUrl') ? '<a href="'.htmlspecialchars(t3lib_div::_GP('returnUrl')).'" class="typo3-goBack"><img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/goback.gif','width="14" height="14"').' alt="" />Click here to go back</a><br/><br/>' : '';
751
                $resetDiffOnly = $this->diffOnly ? '<a href="index.php?id='.intval($this->id).'" class="typo3-goBack">Show all information</a><br/><br/>' : '';
752

    
753
                $versionSelector = $GLOBALS['BE_USER']->workspace ? $this->doc->getVersionSelector($this->id) : '';
754

    
755
                return $versionSelector.$linkBack.$resetDiffOnly.$table.$this->markupNewOriginals();
756
        }
757

    
758
        /**
759
         * Rendering the content for the publish / review overview:
760
         * (Made for internal recursive calling)
761
         *
762
         * @param        array                Storage of the elements to display (see displayWorkspaceOverview() / displayWorkspaceOverview_setInPageArray())
763
         * @return        array                Table rows, see displayWorkspaceOverview()
764
         */
765
        function displayWorkspaceOverview_list($pArray)        {
766
                global $TCA;
767

    
768
                        // If there ARE elements on this level, print them:
769
                $warnAboutVersions_nonPages = FALSE;
770
                $warnAboutVersions_page = FALSE;
771
                if (is_array($pArray))        {
772
                        foreach($pArray as $table => $oidArray)        {
773
                                foreach($oidArray as $oid => $recs)        {
774

    
775
                                                // Get CURRENT online record and icon based on "t3ver_oid":
776
                                        $rec_on = t3lib_BEfunc::getRecord($table,$oid);
777
                                        $icon = t3lib_iconWorks::getIconImage($table, $rec_on, $this->doc->backPath,' align="top" title="'.t3lib_BEfunc::getRecordIconAltText($rec_on,$table).'"');
778
                                        if ($GLOBALS['BE_USER']->workspace===0) {        // Only edit online records if in ONLINE workspace:
779
                                                $icon = $this->doc->wrapClickMenuOnIcon($icon, $table, $rec_on['uid'], 1, '', '+edit,view,info,delete');
780
                                        }
781

    
782
                                                // Online version display:
783
                                                // Create the main cells which will span over the number of versions there is.
784
                                        $verLinkUrl = $TCA[$table]['ctrl']['versioningWS'];
785
                                        $origElement = $icon.
786
                                                ($verLinkUrl ? '<a href="'.htmlspecialchars('index.php?table='.$table.'&uid='.$rec_on['uid']).'">' : '').
787
                                                t3lib_BEfunc::getRecordTitle($table,$rec_on,TRUE).
788
                                                ($verLinkUrl ? '</a>' : '');
789
                                        $mainCell_rowSpan = count($recs)>1 ? ' rowspan="'.count($recs).'"' : '';
790
                                        $mainCell = '
791
                                                                <td align="center"'.$mainCell_rowSpan.'>'.$this->formatVerId($rec_on['t3ver_id']).'</td>
792
                                                                <td nowrap="nowrap"'.$mainCell_rowSpan.'>'.
793
                                                                        $origElement.
794
                                                                        '###SUB_ELEMENTS###'.        // For substitution with sub-elements, if any.
795
                                                                '</td>';
796

    
797
                                                // Offline versions display:
798
                                                // Traverse the versions of the element
799
                                        foreach($recs as $rec)        {
800

    
801
                                                        // Get the offline version record and icon:
802
                                                $rec_off = t3lib_BEfunc::getRecord($table,$rec['uid']);
803

    
804
                                                // Prepare swap-mode values:
805
                                                if ($table==='pages' && $rec_off['t3ver_swapmode']!=-1)        {
806
                                                        if ($rec_off['t3ver_swapmode']>0)        {
807
                                                                $vType = 'branch';
808
                                                        } else {
809
                                                                $vType = 'page';
810
                                                        }
811
                                                } else {
812
                                                        $vType = 'element';
813
                                                }
814
                                                
815
                                                // Get icon
816
                                                $icon = t3lib_iconWorks::getIconImage($table, $rec_off, $this->doc->backPath, ' align="top" title="'.t3lib_BEfunc::getRecordIconAltText($rec_off,$table).'"');
817
                                                $tempUid = ($table != 'pages' || $vType==='branch' || $GLOBALS['BE_USER']->workspace===0 ? $rec_off['uid'] : $rec_on['uid']);
818
                                                $icon = $this->doc->wrapClickMenuOnIcon($icon, $table, $tempUid, 1, '', '+edit,' . ($table == 'pages' ? 'view,info,' : '') . 'delete');
819

    
820
                                                        // Prepare diff-code:
821
                                                if ($this->MOD_SETTINGS['diff'] || $this->diffOnly)        {
822
                                                        $diffCode = '';
823
                                                        list($diffHTML,$diffPct) = $this->createDiffView($table, $rec_off, $rec_on);
824
                                                        if ($rec_on['t3ver_state']==1)        {        // New record:
825
                                                                $diffCode.= $this->doc->icons(1).'New element<br/>';        // TODO Localize?
826
                                                                $diffCode.= $diffHTML;
827
                                                        } elseif ($rec_off['t3ver_state']==2)        {
828
                                                                $diffCode.= $this->doc->icons(2).'Deleted element<br/>';
829
                                                        } else {
830
                                                                $diffCode.= ($diffPct<0 ? 'N/A' : ($diffPct ? $diffPct.'% change:' : ''));
831
                                                                $diffCode.= $diffHTML;
832
                                                        }
833
                                                } else $diffCode = '';
834

    
835
                                                switch($vType) {
836
                                                        case 'element':
837
                                                                $swapLabel = ' [Element]';
838
                                                                $swapClass = 'ver-element';
839
                                                                $warnAboutVersions_nonPages = $warnAboutVersions_page;        // Setting this if sub elements are found with a page+content (must be rendered prior to this of course!)
840
                                                        break;
841
                                                        case 'page':
842
                                                                $swapLabel = ' [Page]';
843
                                                                $swapClass = 'ver-page';
844
                                                                $warnAboutVersions_page = !$this->showWorkspaceCol;                // This value is true only if multiple workspaces are shown and we need the opposite here.
845
                                                        break;
846
                                                        case 'branch':
847
                                                                $swapLabel = ' [Branch]';
848
                                                                $swapClass = 'ver-branch';
849
                                                        break;
850
                                                }
851

    
852
                                                        // Modify main cell based on first version shown:
853
                                                $subElements = array();
854
                                                if ($table==='pages' && $rec_off['t3ver_swapmode']!=-1 && $mainCell)        {        // For "Page" and "Branch" swap modes where $mainCell is still carrying content (only first version)
855
                                                        $subElements['on'] = $this->subElements($rec_on['uid'], $rec_off['t3ver_swapmode']);
856
                                                        $subElements['off'] = $this->subElements($rec_off['uid'],$rec_off['t3ver_swapmode'],$rec_on['uid']);
857
                                                }
858
                                                $mainCell = str_replace('###SUB_ELEMENTS###', $subElements['on'], $mainCell);
859

    
860
                                                        // Create version element:
861
                                                $versionsInOtherWS = $this->versionsInOtherWS($table, $rec_on['uid']);
862
                                                $versionsInOtherWSWarning = $versionsInOtherWS && $GLOBALS['BE_USER']->workspace!==0 ? '<br/>'.$this->doc->icons(2).'Other version(s) in workspace '.$versionsInOtherWS : '';
863
                                                $multipleWarning = (!$mainCell && $GLOBALS['BE_USER']->workspace!==0? '<br/>'.$this->doc->icons(3).'<b>Multiple versions in same workspace!</b>' : '');
864
                                                $verWarning = $warnAboutVersions || ($warnAboutVersions_nonPages && $GLOBALS['TCA'][$table]['ctrl']['versioning_followPages'])? '<br/>'.$this->doc->icons(3).'<b>Version inside version!</b>' : '';
865
                                                $verElement = $icon.
866
                                                        (!$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)).'">' : '').
867
                                                        t3lib_BEfunc::getRecordTitle($table,$rec_off,TRUE).
868
                                                        (!$this->details ? '</a>' : '').
869
                                                        $versionsInOtherWSWarning.
870
                                                        $multipleWarning.
871
                                                        $verWarning;
872

    
873
                                                $ctrlTable = '
874
                                                                <td nowrap="nowrap">'.$this->showStageChangeLog($table,$rec_off['uid'],$this->displayWorkspaceOverview_stageCmd($table,$rec_off)).'</td>
875
                                                                <td nowrap="nowrap" class="'.$swapClass.'">'.
876
                                                                        $this->displayWorkspaceOverview_commandLinks($table,$rec_on,$rec_off,$vType).
877
                                                                        htmlspecialchars($swapLabel).
878
                                                                        '&nbsp;&nbsp;</td>
879
                                                                '.(!$this->diffOnly?'<td nowrap="nowrap"><b>Lifecycle:</b> '.htmlspecialchars($this->formatCount($rec_off['t3ver_count'])).'</td>'.                // Lifecycle
880
                                                                        ($this->showWorkspaceCol ? '
881
                                                                <td nowrap="nowrap">&nbsp;&nbsp;<b>Workspace:</b> '.htmlspecialchars($this->formatWorkspace($rec_off['t3ver_wsid'])).'</td>' : ''):'');
882

    
883
                                                if ($diffCode)        {
884
                                                        $verElement = $verElement.'
885
                                                        <br/><b>Difference to live element:</b>
886
                                                        <table border="0" cellpadding="0" cellspacing="0" class="ver-verElement">
887
                                                                <tr>
888
                                                                        <td class="c-diffCell">'.$diffCode.'</td>
889
                                                                </tr>
890
                                                        </table>';
891
                                                }
892

    
893

    
894
                                                        // Create version cell:
895
                                                $verCell = '
896
                                                                <td align="center">'.$this->formatVerId($rec_off['t3ver_id']).'</td>
897
                                                                <td nowrap="nowrap">'.
898
                                                                        $verElement.
899
                                                                        $subElements['off'].
900
                                                                        '</td>
901
                                                                ';
902

    
903
                                                        // Compile table row:
904
                                                $tableRows[] = '
905
                                                        <tr class="bgColor4">
906
                                                                '.
907
                                                                ($this->diffOnly?'':$mainCell).
908
                                                                $verCell.
909
                                                                $ctrlTable.
910
                                                                '
911
                                                        </tr>';
912

    
913
                                                        // Reset the main cell:
914
                                                $mainCell = '';
915

    
916
                                        }
917
                                }
918
                        }
919
                }
920

    
921
                return $tableRows;
922
        }
923

    
924
        /**
925
         * Building up of the $pArray
926
         * (Internal)
927
         *
928
         * @param        array                Array that is built up with the page tree structure
929
         * @param        string                Table name
930
         * @param        array                Table row
931
         * @return        void                $pArray is passed by reference and modified internally
932
         */
933
        function displayWorkspaceOverview_setInPageArray(&$pArray,$table,$row)        {
934
                if (!$this->details || $this->details==$table.':'.$row['uid'])        {
935
                        $pArray[$table][$row['t3ver_oid']][] = $row;
936
                }
937
        }
938

    
939
        /**
940
         * Links to stage change of a version
941
         *
942
         * @param        string                Table name
943
         * @param        array                Offline record (version)
944
         * @return        string                HTML content, mainly link tags and images.
945
         */
946
        function displayWorkspaceOverview_allStageCmd()        {
947

    
948
                $table = t3lib_div::_GP('table');
949
                if ($table && $table!='pages')        {
950
                        $uid = t3lib_div::_GP('uid');
951
                        if ($rec_off = t3lib_BEfunc::getRecordWSOL($table,$uid)) {
952
                                $uid = $rec_off['_ORIG_uid'];
953
                        }
954
                } else $table = '';
955

    
956
                if ($table)        {
957
                        if ($uid && $this->recIndex[$table][$uid])        {
958
                                $sId = $this->recIndex[$table][$uid];
959
                                switch($sId)        {
960
                                        case 1:
961
                                                $label = 'Comment for Reviewer:';
962
                                        break;
963
                                        case 10:
964
                                                $label = 'Comment for Publisher:';
965
                                        break;
966
                                }
967
                        } else $sId = 0;
968
                } else {
969
                        if (count($this->stageIndex[1]))        {        // Review:
970
                                $sId = 1;
971
                                $color = '#666666';
972
                                $label = 'Sending %s item(s) to review. Comment for Reviewer:';
973
                                $titleAttrib = 'Send all to Review';
974
                        } elseif(count($this->stageIndex[10]))  {        // Publish:
975
                                $sId = 10;
976
                                $color = '#6666cc';
977
                                $label = 'Approving %s item(s) to publishing. Comment for Publisher:';
978
                                $titleAttrib = 'Approve all for Publishing';
979
                        } else {
980
                                $sId = 0;
981
                        }
982
                }
983

    
984
                if ($sId>0)        {
985
                        $issueCmd = '';
986
                        $itemCount = 0;
987

    
988
                        if ($table && $uid && $this->recIndex[$table][$uid])        {
989
                                $issueCmd.='&cmd['.$table.']['.$uid.'][version][action]=setStage';
990
                                $issueCmd.='&cmd['.$table.']['.$uid.'][version][stageId]='.$this->recIndex[$table][$uid];
991
                        } else {
992
                                foreach($this->stageIndex[$sId] as $table => $uidArray)        {
993
                                        $issueCmd.='&cmd['.$table.']['.implode(',',$uidArray).'][version][action]=setStage';
994
                                        $issueCmd.='&cmd['.$table.']['.implode(',',$uidArray).'][version][stageId]='.$sId;
995
                                        $itemCount+=count($uidArray);
996
                                }
997
                        }
998

    
999
                        $onClick = 'var commentTxt=window.prompt("'.sprintf($label,$itemCount).'","");
1000
                                                        if (commentTxt!=null) {window.location.href="'.$this->doc->issueCommand($issueCmd,$this->REQUEST_URI).'&generalComment="+escape(commentTxt);}';
1001

    
1002
                        if (t3lib_div::_GP('sendToReview'))        {
1003
                                $onClick.= ' else {window.location.href = "'.$this->REQUEST_URI.'"}';
1004
                                $actionLinks.=
1005
                                        $this->doc->wrapScriptTags($onClick);
1006
                        } else {
1007
                                $onClick.= ' return false;';
1008
                                $actionLinks.=
1009
                                        '<input type="submit" name="_" value="'.htmlspecialchars($titleAttrib).'" onclick="'.htmlspecialchars($onClick).'" />';
1010
                        }        
1011
                } elseif (t3lib_div::_GP('sendToReview'))        {
1012
                        $onClick = 'window.location.href = "'.$this->REQUEST_URI.'";';
1013
                        $actionLinks.=
1014
                                $this->doc->wrapScriptTags($onClick);
1015
                } else $actionLinks = '';
1016

    
1017
                return $actionLinks;
1018
        }
1019

    
1020

    
1021

    
1022

    
1023

    
1024

    
1025
        /**************************************
1026
         *
1027
         * Helper functions (REDUNDANT FROM user/ws/index.php - someone could refactor this...)
1028
         *
1029
         *************************************/
1030

    
1031
        /**
1032
         * Formatting the version number for HTML output
1033
         *
1034
         * @param        integer                Version number
1035
         * @return        string                Version number for output
1036
         */
1037
        function formatVerId($verId)        {
1038
                return '1.'.$verId;
1039
        }
1040

    
1041
        /**
1042
         * Formatting workspace ID into a visual label
1043
         *
1044
         * @param        integer                Workspace ID
1045
         * @return        string                Workspace title
1046
         */
1047
        function formatWorkspace($wsid)        {
1048

    
1049
                        // Render, if not cached:
1050
                if (!isset($this->formatWorkspace_cache[$wsid]))        {
1051
                        switch($wsid)        {
1052
                                case -1:
1053
                                        $this->formatWorkspace_cache[$wsid] = '[Offline]';
1054
                                break;
1055
                                case 0:
1056
                                        $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...
1057
                                break;
1058
                                default:
1059
                                        list($titleRec) = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('title','sys_workspace','uid='.intval($wsid).t3lib_BEfunc::deleteClause('sys_workspace'));
1060
                                        $this->formatWorkspace_cache[$wsid] = '['.$wsid.'] '.$titleRec['title'];
1061
                                break;
1062
                        }
1063
                }
1064

    
1065
                return $this->formatWorkspace_cache[$wsid];
1066
        }
1067

    
1068
        /**
1069
         * Format publishing count for version (lifecycle state)
1070
         *
1071
         * @param        integer                t3ver_count value (number of times it has been online)
1072
         * @return        string                String translation of count.
1073
         */
1074
        function formatCount($count)        {
1075

    
1076
                        // Render, if not cached:
1077
                if (!isset($this->formatCount_cache[$count]))        {
1078
                        switch($count)        {
1079
                                case 0:
1080
                                        $this->formatCount_cache[$count] = 'Draft';
1081
                                break;
1082
                                case 1:
1083
                                        $this->formatCount_cache[$count] = 'Archive';
1084
                                break;
1085
                                default:
1086
                                        $this->formatCount_cache[$count] = 'Published '.$count.' times';
1087
                                break;
1088
                        }
1089
                }
1090

    
1091
                return $this->formatCount_cache[$count];
1092
        }
1093

    
1094
        /**
1095
         * Looking for versions of a record in other workspaces than the current
1096
         *
1097
         * @param        string                Table name
1098
         * @param        integer                Record uid
1099
         * @return        string                List of other workspace IDs
1100
         */
1101
        function versionsInOtherWS($table,$uid)        {
1102

    
1103
                        // Check for duplicates:
1104
                        // Select all versions of record NOT in this workspace:
1105
                $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1106
                        't3ver_wsid',
1107
                        $table,
1108
                        'pid=-1
1109
                                AND t3ver_oid='.intval($uid).'
1110
                                AND t3ver_wsid!='.intval($GLOBALS['BE_USER']->workspace).'
1111
                                AND (t3ver_wsid=-1 OR t3ver_wsid>0)'.
1112
                                t3lib_BEfunc::deleteClause($table),
1113
                        '',
1114
                        't3ver_wsid',
1115
                        '',
1116
                        't3ver_wsid'
1117
                );
1118
                if (count($rows))        {
1119
                        return implode(',',array_keys($rows));
1120
                }
1121
        }
1122

    
1123
        /**
1124
         * Looks up stage changes for version and displays a formatted view on mouseover.
1125
         *
1126
         * @param        string                Table name
1127
         * @param        integer                Record ID
1128
         * @param        string                HTML string to wrap the mouseover around (should be stage change links)
1129
         * @return        string                HTML code.
1130
         */
1131
        function showStageChangeLog($table,$id,$stageCommands)        {
1132
                $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1133
                        'log_data,tstamp,userid',
1134
                        'sys_log',
1135
                        'action=6 and details_nr=30
1136
                                AND tablename='.$GLOBALS['TYPO3_DB']->fullQuoteStr($table,'sys_log').'
1137
                                AND recuid='.intval($id)
1138
                );
1139

    
1140
                $entry = array();
1141
                foreach($rows as $dat)        {
1142
                        $data = unserialize($dat['log_data']);
1143
                        $username = $this->be_user_Array[$dat['userid']] ? $this->be_user_Array[$dat['userid']]['username'] : '['.$dat['userid'].']';
1144

    
1145
                        switch($data['stage'])        {
1146
                                case 1:
1147
                                        $text = 'sent element to "Review"';
1148
                                break;
1149
                                case 10:
1150
                                        $text = 'approved for "Publish"';
1151
                                break;
1152
                                case -1:
1153
                                        $text = 'rejected element!';
1154
                                break;
1155
                                case 0:
1156
                                        $text = 'reset to "Editing"';
1157
                                break;
1158
                                default:
1159
                                        $text = '[undefined]';
1160
                                break;
1161
                        }
1162
                        $text = t3lib_BEfunc::dateTime($dat['tstamp']).': "'.$username.'" '.$text;
1163
                        $text.= ($data['comment']?'<br/>User Comment: <em>'.htmlspecialchars($data['comment']).'</em>':'');
1164

    
1165
                        $entry[] = $text;
1166
                }
1167

    
1168
                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>'.
1169
                                '<div class="logLayer" style="visibility: hidden; position: absolute;" id="log_'.$table.$id.'">'.implode('<hr/>',array_reverse($entry)).'</div>' : $stageCommands;
1170
        }
1171

    
1172
        /**
1173
         * Creates display of sub elements of a page when the swap mode is either "Page" or "Branch" (0 / ALL)
1174
         *
1175
         * @param        integer                Page uid (for either online or offline version, but it MUST have swapmode/treeLevel set to >0 (not -1 indicating element versioning)
1176
         * @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!)
1177
         * @param        integer                For offline versions; This is t3ver_oid, the original ID of the online page.
1178
         * @return        string                HTML content.
1179
         */
1180
        function subElements($uid,$treeLevel,$origId=0)        {
1181
                global $TCA;
1182

    
1183
                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:
1184
                        return '<br/>
1185
                                        <img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/ol/joinbottom.gif','width="18" height="16"').' align="top" alt="" title="" />'.
1186
                                        ($origId ?
1187
                                                '<a href="'.htmlspecialchars($this->doc->backPath.t3lib_extMgm::extRelPath('version').'cm1/index.php?id='.$uid.'&details='.rawurlencode('pages:'.$uid).'&returnUrl='.rawurlencode($this->REQUEST_URI)).'">'.
1188
                                                '<span class="typo3-dimmed"><em>[Sub elements, click for details]</em><span></a>' :
1189
                                                '<span class="typo3-dimmed"><em>[Sub elements]</em><span>');
1190
                } else {        // For an offline workspace, show sub elements:
1191

    
1192
                        $tCell = array();
1193

    
1194
                                // Find records that follow pages when swapping versions:
1195
                        $recList = array();
1196
                        foreach($TCA as $tN => $tCfg)        {
1197
                                if ($tN!='pages' && ($treeLevel>0 || $TCA[$tN]['ctrl']['versioning_followPages']))        {
1198
                                        $this->subElements_getNonPageRecords($tN, $uid, $recList);
1199
                                }
1200
                        }
1201

    
1202
                                // Render records collected above:
1203
                        $elCount = count($recList)-1;
1204
                        foreach($recList as $c => $comb)        {
1205
                                list($tN,$rec) = $comb;
1206

    
1207
                                $this->subElements_renderItem(
1208
                                        $tCell,
1209
                                        $tN,
1210
                                        $uid,
1211
                                        $rec,
1212
                                        $origId,
1213
                                        $c==$elCount && $treeLevel==0 ? 1 : 0,                // If true, will show bottom-join icon.
1214
                                        ''
1215
                                );
1216
                        }
1217

    
1218
                                // For branch, dive into the subtree:
1219
                        if ($treeLevel>0) {
1220

    
1221
                                        // Drawing tree:
1222
                                $tree = t3lib_div::makeInstance('t3lib_pageTree');
1223
                                $tree->init('AND '.$GLOBALS['BE_USER']->getPagePermsClause(1));
1224
                                $tree->makeHTML = 2;                // 2=Also rendering depth-data into the result array
1225
                                $tree->getTree($uid, 99, '');
1226

    
1227
                                        // Traverse page tree:
1228
                                foreach($tree->tree as $data)        {
1229

    
1230
                                                // Render page in table cell:
1231
                                        $this->subElements_renderItem(
1232
                                                $tCell,
1233
                                                'pages',
1234
                                                $uid,
1235
                                                t3lib_BEfunc::getRecord('pages',$data['row']['uid']),        // Needs all fields, at least more than what is given in $data['row']...
1236
                                                $origId,
1237
                                                2,                // 2=the join icon and icon for the record is not rendered for pages (where all is in $data['HTML']
1238
                                                $data['HTML']
1239
                                        );
1240

    
1241
                                                // Find all records from page and collect in $recList:
1242
                                        $recList = array();
1243
                                        foreach($TCA as $tN => $tCfg)        {
1244
                                                if ($tN!=='pages')        {
1245
                                                        $this->subElements_getNonPageRecords($tN, $data['row']['uid'], $recList);
1246
                                                }
1247
                                        }
1248

    
1249
                                                // Render records collected above:
1250
                                        $elCount = count($recList)-1;
1251
                                        foreach($recList as $c => $comb)        {
1252
                                                list($tN,$rec) = $comb;
1253

    
1254
                                                $this->subElements_renderItem(
1255
                                                        $tCell,
1256
                                                        $tN,
1257
                                                        $uid,
1258
                                                        $rec,
1259
                                                        $origId,
1260
                                                        $c==$elCount?1:0,        // If true, will show bottom-join icon.
1261
                                                        $data['HTML_depthData']
1262
                                                );
1263
                                        }
1264
                                }
1265
                        }
1266

    
1267
                        return '
1268
                                        <!-- Sub-element tree for versions -->
1269
                                        <table border="0" cellpadding="0" cellspacing="1" class="ver-subtree">
1270
                                                '.implode('',$tCell).'
1271
                                        </table>';
1272
                }
1273
        }
1274

    
1275
        /**
1276
         * Select records from a table and add them to recList
1277
         *
1278
         * @param        string                Table name (from TCA)
1279
         * @param        integer                PID to select records from
1280
         * @param        array                Array where records are accumulated, passed by reference
1281
         * @return        void
1282
         */
1283
        function subElements_getNonPageRecords($tN, $uid, &$recList)        {
1284
                global $TCA;
1285

    
1286
                $records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1287
                        '*',
1288
                        $tN,
1289
                        'pid='.intval($uid).
1290
                                ($TCA[$tN]['ctrl']['versioningWS'] ? ' AND t3ver_state=0' : '').
1291
                                t3lib_BEfunc::deleteClause($tN),
1292
                        '',
1293
                        $TCA[$tN]['ctrl']['sortby'] ? $TCA[$tN]['ctrl']['sortby'] : $GLOBALS['TYPO3_DB']->stripOrderBy($TCA[$tN]['ctrl']['default_sortby'])
1294
                );
1295

    
1296
                foreach($records as $rec)        {
1297
                        $recList[] = array($tN,$rec);
1298
                }
1299
        }
1300

    
1301
        /**
1302
         * Render a single item in a subelement list into a table row:
1303
         *
1304
         * @param        array                Table rows, passed by reference
1305
         * @param        string                Table name
1306
         * @param        integer                Page uid for which the subelements are selected/shown
1307
         * @param        array                Row of element in list
1308
         * @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.
1309
         * @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)
1310
         * @param        string                Prefix HTML data (icons for tree rendering)
1311
         * @return        void                (Content accumulated in $tCell!)
1312
         */
1313
        function subElements_renderItem(&$tCell,$tN,$uid,$rec,$origId,$iconMode,$HTMLdata)        {
1314
                global $TCA;
1315

    
1316
                        // Initialize:
1317
                $origUidFields = $TCA[$tN]['ctrl']['origUid'];
1318
                $diffCode = '';
1319

    
1320
                if ($origUidFields)        {        // If there is a field for this table with original uids we will use that to connect records:
1321
                        if (!$origId)        {        // In case we are displaying the online originals:
1322
                                $this->targets['orig_'.$uid.'_'.$tN.'_'.$rec['uid']] = $rec;        // Build up target array (important that
1323
                                $tdParams =  ' id="orig_'.$uid.'_'.$tN.'_'.$rec['uid'].'" class="typo3-ver"';                // Setting ID of the table row
1324
                        } else {        // Version branch:
1325
                                if ($this->targets['orig_'.$origId.'_'.$tN.'_'.$rec[$origUidFields]])        {        // If there IS a corresponding original record...:
1326

    
1327
                                                // Prepare Table row parameters:
1328
                                        $tdParams =  ' onmouseover="hlSubelements(\''.$origId.'_'.$tN.'_'.$rec[$origUidFields].'\', \''.$uid.'_'.$tN.'_'.$rec[$origUidFields].'\', 1, '.($this->MOD_SETTINGS['diff']==2?1:0).');"'.
1329
                                                                ' onmouseout="hlSubelements(\''.$origId.'_'.$tN.'_'.$rec[$origUidFields].'\', \''.$uid.'_'.$tN.'_'.$rec[$origUidFields].'\', 0, '.($this->MOD_SETTINGS['diff']==2?1:0).');"'.
1330
                                                                ' id="ver_'.$uid.'_'.$tN.'_'.$rec[$origUidFields].'" class="typo3-ver"';
1331

    
1332
                                                // Create diff view:
1333
                                        if ($this->MOD_SETTINGS['diff'])        {
1334
                                                list($diffHTML,$diffPct) = $this->createDiffView($tN, $rec, $this->targets['orig_'.$origId.'_'.$tN.'_'.$rec[$origUidFields]]);
1335

    
1336
                                                if ($this->MOD_SETTINGS['diff']==2)        {
1337
                                                        $diffCode =
1338
                                                                ($diffPct ? '<span class="nobr">'.$diffPct.'% change</span>' : '-').
1339
                                                                '<div style="visibility: hidden; position: absolute;" id="diff_'.$uid.'_'.$tN.'_'.$rec[$origUidFields].'" class="diffLayer">'.
1340
                                                                $diffHTML.
1341
                                                                '</div>';
1342
                                                } else {
1343
                                                        $diffCode =
1344
                                                                ($diffPct<0 ? 'N/A' : ($diffPct ? $diffPct.'% change:' : '')).
1345
                                                                $diffHTML;
1346
                                                }
1347
                                        }
1348

    
1349
                                                // Unsetting the target fields allows us to mark all originals without a version in the subtree (see ->markupNewOriginals())
1350
                                        unset($this->targets['orig_'.$origId.'_'.$tN.'_'.$rec[$origUidFields]]);
1351
                                } else {        // No original record, so must be new:
1352
                                        $tdParams =  ' class="typo3-ver-new"';
1353
                                }
1354
                        }
1355
                } else {        // If no original uid column is supported for this table we are forced NOT to display any diff or highlighting.
1356
                        $tdParams = ' class="typo3-ver-noComp"';
1357
                }
1358

    
1359
                        // Compile the cell:
1360
                $tCell[] = '
1361
                                                <tr'.$tdParams.'>
1362
                                                        <td class="iconTitle">'.
1363
                                                                $HTMLdata.
1364
                                                                ($iconMode < 2 ?
1365
                                                                        '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/ol/join'.($iconMode ? 'bottom' : '').'.gif','width="18" height="16"').' alt="" />'.
1366
                                                                        t3lib_iconWorks::getIconImage($tN, $rec, $this->doc->backPath,'') : '').
1367
                                                                t3lib_BEfunc::getRecordTitle($tN, $rec, TRUE).
1368
                                                        '</td>
1369
                                                        <td class="cmdCell">'.
1370
                                                                $this->displayWorkspaceOverview_commandLinksSub($tN,$rec,$origId).
1371
                                                        '</td>'.($origId ? '<td class="diffCell">'.
1372
                                                                $diffCode.
1373
                                                        '</td>':'').'
1374
                                                </tr>';
1375
        }
1376

    
1377
        /**
1378
         * JavaScript code to mark up new records that are online (in sub element lists)
1379
         *
1380
         * @return        string                HTML javascript section
1381
         */
1382
        function markupNewOriginals()        {
1383

    
1384
                if (count($this->targets))        {
1385
                        $scriptCode = '';
1386
                        foreach($this->targets as $key => $rec)        {
1387
                                $scriptCode.='
1388
                                        document.getElementById(\''.$key.'\').attributes.getNamedItem("class").nodeValue = \'typo3-ver-new\';
1389
                                ';
1390
                        }
1391

    
1392
                        return $this->doc->wrapScriptTags($scriptCode);
1393
                }
1394
        }
1395

    
1396
        /**
1397
         * Create visual difference view of two records. Using t3lib_diff library
1398
         *
1399
         * @param        string                Table name
1400
         * @param        array                New version record (green)
1401
         * @param        array                Old version record (red)
1402
         * @return        array                Array with two keys (0/1) with HTML content / percentage integer (if -1, then it means N/A) indicating amount of change
1403
         */
1404
        function createDiffView($table, $diff_1_record, $diff_2_record)        {
1405
                global $TCA;
1406

    
1407
                        // Initialize:
1408
                $pctChange = 'N/A';
1409

    
1410
                        // Check that records are arrays:
1411
                if (is_array($diff_1_record) && is_array($diff_2_record))        {
1412

    
1413
                                // Load full table description and initialize diff-object:
1414
                        t3lib_div::loadTCA($table);
1415
                        $t3lib_diff_Obj = t3lib_div::makeInstance('t3lib_diff');
1416

    
1417
                                // Add header row:
1418
                        $tRows = array();
1419
                        $tRows[] = '
1420
                                <tr class="bgColor5 tableheader">
1421
                                        <td>Fieldname:</td>
1422
                                        <td width="98%" nowrap="nowrap">Colored diff-view:</td>
1423
                                </tr>
1424
                        ';
1425

    
1426
                                // Initialize variables to pick up string lengths in:
1427
                        $allStrLen = 0;
1428
                        $diffStrLen = 0;
1429

    
1430
                                // Traversing the first record and process all fields which are editable:
1431
                        foreach($diff_1_record as $fN => $fV)        {
1432
                                if ($TCA[$table]['columns'][$fN] && $TCA[$table]['columns'][$fN]['config']['type']!='passthrough' && !t3lib_div::inList('t3ver_label',$fN))        {
1433

    
1434
                                                // Check if it is files:
1435
                                        $isFiles = FALSE;
1436
                                        if (strcmp(trim($diff_1_record[$fN]),trim($diff_2_record[$fN])) &&
1437
                                                        $TCA[$table]['columns'][$fN]['config']['type']=='group' &&
1438
                                                        $TCA[$table]['columns'][$fN]['config']['internal_type']=='file')        {
1439

    
1440
                                                        // Initialize:
1441
                                                $uploadFolder = $TCA[$table]['columns'][$fN]['config']['uploadfolder'];
1442
                                                $files1 = array_flip(t3lib_div::trimExplode(',', $diff_1_record[$fN],1));
1443
                                                $files2 = array_flip(t3lib_div::trimExplode(',', $diff_2_record[$fN],1));
1444

    
1445
                                                        // Traverse filenames and read their md5 sum:
1446
                                                foreach($files1 as $filename => $tmp)        {
1447
                                                        $files1[$filename] = @is_file(PATH_site.$uploadFolder.'/'.$filename) ? md5(t3lib_div::getUrl(PATH_site.$uploadFolder.'/'.$filename)) : $filename;
1448
                                                }
1449
                                                foreach($files2 as $filename => $tmp)        {
1450
                                                        $files2[$filename] = @is_file(PATH_site.$uploadFolder.'/'.$filename) ? md5(t3lib_div::getUrl(PATH_site.$uploadFolder.'/'.$filename)) : $filename;
1451
                                                }
1452

    
1453
                                                        // Implode MD5 sums and set flag:
1454
                                                $diff_1_record[$fN] = implode(' ',$files1);
1455
                                                $diff_2_record[$fN] = implode(' ',$files2);
1456
                                                $isFiles = TRUE;
1457
                                        }
1458

    
1459
                                                // If there is a change of value:
1460
                                        if (strcmp(trim($diff_1_record[$fN]),trim($diff_2_record[$fN])))        {
1461

    
1462

    
1463
                                                        // Get the best visual presentation of the value and present that:
1464
                                                $val1 = t3lib_BEfunc::getProcessedValue($table,$fN,$diff_2_record[$fN],0,1);
1465
                                                $val2 = t3lib_BEfunc::getProcessedValue($table,$fN,$diff_1_record[$fN],0,1);
1466

    
1467
                                                        // Make diff result and record string lenghts:
1468
                                                $diffres = $t3lib_diff_Obj->makeDiffDisplay($val1,$val2,$isFiles?'div':'span');
1469
                                                $diffStrLen+= $t3lib_diff_Obj->differenceLgd;
1470
                                                $allStrLen+= strlen($val1.$val2);
1471

    
1472
                                                        // If the compared values were files, substituted MD5 hashes:
1473
                                                if ($isFiles)        {
1474
                                                        $allFiles = array_merge($files1,$files2);
1475
                                                        foreach($allFiles as $filename => $token)        {
1476
                                                                if (strlen($token)==32 && strstr($diffres,$token))        {
1477
                                                                        $filename =
1478
                                                                                t3lib_BEfunc::thumbCode(array($fN=>$filename),$table,$fN,$this->doc->backPath).
1479
                                                                                $filename;
1480
                                                                        $diffres = str_replace($token,$filename,$diffres);
1481
                                                                }
1482
                                                        }
1483
                                                }
1484

    
1485
                                                        // Add table row with result:
1486
                                                $tRows[] = '
1487
                                                        <tr class="bgColor4">
1488
                                                                <td>'.htmlspecialchars($GLOBALS['LANG']->sL(t3lib_BEfunc::getItemLabel($table,$fN))).'</td>
1489
                                                                <td width="98%">'.$diffres.'</td>
1490
                                                        </tr>
1491
                                                ';
1492
                                        } else {
1493
                                                        // Add string lengths even if value matched - in this was the change percentage is not high if only a single field is changed:
1494
                                                $allStrLen+=strlen($diff_1_record[$fN].$diff_2_record[$fN]);
1495
                                        }
1496
                                }
1497
                        }
1498

    
1499
                                // Calculate final change percentage:
1500
                        $pctChange = $allStrLen ? ceil($diffStrLen*100/$allStrLen) : -1;
1501

    
1502
                                // Create visual representation of result:
1503
                        if (count($tRows)>1)        {
1504
                                $content.= '<table border="0" cellpadding="1" cellspacing="1" class="diffTable">'.implode('',$tRows).'</table>';
1505
                        } else {
1506
                                $content.= '<span class="nobr">'.$this->doc->icons(1).'Complete match on editable fields.</span>';
1507
                        }
1508
                } else $content.= $this->doc->icons(3).'ERROR: Records could strangely not be found!';
1509

    
1510
                        // Return value:
1511
                return array($content,$pctChange);
1512
        }
1513

    
1514
        /**
1515
         * Links to stage change of a version
1516
         *
1517
         * @param        string                Table name
1518
         * @param        array                Offline record (version)
1519
         * @return        string                HTML content, mainly link tags and images.
1520
         */
1521
        function displayWorkspaceOverview_stageCmd($table,&$rec_off)        {
1522
#debug($rec_off['t3ver_stage']);
1523
                switch((int)$rec_off['t3ver_stage'])        {
1524
                        case 0:
1525
                                $sId = 1;
1526
                                $sLabel = 'Editing';
1527
                                $color = '#666666';
1528
                                 $label = 'Comment for Reviewer:';
1529
                                $titleAttrib = 'Send to Review';
1530
                        break;
1531
                        case 1:
1532
                                $sId = 10;
1533
                                $sLabel = 'Review';
1534
                                $color = '#6666cc';
1535
                                $label = 'Comment for Publisher:';
1536
                                $titleAttrib = 'Approve for Publishing';
1537
                        break;
1538
                        case 10:
1539
                                $sLabel = 'Publish';
1540
                                $color = '#66cc66';
1541
                        break;
1542
                        case -1:
1543
                                $sLabel = $this->doc->icons(2).'Rejected';
1544
                                $sId = 0;
1545
                                $color = '#ff0000';
1546
                                $label = 'Comment:';
1547
                                $titleAttrib = 'Reset stage';
1548
                        break;
1549
                        default:
1550
                                $sLabel = 'Undefined';
1551
                                $sId = 0;
1552
                                $color = '';
1553
                        break;
1554
                }
1555
#debug($sId);
1556

    
1557
                $raiseOk = !$GLOBALS['BE_USER']->workspaceCannotEditOfflineVersion($table,$rec_off);
1558

    
1559
                if ($raiseOk && $rec_off['t3ver_stage']!=-1)        {
1560
                        $onClick = 'var commentTxt=window.prompt("Please explain why you reject:","");
1561
                                                        if (commentTxt!=null) {window.location.href="'.$this->doc->issueCommand(
1562
                                                        '&cmd['.$table.']['.$rec_off['uid'].'][version][action]=setStage'.
1563
                                                        '&cmd['.$table.']['.$rec_off['uid'].'][version][stageId]=-1'
1564
                                                        ).'&cmd['.$table.']['.$rec_off['uid'].'][version][comment]="+escape(commentTxt);}'.
1565
                                                        ' return false;';
1566
                                // Reject:
1567
                        $actionLinks.=
1568
                                '<a href="#" onclick="'.htmlspecialchars($onClick).'">'.
1569
                                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/down.gif','width="14" height="14"').' alt="" align="top" title="Reject" />'.
1570
                                '</a>';
1571
                } else {
1572
                                // Reject:
1573
                        $actionLinks.=
1574
                                '<img src="'.$this->doc->backPath.'gfx/clear.gif" width="14" height="14" alt="" align="top" title="" />';
1575
                }
1576

    
1577
                $actionLinks.= '<span style="background-color: '.$color.'; color: white;">'.$sLabel.'</span>';
1578

    
1579
                        // Raise
1580
                if ($raiseOk)        {
1581
                        $onClick = 'var commentTxt=window.prompt("'.$label.'","");
1582
                                                        if (commentTxt!=null) {window.location.href="'.$this->doc->issueCommand(
1583
                                                        '&cmd['.$table.']['.$rec_off['uid'].'][version][action]=setStage'.
1584
                                                        '&cmd['.$table.']['.$rec_off['uid'].'][version][stageId]='.$sId
1585
                                                        ).'&cmd['.$table.']['.$rec_off['uid'].'][version][comment]="+escape(commentTxt);}'.
1586
                                                        ' return false;';
1587
                        if ($rec_off['t3ver_stage']!=10)        {
1588
                                $actionLinks.=
1589
                                        '<a href="#" onclick="'.htmlspecialchars($onClick).'">'.
1590
                                        '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/up.gif','width="14" height="14"').' alt="" align="top" title="'.htmlspecialchars($titleAttrib).'" />'.
1591
                                        '</a>';
1592

    
1593
                                $this->stageIndex[$sId][$table][] = $rec_off['uid'];
1594
                                $this->recIndex[$table][$rec_off['uid']] = $sId;
1595
                        }
1596
                }
1597
                return $actionLinks;
1598
        }
1599

    
1600
        /**
1601
         * Links to publishing etc of a version
1602
         *
1603
         * @param        string                Table name
1604
         * @param        array                Online record
1605
         * @param        array                Offline record (version)
1606
         * @param        string                Swap type, "branch", "page" or "element"
1607
         * @return        string                HTML content, mainly link tags and images.
1608
         */
1609
        function displayWorkspaceOverview_commandLinks($table,&$rec_on,&$rec_off,$vType)        {
1610
                if ($this->publishAccess && (!($GLOBALS['BE_USER']->workspaceRec['publish_access']&1) || (int)$rec_off['t3ver_stage']===10))        {
1611
                        $actionLinks =
1612
                                '<a href="'.htmlspecialchars($this->doc->issueCommand(
1613
                                                '&cmd['.$table.']['.$rec_on['uid'].'][version][action]=swap'.
1614
                                                '&cmd['.$table.']['.$rec_on['uid'].'][version][swapWith]='.$rec_off['uid']
1615
                                                )).'">'.
1616
                                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert1.gif','width="14" height="14"').' alt="" align="top" title="Publish" />'.
1617
                                '</a>';
1618
                        if ($GLOBALS['BE_USER']->workspaceSwapAccess() && (int)$rec_on['t3ver_state']!==1 && (int)$rec_off['t3ver_state']!==2)        {
1619
                                $actionLinks.=
1620
                                        '<a href="'.htmlspecialchars($this->doc->issueCommand(
1621
                                                        '&cmd['.$table.']['.$rec_on['uid'].'][version][action]=swap'.
1622
                                                        '&cmd['.$table.']['.$rec_on['uid'].'][version][swapWith]='.$rec_off['uid'].
1623
                                                        '&cmd['.$table.']['.$rec_on['uid'].'][version][swapIntoWS]=1'
1624
                                                        )).'">'.
1625
                                        '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/swap.png','width="14" height="14"').' alt="" align="top" title="Swap" />'.
1626
                                        '</a>';
1627
                        }
1628
                }
1629

    
1630
                if (!$GLOBALS['BE_USER']->workspaceCannotEditOfflineVersion($table,$rec_off))        {
1631
                                // Release
1632
                        $actionLinks.=
1633
                                '<a href="'.htmlspecialchars($this->doc->issueCommand('&cmd['.$table.']['.$rec_off['uid'].'][version][action]=clearWSID')).'" onclick="return confirm(\'Remove from workspace?\');">'.
1634
                                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/group_clear.gif','width="14" height="14"').' alt="" align="top" title="Remove from workspace" />'.
1635
                                '</a>';
1636

    
1637
                                // Edit
1638
                        if ($table==='pages' && $vType!=='element')        {
1639
                                $tempUid = ($vType==='branch' || $GLOBALS['BE_USER']->workspace===0 ? $rec_off['uid'] : $rec_on['uid']);
1640
                                $actionLinks.=
1641
                                        '<a href="#" onclick="top.loadEditId('.$tempUid.');top.goToModule(\''.$this->pageModule.'\'); return false;">'.
1642
                                        '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,t3lib_extMgm::extRelPath('cms').'layout/layout.gif','width="14" height="12"').' title="Edit page" alt="" />'.
1643
                                        '</a>';
1644
                        } else {
1645
                                $params = '&edit['.$table.']['.$rec_off['uid'].']=edit';
1646
                                $actionLinks.=
1647
                                        '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->doc->backPath)).'">'.
1648
                                        '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/edit2.gif','width="12" height="12"').' title="Edit element" alt="" />'.
1649
                                        '</a>';
1650
                        }
1651
                }
1652

    
1653
                        // History/Log
1654
                $actionLinks.=
1655
                        '<a href="'.htmlspecialchars($this->doc->backPath.'show_rechis.php?element='.rawurlencode($table.':'.$rec_off['uid']).'&returnUrl='.rawurlencode($this->REQUEST_URI)).'">'.
1656
                        '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/history2.gif','width="13" height="12"').' title="Show Log" alt="" />'.
1657
                        '</a>';
1658

    
1659
                        // View
1660
                if ($table==='pages')        {
1661
                        $tempUid = ($vType==='branch' || $GLOBALS['BE_USER']->workspace===0 ? $rec_off['uid'] : $rec_on['uid']);
1662
                        $actionLinks.=
1663
                                '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($tempUid,$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($tempUid))).'">'.
1664
                                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/zoom.gif','width="12" height="12"').' title="" alt="" />'.
1665
                                '</a>';
1666
                }
1667

    
1668
                return $actionLinks;
1669
        }
1670

    
1671
        /**
1672
         * Links to publishing etc of a version
1673
         *
1674
         * @param        string                Table name
1675
         * @param        array                Record
1676
         * @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.
1677
         * @return        string                HTML content, mainly link tags and images.
1678
         */
1679
        function displayWorkspaceOverview_commandLinksSub($table,$rec,$origId)        {
1680
                $uid = $rec['uid'];
1681
                if ($origId || $GLOBALS['BE_USER']->workspace===0)        {
1682
                        if (!$GLOBALS['BE_USER']->workspaceCannotEditRecord($table,$rec))        {
1683
                                        // Edit
1684
                                if ($table==='pages')        {
1685
                                        $actionLinks.=
1686
                                                '<a href="#" onclick="top.loadEditId('.$uid.');top.goToModule(\''.$this->pageModule.'\'); return false;">'.
1687
                                                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,t3lib_extMgm::extRelPath('cms').'layout/layout.gif','width="14" height="12"').' title="Edit page" alt="" />'.
1688
                                                '</a>';
1689
                                } else {
1690
                                        $params = '&edit['.$table.']['.$uid.']=edit';
1691
                                        $actionLinks.=
1692
                                                '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->doc->backPath)).'">'.
1693
                                                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/edit2.gif','width="12" height="12"').' title="Edit element" alt="" />'.
1694
                                                '</a>';
1695
                                }
1696
                        }
1697

    
1698
                                // History/Log
1699
                        $actionLinks.=
1700
                                '<a href="'.htmlspecialchars($this->doc->backPath.'show_rechis.php?element='.rawurlencode($table.':'.$uid).'&returnUrl='.rawurlencode($this->REQUEST_URI)).'">'.
1701
                                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/history2.gif','width="13" height="12"').' title="Show Log" alt="" />'.
1702
                                '</a>';
1703
                }
1704

    
1705
                        // View
1706
                if ($table==='pages')        {
1707
                        $actionLinks.=
1708
                                '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($uid,$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($uid))).'">'.
1709
                                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/zoom.gif','width="12" height="12"').' title="" alt="" />'.
1710
                                '</a>';
1711
                }
1712

    
1713
                return $actionLinks;
1714
        }
1715

    
1716

    
1717

    
1718

    
1719

    
1720

    
1721

    
1722

    
1723

    
1724
        /**********************************
1725
         *
1726
         * Processing
1727
         *
1728
         **********************************/
1729

    
1730
        /**
1731
         * Will publish workspace if buttons are pressed
1732
         *
1733
         * @return        void
1734
         */
1735
        function publishAction()        {
1736

    
1737
                        // If "Publish" or "Swap" buttons are pressed:
1738
                if (t3lib_div::_POST('_publish') || t3lib_div::_POST('_swap'))        {
1739

    
1740
                        if ($this->table==='pages')        {        // Making sure ->uid is a page ID!
1741
                                        // Initialize workspace object and request all pending versions:
1742
                                $wslibObj = t3lib_div::makeInstance('wslib');
1743
                                $cmd = $wslibObj->getCmdArrayForPublishWS($GLOBALS['BE_USER']->workspace, t3lib_div::_POST('_swap'),$this->uid);
1744

    
1745
                                        // Execute the commands:
1746
                                $tce = t3lib_div::makeInstance('t3lib_TCEmain');
1747
                                $tce->stripslashes_values = 0;
1748
                                $tce->start(array(), $cmd);
1749
                                $tce->process_cmdmap();
1750

    
1751
                                t3lib_BEfunc::getSetUpdateSignal('updatePageTree');
1752

    
1753
                                return $tce->errorLog;
1754
                        }
1755
                }
1756
        }
1757
}
1758

    
1759

    
1760

    
1761
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/version/cm1/index.php'])        {
1762
        include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/version/cm1/index.php']);
1763
}
1764

    
1765

    
1766

    
1767

    
1768
// Make instance:
1769
$SOBE = t3lib_div::makeInstance('tx_version_cm1');
1770
$SOBE->init();
1771

    
1772

    
1773
$SOBE->main();
1774
$SOBE->printContent();
1775

    
1776
?>