Best of saturday night.
[Packages/TYPO3.CMS.git] / typo3 / sysext / version / cm1 / index.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2004-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24 /**
25 * Versioning module
26 *
27 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
28 */
29 /**
30 * [CLASS/FUNCTION INDEX of SCRIPT]
31 *
32 *
33 *
34 * 73: class tx_version_cm1 extends t3lib_SCbase
35 * 80: function main()
36 * 105: function jumpToUrl(URL)
37 * 139: function printContent()
38 * 150: function moduleContent()
39 * 310: function pageSubContent($pid,$c=0)
40 * 364: function lookForOwnVersions($table,$uid)
41 * 381: function adminLinks($table,$row)
42 *
43 * TOTAL FUNCTIONS: 7
44 * (This index is automatically created/updated by the extension "extdeveval")
45 *
46 */
47
48
49 // DEFAULT initialization of a module [BEGIN]
50 unset($MCONF);
51 require ('conf.php');
52 require ($BACK_PATH.'init.php');
53 require ($BACK_PATH.'template.php');
54 $LANG->includeLLFile('EXT:version/locallang.xml');
55 require_once (PATH_t3lib.'class.t3lib_scbase.php');
56 // DEFAULT initialization of a module [END]
57
58 require_once(PATH_t3lib.'class.t3lib_diff.php');
59
60
61
62 /**
63 * Versioning module, including workspace management
64 *
65 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
66 * @package TYPO3
67 * @subpackage core
68 */
69 class tx_version_cm1 extends t3lib_SCbase {
70
71
72 /**
73 * Main function of the module. Write the content to $this->content
74 *
75 * @return void
76 */
77 function main() {
78 global $BE_USER,$LANG,$BACK_PATH,$TCA_DESCR,$TCA,$CLIENT,$TYPO3_CONF_VARS;
79
80 // Draw the header.
81 $this->doc = t3lib_div::makeInstance('mediumDoc');
82 $this->doc->backPath = $BACK_PATH;
83 $this->doc->form='<form action="" method="post">';
84
85 // Getting input data:
86 $this->id = intval(t3lib_div::_GP('id')); // Page id. If set, indicates activation from Web>Versioning module
87 if (!$this->id) {
88 $this->uid = intval(t3lib_div::_GP('uid')); // Record uid. Goes with table name to indicate specific record
89 $this->table = t3lib_div::_GP('table'); // Record table. Goes with uid to indicate specific record
90 } else {
91 $this->uid = $this->id;
92 $this->table = 'pages';
93 }
94
95 // Reading the record:
96 $record = t3lib_BEfunc::getRecord($this->table,$this->uid);
97 if ($record['pid']==-1) {
98 $record = t3lib_BEfunc::getRecord($this->table,$record['t3ver_oid']);
99 }
100
101 // Checking access etc.
102 if (is_array($record) && $TCA[$this->table]['ctrl']['versioningWS']) {
103 $this->uid = $record['uid']; // Might have changed if new live record was found!
104
105 // Access check!
106 // The page will show only if there is a valid page and if this page may be viewed by the user
107 $this->pageinfo = t3lib_BEfunc::readPageAccess($record['pid'],$this->perms_clause);
108 $access = is_array($this->pageinfo) ? 1 : 0;
109
110 if (($record['pid'] && $access) || ($BE_USER->user['admin'] && !$record['pid'])) {
111
112 // JavaScript
113 $this->doc->JScode = '
114 <script language="javascript" type="text/javascript">
115 script_ended = 0;
116 function jumpToUrl(URL) {
117 document.location = URL;
118 }
119 </script>
120 ';
121
122 $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);
123
124 $this->content.=$this->doc->startPage($LANG->getLL('title'));
125 $this->content.=$this->doc->header($LANG->getLL('title'));
126 $this->content.=$this->doc->spacer(5);
127 $this->content.=$this->doc->section('',$headerSection);
128 $this->content.=$this->doc->divider(5);
129
130 // Render content:
131 if ($this->id) {
132 $this->workspaceMgm();
133 } else {
134 $this->versioningMgm();
135 }
136
137 // ShortCut
138 if ($BE_USER->mayMakeShortcut()) {
139 $this->content.=$this->doc->spacer(20).$this->doc->section('',$this->doc->makeShortcutIcon('id',implode(',',array_keys($this->MOD_MENU)),$this->MCONF['name']));
140 }
141 }
142
143 $this->content.=$this->doc->spacer(10);
144 }
145 }
146
147 /**
148 * Outputs accumulated module content to browser.
149 *
150 * @return void
151 */
152 function printContent() {
153
154 $this->content.=$this->doc->endPage();
155 echo $this->content;
156 }
157
158
159
160
161
162
163
164
165
166
167 /******************************
168 *
169 * Versioning management
170 *
171 ******************************/
172
173 /**
174 * Management of versions for record
175 *
176 * @return void
177 */
178 function versioningMgm() {
179 global $TCA;
180
181 // Diffing:
182 $diff_1 = t3lib_div::_POST('diff_1');
183 $diff_2 = t3lib_div::_POST('diff_2');
184 if (t3lib_div::_POST('do_diff')) {
185 $content='';
186 $content.='<h3>DIFFING:</h3>';
187 if ($diff_1 && $diff_2) {
188 $diff_1_record = t3lib_BEfunc::getRecord($this->table, $diff_1);
189 $diff_2_record = t3lib_BEfunc::getRecord($this->table, $diff_2);
190
191 if (is_array($diff_1_record) && is_array($diff_2_record)) {
192 t3lib_div::loadTCA($this->table);
193 $t3lib_diff_Obj = t3lib_div::makeInstance('t3lib_diff');
194
195 $tRows=array();
196 $tRows[] = '
197 <tr class="bgColor5 tableheader">
198 <td>Fieldname:</td>
199 <td width="98%">Colored diff-view:</td>
200 </tr>
201 ';
202 foreach($diff_1_record as $fN => $fV) {
203 if ($TCA[$this->table]['columns'][$fN] && $TCA[$this->table]['columns'][$fN]['config']['type']!='passthrough' && !t3lib_div::inList('t3ver_label',$fN)) {
204 if (strcmp($diff_1_record[$fN],$diff_2_record[$fN])) {
205
206 $diffres = $t3lib_diff_Obj->makeDiffDisplay(
207 t3lib_BEfunc::getProcessedValue($this->table,$fN,$diff_2_record[$fN],0,1),
208 t3lib_BEfunc::getProcessedValue($this->table,$fN,$diff_1_record[$fN],0,1)
209 );
210
211 $tRows[] = '
212 <tr class="bgColor4">
213 <td>'.$fN.'</td>
214 <td width="98%">'.$diffres.'</td>
215 </tr>
216 ';
217 }
218 }
219 }
220
221 if (count($tRows)>1) {
222 $content.='<table border="0" cellpadding="1" cellspacing="1" width="100%">'.implode('',$tRows).'</table><br/><br/>';
223 } else {
224 $content.='Records matches completely on all editable fields!';
225 }
226 } else $content.='ERROR: Records could strangely not be found!';
227 } else {
228 $content.='ERROR: You didn\'t select two sources for diffing!';
229 }
230 }
231
232 // Element:
233 $record = t3lib_BEfunc::getRecord($this->table,$this->uid);
234 $recordIcon = t3lib_iconWorks::getIconImage($this->table,$record,$this->doc->backPath,'class="absmiddle"');
235 $recTitle = t3lib_BEfunc::getRecordTitle($this->table,$record,1);
236
237 // Display versions:
238 $content.='
239 '.$recordIcon.$recTitle.'
240 <form action="'.t3lib_div::getIndpEnv('REQUEST_URI').'" method="post">
241 <table border="0" cellspacing="1" cellpadding="1">';
242 $content.='
243 <tr class="bgColor5 tableheader">
244 <td>&nbsp;</td>
245 <td>&nbsp;</td>
246 <td>Title</td>
247 <td>UID</td>
248 <td>t3ver_oid</td>
249 <td>t3ver_id</td>
250 <td>t3ver_wsid</td>
251 <td>pid</td>
252 <td>t3ver_label</td>
253 <td colspan="2"><input type="submit" name="do_diff" value="Diff" /></td>
254 </tr>';
255
256 $versions = t3lib_BEfunc::selectVersionsOfRecord($this->table, $this->uid, '*', $GLOBALS['BE_USER']->workspace);
257 foreach($versions as $row) {
258 $adminLinks = $this->adminLinks($this->table,$row);
259
260 $content.='
261 <tr class="'.($row['uid']!=$this->uid ? 'bgColor4' : 'bgColor2 tableheader').'">
262 <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').'">'.
263 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert1.gif','width="14" height="14"').' alt="" title="SWAP with current" />'.
264 '</a>' /* (
265 $this->table == 'pages' ?
266 '<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').'">'.
267 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert2.gif','width="14" height="14"').' alt="" title="Publish page AND content!" />'.
268 '</a>'.
269 '<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').'">'.
270 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/insert4.gif','width="14" height="14"').' alt="" title="Publish page AND content! - AND ALL SUBPAGES!" />'.
271 '</a>' : '') */ : '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/blinkarrow_left.gif','width="5" height="9"').' alt="" title="CURRENT ONLINE VERSION!"/>').'</td>
272 <td>'.$adminLinks.'</td>
273 <td nowrap="nowrap">'.t3lib_BEfunc::getRecordTitle($this->table,$row,1).'</td>
274 <td>'.$row['uid'].'</td>
275 <td>'.$row['t3ver_oid'].'</td>
276 <td>'.$row['t3ver_id'].'</td>
277 <td>'.$row['t3ver_wsid'].'</td>
278 <td>'.$row['pid'].'</td>
279 <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>
280 <td bgcolor="green"><input type="radio" name="diff_1" value="'.$row['uid'].'"'.($diff_1==$row['uid'] ? ' checked="checked"':'').'/></td>
281 <td bgcolor="red"><input type="radio" name="diff_2" value="'.$row['uid'].'"'.($diff_2==$row['uid'] ? ' checked="checked"':'').'/></td>
282 </tr>';
283
284 // 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;)
285 if ($this->table == 'pages' && $row['uid']!=$this->uid) {
286 $sub = $this->pageSubContent($row['uid']);
287
288 if ($sub) {
289 $content.='
290 <tr>
291 <td></td>
292 <td></td>
293 <td colspan="7">'.$sub.'</td>
294 <td colspan="2"></td>
295 </tr>';
296 }
297 }
298 }
299 $content.='</table></form>';
300
301 $this->content.=$this->doc->section('',$content,0,1);
302
303
304 // Create new:
305 $content='
306
307 <form action="'.$this->doc->backPath.'tce_db.php" method="post">
308 Label: <input type="text" name="cmd['.$this->table.']['.$this->uid.'][version][label]" /><br/>
309 '.($this->table == 'pages' ? '<select name="cmd['.$this->table.']['.$this->uid.'][version][treeLevels]">
310 <option value="0">Page: Page + content</option>
311 <option value="100">Branch: All subpages</option>
312 <option value="-1">Element: Just record</option>
313 </select>' : '').'
314 <br/><input type="hidden" name="cmd['.$this->table.']['.$this->uid.'][version][action]" value="new" />
315 <input type="hidden" name="prErr" value="1" />
316 <input type="hidden" name="redirect" value="'.t3lib_div::getIndpEnv('REQUEST_URI').'" />
317 <input type="submit" name="_" value="Create new version" />
318
319 </form>
320
321 ';
322
323 $this->content.=$this->doc->spacer(15);
324 $this->content.=$this->doc->section('Create new version',$content,0,1);
325
326 }
327
328 /**
329 * Recursively look for children for page version with $pid
330 *
331 * @param integer UID of page record for which to look up sub-elements following that version
332 * @param integer Counter, do not set (limits to 100 levels)
333 * @return string Table with content if any
334 */
335 function pageSubContent($pid,$c=0) {
336 global $TCA;
337
338 $tableNames = t3lib_div::removeArrayEntryByValue(array_keys($TCA),'pages');
339 $tableNames[] = 'pages';
340
341 foreach($tableNames as $tN) {
342 // Basically list ALL tables - not only those being copied might be found!
343 #if ($TCA[$tN]['ctrl']['versioning_followPages'] || $tN=='pages') {
344 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $tN, 'pid='.intval($pid).t3lib_BEfunc::deleteClause($tN), '', ($TCA[$tN]['ctrl']['sortby'] ? $TCA[$tN]['ctrl']['sortby'] : ''));
345
346 if ($GLOBALS['TYPO3_DB']->sql_num_rows($mres)) {
347 $content.='
348 <tr>
349 <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>
350 </tr>';
351 while ($subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) {
352 $ownVer = $this->lookForOwnVersions($tN,$subrow['uid']);
353 $content.='
354 <tr>
355 <td>'.$this->adminLinks($tN,$subrow).'</td>
356 <td>'.$subrow['uid'].'</td>
357 '.($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>').'
358 <td width="98%">'.t3lib_BEfunc::getRecordTitle($tN,$subrow,1).'</td>
359 </tr>';
360
361 if ($tN == 'pages' && $c<100) {
362 $sub = $this->pageSubContent($subrow['uid'],$c+1);
363
364 if ($sub) {
365 $content.='
366 <tr>
367 <td></td>
368 <td></td>
369 <td></td>
370 <td width="98%">'.$sub.'</td>
371 </tr>';
372 }
373 }
374 }
375 }
376 #}
377 }
378
379 return $content ? '<table border="1" cellpadding="1" cellspacing="0" width="100%">'.$content.'</table>' : '';
380 }
381
382 /**
383 * Look for number of versions of a record
384 *
385 * @param string Table name
386 * @param integer Record uid
387 * @return integer Number of versions for record, false if none.
388 */
389 function lookForOwnVersions($table,$uid) {
390 global $TCA;
391
392 $versions = t3lib_BEfunc::selectVersionsOfRecord($table, $uid, 'uid');
393 if (is_array($versions)) {
394 return count($versions);
395 }
396 return FALSE;
397 }
398
399 /**
400 * Administrative links for a table / record
401 *
402 * @param string Table name
403 * @param array Record for which administrative links are generated.
404 * @return string HTML link tags.
405 */
406 function adminLinks($table,$row) {
407 global $BE_USER;
408
409 $adminLink = '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick('&edit['.$table.']['.$row['uid'].']=edit',$this->doc->backPath)).'">'.
410 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/edit2.gif','width="11" height="12"').' alt="" title="Edit"/>'.
411 '</a>';
412
413 if ($table == 'pages') {
414
415 // If another page module was specified, replace the default Page module with the new one
416 $newPageModule = trim($BE_USER->getTSConfigVal('options.overridePageModule'));
417 $pageModule = t3lib_BEfunc::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
418
419 // Perform some acccess checks:
420 $a_wl = $BE_USER->check('modules','web_list');
421 $a_wp = t3lib_extMgm::isLoaded('cms') && $BE_USER->check('modules',$pageModule);
422
423 $adminLink.='<a href="#" onclick="top.loadEditId('.$row['uid'].');top.goToModule(\''.$pageModule.'\'); return false;">'.
424 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,t3lib_extMgm::extRelPath('cms').'layout/layout.gif','width="14" height="12"').' title="" alt="" />'.
425 '</a>';
426 $adminLink.='<a href="#" onclick="top.loadEditId('.$row['uid'].');top.goToModule(\'web_list\'); return false;">'.
427 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'mod/web/list/list.gif','width="14" height="12"').' title="" alt="" />'.
428 '</a>';
429
430 // "View page" icon is added:
431 $adminLink.='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($row['uid'],$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($row['uid']))).'">'.
432 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/zoom.gif','width="12" height="12"').' title="" alt="" />'.
433 '</a>';
434 } else {
435 if ($row['pid']==-1) {
436 $getVars = '&ADMCMD_vPrev['.rawurlencode($table.':'.$row['t3ver_oid']).']='.$row['uid'];
437
438 // "View page" icon is added:
439 $adminLink.='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($row['_REAL_PID'],$this->doc->backPath,t3lib_BEfunc::BEgetRootLine($row['_REAL_PID']),'','',$getVars)).'">'.
440 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/zoom.gif','width="12" height="12"').' title="" alt="" />'.
441 '</a>';
442 }
443 }
444
445 return $adminLink;
446 }
447
448
449
450
451
452
453
454
455
456
457
458 /******************************
459 *
460 * Workspace management
461 *
462 ******************************/
463
464 /**
465 * Management of workspace for page ID
466 * Called when $this->id is set.
467 *
468 * @return void
469 */
470 function workspaceMgm() {
471 $this->content.=$this->doc->spacer(15);
472 $this->content.=$this->doc->section('Workspace management','... - ...',0,1);
473 }
474 }
475
476
477
478 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/version/cm1/index.php']) {
479 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/version/cm1/index.php']);
480 }
481
482
483
484
485 // Make instance:
486 $SOBE = t3lib_div::makeInstance('tx_version_cm1');
487 $SOBE->init();
488
489
490 $SOBE->main();
491 $SOBE->printContent();
492
493 ?>