* Merging all changes from TYPO3_4-0 branch back into HEAD
[Packages/TYPO3.CMS.git] / typo3 / alt_doc.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-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 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Main form rendering script
29 * By sending certain parameters to this script you can bring up a form
30 * which allows the user to edit the content of one or more database records.
31 *
32 * $Id$
33 * Revised for TYPO3 3.6 November/2003 by Kasper Skaarhoj
34 * XHTML compliant
35 *
36 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
37 */
38 /**
39 * [CLASS/FUNCTION INDEX of SCRIPT]
40 *
41 *
42 *
43 * 105: class SC_alt_doc
44 * 179: function preInit()
45 * 241: function doProcessData()
46 * 251: function processData()
47 * 379: function init()
48 * 473: function main()
49 * 551: function printContent()
50 *
51 * SECTION: Sub-content functions, rendering specific parts of the module content.
52 * 587: function makeEditForm()
53 * 771: function makeButtonPanel()
54 * 850: function makeDocSel()
55 * 892: function makeCmenu()
56 * 914: function compileForm($panel,$docSel,$cMenu,$editForm, $langSelector='')
57 * 982: function functionMenus()
58 * 1013: function shortCutLink()
59 * 1044: function tceformMessages()
60 *
61 * SECTION: Localization stuff
62 * 1083: function languageSwitch($table, $uid, $pid=NULL)
63 * 1179: function localizationRedirect($justLocalized)
64 * 1213: function getLanguages($id)
65 *
66 * SECTION: Other functions
67 * 1275: function fixWSversioningInEditConf($mapArray=FALSE)
68 * 1324: function getRecordForEdit($table,$theUid)
69 * 1358: function editRegularContentFromId()
70 * 1386: function compileStoreDat()
71 * 1399: function getNewIconMode($table,$key='saveDocNew')
72 * 1412: function closeDocument($code=0)
73 * 1444: function setDocument($currentDocFromHandlerMD5='',$retUrl='alt_doc_nodoc.php')
74 *
75 * TOTAL FUNCTIONS: 24
76 * (This index is automatically created/updated by the extension "extdeveval")
77 *
78 */
79
80
81 require('init.php');
82 require('template.php');
83 $LANG->includeLLFile('EXT:lang/locallang_alt_doc.xml');
84 require_once (PATH_t3lib.'class.t3lib_tceforms.php');
85 require_once (PATH_t3lib.'class.t3lib_clipboard.php');
86
87 require_once (PATH_t3lib.'class.t3lib_tcemain.php');
88 require_once (PATH_t3lib.'class.t3lib_loaddbgroup.php');
89 require_once (PATH_t3lib.'class.t3lib_transferdata.php');
90
91
92 t3lib_BEfunc::lockRecords();
93
94
95
96
97 /**
98 * Script Class: Drawing the editing form for editing records in TYPO3.
99 * Notice: It does NOT use tce_db.php to submit data to, rather it handles submissions itself
100 *
101 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
102 * @package TYPO3
103 * @subpackage core
104 */
105 class SC_alt_doc {
106
107 // Internal, static: GPvars:
108 var $editconf; // GPvar "edit": Is an array looking approx like [tablename][list-of-ids]=command, eg. "&edit[pages][123]=edit". See t3lib_BEfunc::editOnClick(). Value can be seen modified internally (converting NEW keyword to id, workspace/versioning etc).
109 var $columnsOnly; // Commalist of fieldnames to edit. The point is IF you specify this list, only those fields will be rendered in the form. Otherwise all (available) fields in the record is shown according to the types configuration in $TCA
110 var $defVals; // Default values for fields (array with tablenames, fields etc. as keys). Can be seen modified internally.
111 var $overrideVals; // Array of values to force being set (as hidden fields). Will be set as $this->defVals IF defVals does not exist.
112 var $returnUrl; // If set, this value will be set in $this->retUrl (which is used quite many places as the return URL). If not set, "dummy.php" will be set in $this->retUrl
113 var $closeDoc; // Close-document command. Not really sure of all options...
114 var $doSave; // Quite simply, if this variable is set, then the processing of incoming data will be performed - as if a save-button is pressed. Used in the forms as a hidden field which can be set through JavaScript if the form is somehow submitted by JavaScript).
115
116 var $data; // GPvar (for processing only) : The data array from which the data comes...
117 var $mirror; // GPvar (for processing only) : ?
118 var $cacheCmd; // GPvar (for processing only) : Clear-cache cmd.
119 var $redirect; // GPvar (for processing only) : Redirect (not used???)
120 var $disableRTE; // GPvar (for processing only) : If set, the rich text editor is disabled in the forms.
121 var $returnNewPageId; // GPvar (for processing only) : Boolean: If set, then the GET var "&id=" will be added to the retUrl string so that the NEW id of something is returned to the script calling the form.
122 var $vC; // GPvar (for processing only) : Verification code, internal stuff.
123
124 var $popViewId; // GPvar (module) : ID for displaying the page in the frontend (used for SAVE/VIEW operations)
125 var $popViewId_addParams; // GPvar (module) : Additional GET vars for the link, eg. "&L=xxx"
126 var $viewUrl; // GPvar (module) : Alternative URL for viewing the frontend pages.
127 var $editRegularContentFromId; // If this is pointing to a page id it will automatically load all content elements (NORMAL column/default language) from that page into the form!
128 var $recTitle; // Alternative title for the document handler.
129 var $disHelp; // Disable help... ?
130 var $noView; // If set, then no SAVE/VIEW button is printed
131 var $returnEditConf; // If set, the $this->editconf array is returned to the calling script (used by wizard_add.php for instance)
132 var $localizationMode; // GP var, localization mode for TCEforms (eg. "text")
133
134
135 // Internal, static:
136 var $doc; // Document template object
137 var $content; // Content accumulation
138
139 var $retUrl; // Return URL script, processed. This contains the script (if any) that we should RETURN TO from the alt_doc.php script IF we press the close button. Thus this variable is normally passed along from the calling script so we can properly return if needed.
140 var $R_URL_parts; // Contains the parts of the REQUEST_URI (current url). By parts we mean the result of resolving REQUEST_URI (current url) by the parse_url() function. The result is an array where eg. "path" is the script path and "query" is the parameters...
141 var $R_URL_getvars; // Contains the current GET vars array; More specifically this array is the foundation for creating the R_URI internal var (which becomes the "url of this script" to which we submit the forms etc.)
142 var $R_URI; // Set to the URL of this script including variables which is needed to re-display the form. See main()
143
144 var $storeTitle; // Is loaded with the "title" of the currently "open document" - this is used in the Document Selector box. (see makeDocSel())
145 var $storeArray; // Contains an array with key/value pairs of GET parameters needed to reach the current document displayed - used in the Document Selector box. (see compileStoreDat())
146 var $storeUrl; // Contains storeArray, but imploded into a GET parameter string (see compileStoreDat())
147 var $storeUrlMd5; // Hashed value of storeURL (see compileStoreDat())
148
149 var $docDat; // Module session data
150 var $docHandler; // An array of the "open documents" - keys are md5 hashes (see $storeUrlMd5) identifying the various documents on the GET parameter list needed to open it. The values are arrays with 0,1,2 keys with information about the document (see compileStoreDat()). The docHandler variable is stored in the $docDat session data, key "0".
151
152
153 // Internal: Related to the form rendering:
154 var $elementsData; // Array of the elements to create edit forms for.
155 var $firstEl; // Pointer to the first element in $elementsData
156 var $errorC; // Counter, used to count the number of errors (when users do not have edit permissions)
157 var $newC; // Counter, used to count the number of new record forms displayed
158 var $viewId; // Is set to the pid value of the last shown record - thus indicating which page to show when clicking the SAVE/VIEW button
159 var $viewId_addParams; // Is set to additional parameters (like "&L=xxx") if the record supports it.
160 var $modTSconfig; // Module TSconfig, loaded from main() based on the page id value of viewId
161 var $tceforms; // Contains the instance of TCEforms class.
162 var $generalPathOfForm; // Contains the root-line path of the currently edited record(s) - for display.
163
164
165 // Internal, dynamic:
166 var $dontStoreDocumentRef; // Used internally to disable the storage of the document reference (eg. new records)
167
168
169
170
171
172
173
174 /**
175 * First initialization.
176 *
177 * @return void
178 */
179 function preInit() {
180 global $BE_USER;
181
182 if (t3lib_div::_GP('justLocalized')) {
183 $this->localizationRedirect(t3lib_div::_GP('justLocalized'));
184 }
185
186 // Setting GPvars:
187 $this->editconf = t3lib_div::_GP('edit');
188 $this->defVals = t3lib_div::_GP('defVals');
189 $this->overrideVals = t3lib_div::_GP('overrideVals');
190 $this->columnsOnly = t3lib_div::_GP('columnsOnly');
191 $this->returnUrl = t3lib_div::_GP('returnUrl');
192 $this->closeDoc = t3lib_div::_GP('closeDoc');
193 $this->doSave = t3lib_div::_GP('doSave');
194 $this->returnEditConf = t3lib_div::_GP('returnEditConf');
195 $this->localizationMode = t3lib_div::_GP('localizationMode');
196
197
198 // Setting override values as default if defVals does not exist.
199 if (!is_array($this->defVals) && is_array($this->overrideVals)) {
200 $this->defVals = $this->overrideVals;
201 }
202
203 // Setting return URL
204 $this->retUrl = $this->returnUrl ? $this->returnUrl : 'dummy.php';
205
206 // Fix $this->editconf if versioning applies to any of the records
207 $this->fixWSversioningInEditConf();
208
209 // Make R_URL (request url) based on input GETvars:
210 $this->R_URL_parts = parse_url(t3lib_div::getIndpEnv('REQUEST_URI'));
211 $this->R_URL_getvars = t3lib_div::_GET();
212 $this->R_URL_getvars['edit'] = $this->editconf;
213
214 // MAKE url for storing
215 $this->compileStoreDat();
216
217 // Initialize more variables.
218 $this->dontStoreDocumentRef=0;
219 $this->storeTitle='';
220
221 // Get session data for the module:
222 $this->docDat = $BE_USER->getModuleData('alt_doc.php','ses');
223 $this->docHandler = $this->docDat[0];
224
225 // If a request for closing the document has been sent, act accordingly:
226 if ($this->closeDoc>0) {
227 $this->closeDocument($this->closeDoc);
228 }
229
230 // If NO vars are sent to the script, try to read first document:
231 if (is_array($this->R_URL_getvars) && count($this->R_URL_getvars)<2 && !is_array($this->editconf)) { // Added !is_array($this->editconf) because editConf must not be set either. Anyways I can't figure out when this situation here will apply...
232 $this->setDocument($this->docDat[1]);
233 }
234 }
235
236 /**
237 * Detects, if a save command has been triggered.
238 *
239 * @return boolean True, then save the document (data submitted)
240 */
241 function doProcessData() {
242 $out = $this->doSave || isset($_POST['_savedok_x']) || isset($_POST['_saveandclosedok_x']) || isset($_POST['_savedokview_x']) || isset($_POST['_savedoknew_x']);
243 return $out;
244 }
245
246 /**
247 * Do processing of data, submitting it to TCEmain.
248 *
249 * @return void
250 */
251 function processData() {
252 global $BE_USER,$TYPO3_CONF_VARS;
253
254 // GPvars specifically for processing:
255 $this->data = t3lib_div::_GP('data');
256 $this->mirror = t3lib_div::_GP('mirror');
257 $this->cacheCmd = t3lib_div::_GP('cacheCmd');
258 $this->redirect = t3lib_div::_GP('redirect');
259 $this->disableRTE = t3lib_div::_GP('_disableRTE');
260 $this->returnNewPageId = t3lib_div::_GP('returnNewPageId');
261 $this->vC = t3lib_div::_GP('vC');
262
263 // See tce_db.php for relevate options here:
264 // Only options related to $this->data submission are included here.
265 $tce = t3lib_div::makeInstance('t3lib_TCEmain');
266 $tce->stripslashes_values=0;
267
268 // Setting default values specific for the user:
269 $TCAdefaultOverride = $BE_USER->getTSConfigProp('TCAdefaults');
270 if (is_array($TCAdefaultOverride)) {
271 $tce->setDefaultsFromUserTS($TCAdefaultOverride);
272 }
273
274 // Setting internal vars:
275 if ($BE_USER->uc['neverHideAtCopy']) { $tce->neverHideAtCopy = 1; }
276 $tce->debug=0;
277 $tce->disableRTE = $this->disableRTE;
278
279 // Loading TCEmain with data:
280 $tce->start($this->data,array());
281 if (is_array($this->mirror)) { $tce->setMirror($this->mirror); }
282
283 // If pages are being edited, we set an instruction about updating the page tree after this operation.
284 if (isset($this->data['pages'])) {
285 t3lib_BEfunc::getSetUpdateSignal('updatePageTree');
286 }
287
288
289 // Checking referer / executing
290 $refInfo=parse_url(t3lib_div::getIndpEnv('HTTP_REFERER'));
291 $httpHost = t3lib_div::getIndpEnv('TYPO3_HOST_ONLY');
292 if ($httpHost!=$refInfo['host'] && $this->vC!=$BE_USER->veriCode() && !$TYPO3_CONF_VARS['SYS']['doNotCheckReferer']) {
293 $tce->log('',0,0,0,1,"Referer host '%s' and server host '%s' did not match and veriCode was not valid either!",1,array($refInfo['host'],$httpHost));
294 debug('Error: Referer host did not match with server host.');
295 } else {
296
297 // Perform the saving operation with TCEmain:
298 $tce->process_uploads($_FILES);
299 $tce->process_datamap();
300
301 // If there was saved any new items, load them:
302 if (count($tce->substNEWwithIDs_table)) {
303
304 // Resetting editconf:
305 $this->editconf = array();
306
307 // Traverse all new records and forge the content of ->editconf so we can continue to EDIT these records!
308 foreach($tce->substNEWwithIDs_table as $nKey => $nTable) {
309 $editId = $tce->substNEWwithIDs[$nKey];
310 // translate new id to the workspace version:
311 if ($versionRec = t3lib_BEfunc::getWorkspaceVersionOfRecord($GLOBALS['BE_USER']->workspace, $nTable, $editId,'uid')) {
312 $editId = $versionRec['uid'];
313 }
314
315 $this->editconf[$nTable][$editId]='edit';
316 if ($nTable=='pages' && $this->retUrl!='dummy.php' && $this->returnNewPageId) {
317 $this->retUrl.='&id='.$tce->substNEWwithIDs[$nKey];
318 }
319 }
320
321 // Finally, set the editconf array in the "getvars" so they will be passed along in URLs as needed.
322 $this->R_URL_getvars['edit']=$this->editconf;
323
324 // Unsetting default values since we don't need them anymore.
325 unset($this->R_URL_getvars['defVals']);
326
327 // Re-compile the store* values since editconf changed...
328 $this->compileStoreDat();
329 }
330
331 // See if any records was auto-created as new versions?
332 if (count($tce->autoVersionIdMap)) {
333 $this->fixWSversioningInEditConf($tce->autoVersionIdMap);
334 }
335
336 // If a document is saved and a new one is created right after.
337 if (isset($_POST['_savedoknew_x']) && is_array($this->editconf)) {
338
339 // Finding the current table:
340 reset($this->editconf);
341 $nTable=key($this->editconf);
342
343 // Finding the first id, getting the records pid+uid
344 reset($this->editconf[$nTable]);
345 $nUid=key($this->editconf[$nTable]);
346 $nRec = t3lib_BEfunc::getRecord($nTable,$nUid,'pid,uid');
347
348 // Setting a blank editconf array for a new record:
349 $this->editconf=array();
350 if ($this->getNewIconMode($nTable)=='top') {
351 $this->editconf[$nTable][$nRec['pid']]='new';
352 } else {
353 $this->editconf[$nTable][-$nRec['uid']]='new';
354 }
355
356 // Finally, set the editconf array in the "getvars" so they will be passed along in URLs as needed.
357 $this->R_URL_getvars['edit']=$this->editconf;
358
359 // Re-compile the store* values since editconf changed...
360 $this->compileStoreDat();
361 }
362
363 $tce->printLogErrorMessages(
364 isset($_POST['_saveandclosedok_x']) ?
365 $this->retUrl :
366 $this->R_URL_parts['path'].'?'.t3lib_div::implodeArrayForUrl('',$this->R_URL_getvars) // popView will not be invoked here, because the information from the submit button for save/view will be lost .... But does it matter if there is an error anyways?
367 );
368 }
369 if (isset($_POST['_saveandclosedok_x']) || $this->closeDoc<0) { // || count($tce->substNEWwithIDs)... If any new items has been save, the document is CLOSED because if not, we just get that element re-listed as new. And we don't want that!
370 $this->closeDocument(abs($this->closeDoc));
371 }
372 }
373
374 /**
375 * Initialize the normal module operation
376 *
377 * @return void
378 */
379 function init() {
380 global $BE_USER,$LANG,$BACK_PATH;
381
382 // Setting more GPvars:
383 $this->popViewId = t3lib_div::_GP('popViewId');
384 $this->popViewId_addParams = t3lib_div::_GP('popViewId_addParams');
385 $this->viewUrl = t3lib_div::_GP('viewUrl');
386 $this->editRegularContentFromId = t3lib_div::_GP('editRegularContentFromId');
387 $this->recTitle = t3lib_div::_GP('recTitle');
388 $this->disHelp = t3lib_div::_GP('disHelp');
389 $this->noView = t3lib_div::_GP('noView');
390
391 // Set other internal variables:
392 $this->R_URL_getvars['returnUrl']=$this->retUrl;
393 $this->R_URI = $this->R_URL_parts['path'].'?'.t3lib_div::implodeArrayForUrl('',$this->R_URL_getvars);
394
395 // MENU-ITEMS:
396 // If array, then it's a selector box menu
397 // If empty string it's just a variable, that'll be saved.
398 // Values NOT in this array will not be saved in the settings-array for the module.
399 $this->MOD_MENU = array(
400 'showPalettes' => '',
401 'showDescriptions' => '',
402 'disableRTE' => ''
403 );
404
405 // Setting virtual document name
406 $this->MCONF['name']='xMOD_alt_doc.php';
407
408 // CLEANSE SETTINGS
409 $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name']);
410
411 // Create an instance of the document template object
412 $this->doc = t3lib_div::makeInstance('mediumDoc');
413 $this->doc->bodyTagMargins['x']=5;
414 $this->doc->bodyTagMargins['y']=5;
415 $this->doc->backPath = $BACK_PATH;
416 $this->doc->docType = 'xhtml_trans';
417
418 $this->doc->form='<form action="'.htmlspecialchars($this->R_URI).'" method="post" enctype="'.$GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'].'" name="editform" onsubmit="return TBE_EDITOR_checkSubmit(1);">';
419
420 $this->doc->JScode = $this->doc->wrapScriptTags('
421 function jumpToUrl(URL,formEl) { //
422 if (!TBE_EDITOR_isFormChanged()) {
423 window.location.href = URL;
424 } else if (formEl && formEl.type=="checkbox") {
425 formEl.checked = formEl.checked ? 0 : 1;
426 }
427 }
428
429 // Object: TS:
430 function typoSetup () { //
431 this.uniqueID = "";
432 }
433 var TS = new typoSetup();
434
435 // Info view:
436 function launchView(table,uid,bP) { //
437 var backPath= bP ? bP : "";
438 var thePreviewWindow="";
439 thePreviewWindow = window.open(backPath+"show_item.php?table="+escape(table)+"&uid="+escape(uid),"ShowItem"+TS.uniqueID,"height=300,width=410,status=0,menubar=0,resizable=0,location=0,directories=0,scrollbars=1,toolbar=0");
440 if (thePreviewWindow && thePreviewWindow.focus) {
441 thePreviewWindow.focus();
442 }
443 }
444 function deleteRecord(table,id,url) { //
445 if (
446 '.($GLOBALS['BE_USER']->jsConfirmation(4)?'confirm('.$LANG->JScharCode($LANG->getLL('deleteWarning')).')':'1==1').'
447 ) {
448 window.location.href = "tce_db.php?cmd["+table+"]["+id+"][delete]=1&redirect="+escape(url)+"&vC='.$BE_USER->veriCode().'&prErr=1&uPT=1";
449 }
450 return false;
451 }
452 '.(isset($_POST['_savedokview_x']) && $this->popViewId ?
453 'if (window.opener) { '.
454 t3lib_BEfunc::viewOnClick($this->popViewId,'',t3lib_BEfunc::BEgetRootLine($this->popViewId),'',$this->viewUrl,$this->popViewId_addParams,FALSE).
455 ' } else { '.
456 t3lib_BEfunc::viewOnClick($this->popViewId,'',t3lib_BEfunc::BEgetRootLine($this->popViewId),'',$this->viewUrl,$this->popViewId_addParams).
457 ' } '
458 : '')
459 ).$this->doc->getDynTabMenuJScode();
460
461 // Setting up the context sensitive menu:
462 $CMparts = $this->doc->getContextMenuCode();
463 $this->doc->JScode.= $CMparts[0];
464 $this->doc->bodyTagAdditions = $CMparts[1];
465 $this->doc->postCode.= $CMparts[2];
466 }
467
468 /**
469 * Main module operation
470 *
471 * @return void
472 */
473 function main() {
474 global $BE_USER,$LANG;
475
476 // Starting content accumulation:
477 $this->content='';
478 $this->content.=$this->doc->startPage('TYPO3 Edit Document');
479
480 // Begin edit:
481 if (is_array($this->editconf)) {
482
483 // Initialize TCEforms (rendering the forms)
484 $this->tceforms = t3lib_div::makeInstance('t3lib_TCEforms');
485 $this->tceforms->initDefaultBEMode();
486 $this->tceforms->doSaveFieldName = 'doSave';
487 $this->tceforms->localizationMode = t3lib_div::inList('text,media',$this->localizationMode) ? $this->localizationMode : ''; // text,media is keywords defined in TYPO3 Core API..., see "l10n_cat"
488 $this->tceforms->returnUrl = $this->R_URI;
489 $this->tceforms->palettesCollapsed = !$this->MOD_SETTINGS['showPalettes'];
490 $this->tceforms->disableRTE = $this->MOD_SETTINGS['disableRTE'];
491 $this->tceforms->enableClickMenu = TRUE;
492 $this->tceforms->enableTabMenu = TRUE;
493
494 // Clipboard is initialized:
495 $this->tceforms->clipObj = t3lib_div::makeInstance('t3lib_clipboard'); // Start clipboard
496 $this->tceforms->clipObj->initializeClipboard(); // Initialize - reads the clipboard content from the user session
497
498 // Setting external variables:
499 if ($BE_USER->uc['edit_showFieldHelp']!='text' && $this->MOD_SETTINGS['showDescriptions']) $this->tceforms->edit_showFieldHelp='text';
500
501 if ($this->editRegularContentFromId) {
502 $this->editRegularContentFromId();
503 }
504
505 // Creating the editing form, wrap it with buttons, document selector etc.
506 $editForm = $this->makeEditForm();
507
508 if ($editForm) {
509 reset($this->elementsData);
510 $this->firstEl = current($this->elementsData);
511
512 // language switch/selector for editing
513 // show only when a single record is edited - multiple records are too confusing
514 if (count($this->elementsData)==1) {
515 $languageSwitch = $this->languageSwitch($this->firstEl['table'], $this->firstEl['uid'], $this->firstEl['pid']);
516 }
517
518
519 if ($this->viewId) {
520 // Module configuration:
521 $this->modTSconfig = t3lib_BEfunc::getModTSconfig($this->viewId,'mod.xMOD_alt_doc');
522 } else $this->modTSconfig=array();
523
524 $panel = $this->makeButtonPanel();
525 $docSel = $this->makeDocSel();
526 $cMenu = $this->makeCmenu();
527
528 $formContent = $this->compileForm($panel,$docSel,$cMenu,$editForm,$languageSwitch);
529
530 $this->content.= $this->tceforms->printNeededJSFunctions_top().
531 $formContent.
532 $this->tceforms->printNeededJSFunctions();
533 $this->content.= $this->functionMenus();
534
535 // Add CSH:
536 $this->content.= t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'TCEforms', $GLOBALS['BACK_PATH'],'<br/>|',FALSE,'margin-top: 20px;');
537
538 $this->content.= $this->shortCutLink();
539
540 $this->tceformMessages();
541 }
542 }
543 }
544
545
546 /**
547 * Outputting the accumulated content to screen
548 *
549 * @return void
550 */
551 function printContent() {
552 $this->content.= $this->doc->endPage();
553 $this->content = $this->doc->insertStylesAndJS($this->content);
554 echo $this->content;
555 }
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576 /***************************
577 *
578 * Sub-content functions, rendering specific parts of the module content.
579 *
580 ***************************/
581
582 /**
583 * Creates the editing form with TCEforms, based on the input from GPvars.
584 *
585 * @return string HTML form elements wrapped in tables
586 */
587 function makeEditForm() {
588 global $BE_USER,$LANG,$TCA;
589
590 // Initialize variables:
591 $this->elementsData=array();
592 $this->errorC=0;
593 $this->newC=0;
594 $thePrevUid='';
595 $editForm='';
596
597 // Traverse the GPvar edit array
598 foreach($this->editconf as $table => $conf) { // Tables:
599 if (is_array($conf) && $TCA[$table] && $BE_USER->check('tables_modify',$table)) {
600
601 // Traverse the keys/comments of each table (keys can be a commalist of uids)
602 foreach($conf as $cKey => $cmd) {
603 if ($cmd=='edit' || $cmd=='new') {
604
605 // Get the ids:
606 $ids = t3lib_div::trimExplode(',',$cKey,1);
607
608 // Traverse the ids:
609 foreach($ids as $theUid) {
610
611 // Checking if the user has permissions? (Only working as a precaution, because the final permission check is always down in TCE. But it's good to notify the user on beforehand...)
612 // First, resetting flags.
613 $hasAccess = 1;
614 $deniedAccessReason = '';
615 $deleteAccess = 0;
616 $this->viewId = 0;
617
618 // If the command is to create a NEW record...:
619 if ($cmd=='new') {
620 if (intval($theUid)) { // NOTICE: the id values in this case points to the page uid onto which the record should be create OR (if the id is negativ) to a record from the same table AFTER which to create the record.
621
622 // Find parent page on which the new record reside
623 if ($theUid<0) { // Less than zero - find parent page
624 $calcPRec=t3lib_BEfunc::getRecord($table,abs($theUid));
625 $calcPRec=t3lib_BEfunc::getRecord('pages',$calcPRec['pid']);
626 } else { // always a page
627 $calcPRec=t3lib_BEfunc::getRecord('pages',abs($theUid));
628 }
629
630 // Now, calculate whether the user has access to creating new records on this position:
631 if (is_array($calcPRec)) {
632 $CALC_PERMS = $BE_USER->calcPerms($calcPRec); // Permissions for the parent page
633 if ($table=='pages') { // If pages:
634 $hasAccess = $CALC_PERMS&8 ? 1 : 0;
635 $this->viewId = $calcPRec['pid'];
636 } else {
637 $hasAccess = $CALC_PERMS&16 ? 1 : 0;
638 $this->viewId = $calcPRec['uid'];
639 }
640 }
641 }
642 $this->dontStoreDocumentRef=1; // Don't save this document title in the document selector if the document is new.
643 } else { // Edit:
644 $calcPRec = t3lib_BEfunc::getRecord($table,$theUid);
645 t3lib_BEfunc::fixVersioningPid($table,$calcPRec);
646 if (is_array($calcPRec)) {
647 if ($table=='pages') { // If pages:
648 $CALC_PERMS = $BE_USER->calcPerms($calcPRec);
649 $hasAccess = $CALC_PERMS&2 ? 1 : 0;
650 $deleteAccess = $CALC_PERMS&4 ? 1 : 0;
651 $this->viewId = $calcPRec['uid'];
652 } else {
653 $CALC_PERMS = $BE_USER->calcPerms(t3lib_BEfunc::getRecord('pages',$calcPRec['pid'])); // Fetching pid-record first.
654 $hasAccess = $CALC_PERMS&16 ? 1 : 0;
655 $deleteAccess = $CALC_PERMS&16 ? 1 : 0;
656 $this->viewId = $calcPRec['pid'];
657
658 // Adding "&L=xx" if the record being edited has a languageField with a value larger than zero!
659 if ($TCA[$table]['ctrl']['languageField'] && $calcPRec[$TCA[$table]['ctrl']['languageField']]>0) {
660 $this->viewId_addParams = '&L='.$calcPRec[$TCA[$table]['ctrl']['languageField']];
661 }
662 }
663
664 // Check internals regarding access:
665 if ($hasAccess) {
666 $hasAccess = $BE_USER->recordEditAccessInternals($table, $calcPRec);
667 $deniedAccessReason = $BE_USER->errorMsg;
668 }
669 } else $hasAccess = 0;
670 }
671
672 // AT THIS POINT we have checked the access status of the editing/creation of records and we can now proceed with creating the form elements:
673
674 if ($hasAccess) {
675 $prevPageID = is_object($trData)?$trData->prevPageID:'';
676 $trData = t3lib_div::makeInstance('t3lib_transferData');
677 $trData->addRawData = TRUE;
678 $trData->defVals = $this->defVals;
679 $trData->lockRecords=1;
680 $trData->disableRTE = $this->MOD_SETTINGS['disableRTE'];
681 $trData->prevPageID = $prevPageID;
682 $trData->fetchRecord($table,$theUid,$cmd=='new'?'new':''); // 'new'
683 reset($trData->regTableItems_data);
684 $rec = current($trData->regTableItems_data);
685 $rec['uid'] = $cmd=='new' ? uniqid('NEW') : $theUid;
686 if ($cmd=='new') {
687 $rec['pid'] = $theUid=='prev'?$thePrevUid:$theUid;
688 }
689 $this->elementsData[]=array(
690 'table' => $table,
691 'uid' => $rec['uid'],
692 'pid' => $rec['pid'],
693 'cmd' => $cmd,
694 'deleteAccess' => $deleteAccess
695 );
696
697 // Now, render the form:
698 if (is_array($rec)) {
699
700 // Setting visual path / title of form:
701 $this->generalPathOfForm = $this->tceforms->getRecordPath($table,$rec);
702 if (!$this->storeTitle) {
703 $this->storeTitle = $this->recTitle ? htmlspecialchars($this->recTitle) : t3lib_BEfunc::getRecordTitle($table,$rec,1);
704 }
705
706 // Setting variables in TCEforms object:
707 $this->tceforms->hiddenFieldList = '';
708 $this->tceforms->globalShowHelp = $this->disHelp ? 0 : 1;
709 if (is_array($this->overrideVals[$table])) {
710 $this->tceforms->hiddenFieldListArr = array_keys($this->overrideVals[$table]);
711 }
712
713 // Register default language labels, if any:
714 $this->tceforms->registerDefaultLanguageData($table,$rec);
715
716 // Create form for the record (either specific list of fields or the whole record):
717 $panel = '';
718 if ($this->columnsOnly) {
719 if(is_array($this->columnsOnly)){
720 $panel.= $this->tceforms->getListedFields($table,$rec,$this->columnsOnly[$table]);
721 } else {
722 $panel.= $this->tceforms->getListedFields($table,$rec,$this->columnsOnly);
723 }
724 } else {
725 $panel.= $this->tceforms->getMainFields($table,$rec);
726 }
727 $panel = $this->tceforms->wrapTotal($panel,$rec,$table);
728
729 // Setting the pid value for new records:
730 if ($cmd=='new') {
731 $panel.= '<input type="hidden" name="data['.$table.']['.$rec['uid'].'][pid]" value="'.$rec['pid'].'" />';
732 $this->newC++;
733 }
734
735 // Display "is-locked" message:
736 if ($lockInfo = t3lib_BEfunc::isRecordLocked($table,$rec['uid'])) {
737 $lockIcon = '
738
739 <!--
740 Warning box:
741 -->
742 <table border="0" cellpadding="0" cellspacing="0" class="warningbox">
743 <tr>
744 <td><img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/recordlock_warning3.gif','width="17" height="12"').' alt="" /></td>
745 <td>'.htmlspecialchars($lockInfo['msg']).'</td>
746 </tr>
747 </table>
748 ';
749 } else $lockIcon = '';
750
751 // Combine it all:
752 $editForm.= $lockIcon.$panel;
753 }
754
755 $thePrevUid = $rec['uid'];
756 } else {
757 $this->errorC++;
758 $editForm.=$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.noEditPermission',1).'<br /><br />'.
759 ($deniedAccessReason ? 'Reason: '.htmlspecialchars($deniedAccessReason).'<br/><br/>' : '');
760 }
761 }
762 }
763 }
764 }
765 }
766
767 return $editForm;
768 }
769
770 /**
771 * Create the panel of buttons for submitting the form or otherwise perform operations.
772 *
773 * @return string HTML code, comprised of images linked to various actions.
774 */
775 function makeButtonPanel() {
776 global $TCA,$LANG;
777
778 $panel='';
779
780 // Render SAVE type buttons:
781 // The action of each button is decided by its name attribute. (See doProcessData())
782 if (!$this->errorC && !$TCA[$this->firstEl['table']]['ctrl']['readOnly']) {
783
784 // SAVE button:
785 $panel.= '<input type="image" class="c-inputButton" name="_savedok"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/savedok.gif','').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:rm.saveDoc',1).'" />';
786
787 // SAVE / VIEW button:
788 if ($this->viewId && !$this->noView && t3lib_extMgm::isLoaded('cms')) {
789 $panel.= '<input type="image" class="c-inputButton" name="_savedokview"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/savedokshow.gif','').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:rm.saveDocShow',1).'" />';
790 }
791
792 // SAVE / NEW button:
793 if (count($this->elementsData)==1 && $this->getNewIconMode($this->firstEl['table'])) {
794 $panel.= '<input type="image" class="c-inputButton" name="_savedoknew"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/savedoknew.gif','').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:rm.saveNewDoc',1).'" />';
795 }
796
797 // SAVE / CLOSE
798 $panel.= '<input type="image" class="c-inputButton" name="_saveandclosedok"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/saveandclosedok.gif','').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:rm.saveCloseDoc',1).'" />';
799 }
800
801 // CLOSE button:
802 $panel.= '<a href="#" onclick="document.editform.closeDoc.value=1; document.editform.submit(); return false;">'.
803 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/closedok.gif','width="21" height="16"').' class="c-inputButton" title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:rm.closeDoc',1).'" alt="" />'.
804 '</a>';
805
806 // DELETE + UNDO buttons:
807 if (!$this->errorC && !$TCA[$this->firstEl['table']]['ctrl']['readOnly'] && count($this->elementsData)==1) {
808 if ($this->firstEl['cmd']!='new' && t3lib_div::testInt($this->firstEl['uid'])) {
809
810 // Delete:
811 if ($this->firstEl['deleteAccess'] && !$TCA[$this->firstEl['table']]['ctrl']['readOnly'] && !$this->getNewIconMode($this->firstEl['table'],'disableDelete')) {
812 $aOnClick = 'return deleteRecord(\''.$this->firstEl['table'].'\',\''.$this->firstEl['uid'].'\',unescape(\''.rawurlencode($this->retUrl).'\'));';
813 $panel.= '<a href="#" onclick="'.htmlspecialchars($aOnClick).'">'.
814 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/deletedok.gif','width="21" height="16"').' class="c-inputButton" title="'.$LANG->getLL('deleteItem',1).'" alt="" />'.
815 '</a>';
816 }
817
818 // Undo:
819 $undoButton = 0;
820 $undoRes = $GLOBALS['TYPO3_DB']->exec_SELECTquery('tstamp', 'sys_history', 'tablename='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->firstEl['table'], 'sys_history').' AND recuid='.intval($this->firstEl['uid']), '', 'tstamp DESC', '1');
821 if ($undoButtonR = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($undoRes)) {
822 $undoButton = 1;
823 }
824 if ($undoButton) {
825 $aOnClick = 'window.location.href=\'show_rechis.php?element='.rawurlencode($this->firstEl['table'].':'.$this->firstEl['uid']).'&revert=ALL_FIELDS&sumUp=-1&returnUrl='.rawurlencode($this->R_URI).'\'; return false;';
826 $panel.= '<a href="#" onclick="'.htmlspecialchars($aOnClick).'">'.
827 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/undo.gif','width="21" height="16"').' class="c-inputButton" title="'.htmlspecialchars(sprintf($LANG->getLL('undoLastChange'),t3lib_BEfunc::calcAge(time()-$undoButtonR['tstamp'],$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.minutesHoursDaysYears')))).'" alt="" />'.
828 '</a>';
829 }
830 if ($this->getNewIconMode($this->firstEl['table'],'showHistory')) {
831 $aOnClick = 'window.location.href=\'show_rechis.php?element='.rawurlencode($this->firstEl['table'].':'.$this->firstEl['uid']).'&returnUrl='.rawurlencode($this->R_URI).'\'; return false;';
832 $panel.= '<a href="#" onclick="'.htmlspecialchars($aOnClick).'">'.
833 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/history2.gif','width="13" height="12"').' class="c-inputButton" alt="" />'.
834 '</a>';
835 }
836
837 // If only SOME fields are shown in the form, this will link the user to the FULL form:
838 if ($this->columnsOnly) {
839 $panel.= '<a href="'.htmlspecialchars($this->R_URI.'&columnsOnly=').'">'.
840 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/edit2.gif','width="11" height="12"').' class="c-inputButton" title="'.$LANG->getLL('editWholeRecord',1).'" alt="" />'.
841 '</a>';
842 }
843 }
844 }
845 return $panel;
846 }
847
848 /**
849 * Create the selector box form element which allows to select between open documents.
850 * Can be disabled through Page TSconfig.
851 *
852 * @return string HTML <select> element (if applicable)
853 */
854 function makeDocSel() {
855 global $BE_USER,$LANG;
856
857 // Render the selector ONLY if it has not been disabled:
858 if (!$this->modTSconfig['properties']['disableDocSelector']) {
859
860 // Checking if the currently open document is stored in the list of "open documents" - if not, then add it:
861 if ((strcmp($this->docDat[1],$this->storeUrlMd5)||!isset($this->docHandler[$this->storeUrlMd5])) && !$this->dontStoreDocumentRef) {
862 $this->docHandler[$this->storeUrlMd5]=array($this->storeTitle,$this->storeArray,$this->storeUrl);
863 $BE_USER->pushModuleData('alt_doc.php',array($this->docHandler,$this->storeUrlMd5));
864 }
865
866 // Now, create the document selector box:
867 $docSel='';
868 if (is_array($this->docHandler)) {
869 $opt = array();
870 $opt[] = '<option>[ '.$LANG->getLL('openDocs',1).': ]</option>';
871
872 // Traverse the list of open documents:
873 foreach($this->docHandler as $md5k => $setupArr) {
874 $theValue = 'alt_doc.php?'.$setupArr[2].'&returnUrl='.rawurlencode($this->retUrl);
875 $opt[]='<option value="'.htmlspecialchars($theValue).'"'.(!strcmp($md5k,$this->storeUrlMd5)?' selected="selected"':'').'>'.htmlspecialchars(strip_tags(t3lib_div::htmlspecialchars_decode($setupArr[0]))).'</option>';
876 }
877
878 // Compile the selector box finally:
879 $onChange = 'if(this.options[this.selectedIndex].value && !TBE_EDITOR_isFormChanged()){window.location.href=(this.options[this.selectedIndex].value);}';
880 $docSel='<select name="_docSelector" onchange="'.htmlspecialchars($onChange).'">'.implode('',$opt).'</select>';
881
882 // Add CSH:
883 $docSel.=t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'TCEforms_docSelector', $GLOBALS['BACK_PATH'],'', TRUE);
884 }
885 } else $docSel='';
886 return $docSel;
887 }
888
889 /**
890 * Create the selector box form element which allows to select a clear-cache operation.
891 * Can be disabled through Page TSconfig.
892 *
893 * @return string HTML <select> element (if applicable)
894 * @see template::clearCacheMenu()
895 */
896 function makeCmenu() {
897
898 // Generate the menu if NOT disabled:
899 if (!$this->modTSconfig['properties']['disableCacheSelector']) {
900 $cMenu = $this->doc->clearCacheMenu(intval($this->viewId),!$this->modTSconfig['properties']['disableDocSelector']);
901
902 // Add CSH:
903 $cMenu.=t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'TCEforms_cacheSelector', $GLOBALS['BACK_PATH'],'', TRUE);
904 } else $cMenu ='';
905 return $cMenu;
906 }
907
908 /**
909 * Put together the various elements (buttons, selectors, form) into a table
910 *
911 * @param string The button panel HTML
912 * @param string Document selector HTML
913 * @param string Clear-cache menu HTML
914 * @param string HTML form.
915 * @param string Language selector HTML for localization
916 * @return string Composite HTML
917 */
918 function compileForm($panel,$docSel,$cMenu,$editForm, $langSelector='') {
919 global $LANG;
920
921
922 $formContent='';
923 $formContent.='
924
925 <!--
926 Header of the editing page.
927 Contains the buttons for saving/closing, the document selector and menu selector.
928 Shows the path of the editing operation as well.
929 -->
930 <table border="0" cellpadding="0" cellspacing="1" width="470" id="typo3-altdoc-header">
931 <tr>
932 <td nowrap="nowrap" valign="top">'.$panel.'</td>
933 <td nowrap="nowrap" valign="top" align="right">'.$docSel.$cMenu.'</td>
934 </tr>';
935
936 if ($langSelector) {
937 $langSelector ='<div id="typo3-altdoc-lang-selector">'.$langSelector.'</div>';
938 }
939 $pagePath = '<div id="typo3-altdoc-page-path">'.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.path',1).': '.htmlspecialchars($this->generalPathOfForm).'</div>';
940
941 $formContent.='
942 <tr>
943 <td colspan="2"><div id="typo3-altdoc-header-info-options">'.$pagePath.$langSelector.'<div></td>
944 </tr>
945 </table>
946
947
948
949
950 <!--
951 EDITING FORM:
952 -->
953
954 '.$editForm.'
955
956
957
958 <!--
959 Saving buttons (same as in top)
960 -->
961
962 '.$panel.
963 '<input type="hidden" name="returnUrl" value="'.htmlspecialchars($this->retUrl).'" />
964 <input type="hidden" name="viewUrl" value="'.htmlspecialchars($this->viewUrl).'" />';
965
966 if ($this->returnNewPageId) {
967 $formContent.='<input type="hidden" name="returnNewPageId" value="1" />';
968 }
969 $formContent.='<input type="hidden" name="popViewId" value="'.htmlspecialchars($this->viewId).'" />';
970 if ($this->viewId_addParams) {
971 $formContent.='<input type="hidden" name="popViewId_addParams" value="'.htmlspecialchars($this->viewId_addParams).'" />';
972 }
973 $formContent.='<input type="hidden" name="closeDoc" value="0" />';
974 $formContent.='<input type="hidden" name="doSave" value="0" />';
975 $formContent.='<input type="hidden" name="_serialNumber" value="'.md5(microtime()).'" />';
976 $formContent.='<input type="hidden" name="_disableRTE" value="'.$this->tceforms->disableRTE.'" />';
977
978 return $formContent;
979 }
980
981 /**
982 * Create the checkbox buttons in the bottom of the pages.
983 *
984 * @return string HTML for function menus.
985 */
986 function functionMenus() {
987 global $BE_USER,$LANG;
988
989 $funcMenus = '';
990
991 // Show palettes:
992 $funcMenus.= '<br /><br />'.t3lib_BEfunc::getFuncCheck('','SET[showPalettes]',$this->MOD_SETTINGS['showPalettes'],'alt_doc.php',t3lib_div::implodeArrayForUrl('',array_merge($this->R_URL_getvars,array('SET'=>'')))).$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.showPalettes',1);
993
994 // Show descriptions/help texts:
995 if ($BE_USER->uc['edit_showFieldHelp']!='text') {
996 $funcMenus.= '<br />'.t3lib_BEfunc::getFuncCheck('','SET[showDescriptions]',$this->MOD_SETTINGS['showDescriptions'],'alt_doc.php',t3lib_div::implodeArrayForUrl('',array_merge($this->R_URL_getvars,array('SET'=>'')))).$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.showDescriptions',1);
997 }
998
999 // Show disable RTE checkbox:
1000 if ($BE_USER->isRTE()) {
1001 $funcMenus.= '<br />'.t3lib_BEfunc::getFuncCheck('','SET[disableRTE]',$this->MOD_SETTINGS['disableRTE'],'alt_doc.php',t3lib_div::implodeArrayForUrl('',array_merge($this->R_URL_getvars,array('SET'=>'')))).$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.disableRTE',1);
1002 }
1003
1004 return '
1005
1006 <!--
1007 Function menus (checkboxes for selecting options):
1008 -->
1009 '.$funcMenus;
1010 }
1011
1012 /**
1013 * Create shortcut and open-in-window link in the bottom of the page
1014 *
1015 * @return string
1016 */
1017 function shortCutLink() {
1018 global $BE_USER,$LANG;
1019
1020 // ShortCut
1021 if ($this->returnUrl!='close.html') {
1022 $content.='<br /><br />';
1023
1024 // Shortcut:
1025 if ($BE_USER->mayMakeShortcut()) {
1026 $content.=$this->doc->makeShortcutIcon('returnUrl,edit,defVals,overrideVals,columnsOnly,returnNewPageId,editRegularContentFromId,disHelp,noView',implode(',',array_keys($this->MOD_MENU)),$this->MCONF['name'],1);
1027 }
1028
1029 // Open in new window:
1030 $aOnClick = 'vHWin=window.open(\''.t3lib_div::linkThisScript(array('returnUrl'=>'close.html')).'\',\''.md5($this->R_URI).'\',\''.($BE_USER->uc['edit_wideDocument']?'width=670,height=500':'width=600,height=400').',status=0,menubar=0,scrollbars=1,resizable=1\');vHWin.focus();return false;';
1031 $content.='<a href="#" onclick="'.htmlspecialchars($aOnClick).'">'.
1032 '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/open_in_new_window.gif','width="19" height="14"').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.openInNewWindow',1).'" alt="" />'.
1033 '</a>';
1034 }
1035 return '
1036
1037 <!--
1038 Shortcut link:
1039 -->
1040 '.$content;
1041 }
1042
1043 /**
1044 * Reads comment messages from TCEforms and prints them in a HTML comment in the buttom of the page.
1045 *
1046 * @return void
1047 */
1048 function tceformMessages() {
1049 if (count($this->tceforms->commentMessages)) {
1050 $this->content.='
1051
1052 <!-- TCEFORM messages
1053 '.htmlspecialchars(implode(chr(10),$this->tceforms->commentMessages)).'
1054 -->
1055
1056 ';
1057 }
1058 }
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072 /***************************
1073 *
1074 * Localization stuff
1075 *
1076 ***************************/
1077
1078 /**
1079 * Make selector box for creating new translation for a record or switching to edit the record in an existing language.
1080 * Displays only languages which are available for the current page.
1081 *
1082 * @param string Table name
1083 * @param integer uid for which to create a new language
1084 * @param integer pid of the record
1085 * @return string <select> HTML element (if there were items for the box anyways...)
1086 */
1087 function languageSwitch($table, $uid, $pid=NULL) {
1088 global $TCA;
1089
1090 $content = '';
1091
1092 $languageField = $TCA[$table]['ctrl']['languageField'];
1093 $transOrigPointerField = $TCA[$table]['ctrl']['transOrigPointerField'];
1094
1095 // table editable and activated for languages?
1096 if ($GLOBALS['BE_USER']->check('tables_modify',$table) && $languageField && $transOrigPointerField && !$TCA[$table]['ctrl']['transOrigPointerTable']) {
1097
1098 if(is_null($pid)) {
1099 $row = t3lib_befunc::getRecord($table, $uid, 'pid');
1100 $pid = $row['pid'];
1101 }
1102
1103 // get all avalibale languages for the page
1104 $langRows = $this->getLanguages($pid);
1105
1106 // page available in other languages than default language?
1107 if (is_array($langRows) && count($langRows)>1) {
1108
1109 $rowsByLang = array();
1110 $fetchFields = 'uid,'.$languageField.','.$transOrigPointerField;
1111
1112 // get record in current language
1113 $rowCurrent = t3lib_befunc::getRecord($table, $uid, $fetchFields);
1114 $currentLanguage = $rowCurrent[$languageField];
1115
1116 if ($currentLanguage>-1) { // Disabled for records with [all] language!
1117 // get record in default language if needed
1118 if ($currentLanguage) {
1119 $rowsByLang[0] = t3lib_befunc::getRecord($table, $rowCurrent[$transOrigPointerField], $fetchFields);
1120 } else {
1121 $rowsByLang[0] = $rowCurrent;
1122 }
1123
1124 // get record in other languages to see what's already available
1125 $translations = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1126 $fetchFields,
1127 $table,
1128 'pid='.intval($pid).
1129 ' AND '.$languageField.'>0'.
1130 ' AND '.$transOrigPointerField.'='.intval($rowsByLang[0]['uid']).
1131 t3lib_BEfunc::deleteClause($table).
1132 t3lib_BEfunc::versioningPlaceholderClause($table)
1133 );
1134 foreach ($translations as $row) {
1135 $rowsByLang[$row[$languageField]] = $row;
1136 }
1137
1138 $langSelItems=array();
1139 foreach ($langRows as $lang) {
1140 if ($GLOBALS['BE_USER']->checkLanguageAccess($lang['uid'])) {
1141
1142 $newTranslation = isset($rowsByLang[$lang['uid']]) ? '' : ' ['.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:labels.new',1).']';
1143
1144 // create url for creating a localized record
1145 if($newTranslation) {
1146 $href = $this->doc->issueCommand(
1147 '&cmd['.$table.']['.$rowsByLang[0]['uid'].'][localize]='.$lang['uid'],
1148 $this->backPath.'alt_doc.php?justLocalized='.rawurlencode($table.':'.$rowsByLang[0]['uid'].':'.$lang['uid']).'&returnUrl='.rawurlencode($this->retUrl)
1149 );
1150
1151 // create edit url
1152 } else {
1153 $href = $this->backPath.'alt_doc.php?';
1154 $href .= '&edit['.$table.']['.$rowsByLang[$lang['uid']]['uid'].']=edit';
1155 $href .= '&returnUrl='.rawurlencode($this->retUrl);
1156 }
1157
1158 $langSelItems[$lang['uid']]='
1159 <option value="'.htmlspecialchars($href).'"'.($currentLanguage==$lang['uid']?' selected="selected"':'').'>'.htmlspecialchars($lang['title'].$newTranslation).'</option>';
1160 }
1161 }
1162
1163 // If any languages are left, make selector:
1164 if (count($langSelItems)>1) {
1165 $onChange = 'if(this.options[this.selectedIndex].value){window.location.href=(this.options[this.selectedIndex].value);}';
1166 $content = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_general.xml:LGL.language',1).' <select name="_langSelector" onchange="'.htmlspecialchars($onChange).'">
1167 '.implode('',$langSelItems).'
1168 </select>';
1169 }
1170 }
1171 }
1172 }
1173 return $content;
1174 }
1175
1176
1177 /**
1178 * Redirects to alt_doc with new parameters to edit a just created localized record
1179 *
1180 * @param string String passed by GET &justLocalized=
1181 * @return void
1182 */
1183 function localizationRedirect($justLocalized) {
1184 global $TCA;
1185
1186 list($table,$orig_uid,$language) = explode(':',$justLocalized);
1187
1188 if ($TCA[$table] && $TCA[$table]['ctrl']['languageField'] && $TCA[$table]['ctrl']['transOrigPointerField']) {
1189 list($localizedRecord) = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1190 'uid',
1191 $table,
1192 $TCA[$table]['ctrl']['languageField'].'='.intval($language).' AND '.
1193 $TCA[$table]['ctrl']['transOrigPointerField'].'='.intval($orig_uid).
1194 t3lib_BEfunc::deleteClause($table).
1195 t3lib_BEfunc::versioningPlaceholderClause($table)
1196 );
1197
1198 if (is_array($localizedRecord)) {
1199 // Create parameters and finally run the classic page module for creating a new page translation
1200 $params = '&edit['.$table.']['.$localizedRecord['uid'].']=edit';
1201 $returnUrl = '&returnUrl='.rawurlencode(t3lib_div::_GP('returnUrl'));
1202 $location = $GLOBALS['BACK_PATH'].'alt_doc.php?'.$params.$returnUrl;
1203
1204 header('Location: '.t3lib_div::locationHeaderUrl($location));
1205 exit;
1206 }
1207 }
1208 }
1209
1210
1211 /**
1212 * Returns sys_language records.
1213 *
1214 * @param integer Page id: If zero, the query will select all sys_language records from root level which are NOT hidden. If set to another value, the query will select all sys_language records that has a pages_language_overlay record on that page (and is not hidden, unless you are admin user)
1215 * @return array Language records including faked record for default language
1216 */
1217 function getLanguages($id) {
1218 global $LANG;
1219
1220 $modSharedTSconfig = t3lib_BEfunc::getModTSconfig($id, 'mod.SHARED');
1221
1222 $languages = array(
1223 0 => array(
1224 'uid' => 0,
1225 'pid' => 0,
1226 'hidden' => 0,
1227 'title' => strlen($modSharedTSconfig['properties']['defaultLanguageLabel']) ? $modSharedTSconfig['properties']['defaultLanguageLabel'].' ('.$GLOBALS['LANG']->sl('LLL:EXT:lang/locallang_mod_web_list.xml:defaultLanguage').')' : $GLOBALS['LANG']->sl('LLL:EXT:lang/locallang_mod_web_list.xml:defaultLanguage'),
1228 'flag' => $modSharedTSconfig['properties']['defaultLanguageFlag'],
1229 )
1230 );
1231
1232 $exQ = $GLOBALS['BE_USER']->isAdmin() ? '' : ' AND sys_language.hidden=0';
1233 if ($id) {
1234 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1235 'sys_language.*',
1236 'pages_language_overlay,sys_language',
1237 'pages_language_overlay.sys_language_uid=sys_language.uid AND pages_language_overlay.pid='.intval($id).$exQ,
1238 'pages_language_overlay.sys_language_uid,sys_language.uid,sys_language.pid,sys_language.tstamp,sys_language.hidden,sys_language.title,sys_language.static_lang_isocode,sys_language.flag',
1239 'sys_language.title'
1240 );
1241 } else {
1242 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1243 'sys_language.*',
1244 'sys_language',
1245 'sys_language.hidden=0',
1246 '',
1247 'sys_language.title'
1248 );
1249 }
1250 if ($rows) {
1251 foreach ($rows as $row) {
1252 $languages[$row['uid']] = $row;
1253 }
1254 }
1255 return $languages;
1256 }
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267 /***************************
1268 *
1269 * Other functions
1270 *
1271 ***************************/
1272
1273 /**
1274 * Fix $this->editconf if versioning applies to any of the records
1275 *
1276 * @param array Mapping between old and new ids if auto-versioning has been performed.
1277 * @return void
1278 */
1279 function fixWSversioningInEditConf($mapArray=FALSE) {
1280 global $TCA,$BE_USER;
1281
1282 // Traverse the editConf array
1283 if (is_array($this->editconf)) {
1284 foreach($this->editconf as $table => $conf) { // Tables:
1285 if (is_array($conf) && $TCA[$table]) {
1286
1287 // Traverse the keys/comments of each table (keys can be a commalist of uids)
1288 $newConf = array();
1289 foreach($conf as $cKey => $cmd) {
1290 if ($cmd=='edit') {
1291 // Traverse the ids:
1292 $ids = t3lib_div::trimExplode(',', $cKey, 1);
1293 foreach($ids as $idKey => $theUid) {
1294 if (is_array($mapArray)) {
1295 if ($mapArray[$table][$theUid]) {
1296 $ids[$idKey] = $mapArray[$table][$theUid];
1297 }
1298 } else { // Default, look for versions in workspace for record:
1299 $calcPRec = $this->getRecordForEdit($table,$theUid);
1300 if (is_array($calcPRec)) {
1301 // Setting UID again if it had changed, eg. due to workspace versioning.
1302 $ids[$idKey] = $calcPRec['uid'];
1303 }
1304 }
1305 #else unset($ids[$idKey]);
1306 }
1307
1308 // Add the possibly manipulated IDs to the new-build newConf array:
1309 $newConf[implode(',',$ids)] = $cmd;
1310 } else {
1311 $newConf[$cKey] = $cmd;
1312 }
1313 }
1314 // Store the new conf array:
1315 $this->editconf[$table] = $newConf;
1316 }
1317 }
1318 }
1319 }
1320
1321 /**
1322 * Get record for editing.
1323 *
1324 * @param string Table name
1325 * @param integer Record UID
1326 * @return array Returns record to edit, false if none
1327 */
1328 function getRecordForEdit($table,$theUid) {
1329 global $TCA;
1330
1331 // Fetch requested record:
1332 $reqRecord = t3lib_BEfunc::getRecord($table,$theUid,'uid,pid');
1333
1334 if (is_array($reqRecord)) {
1335 // If workspace is OFFLINE:
1336 if ($GLOBALS['BE_USER']->workspace!=0) {
1337
1338 // Check for versioning support of the table:
1339 if ($TCA[$table] && $TCA[$table]['ctrl']['versioningWS']) {
1340
1341 // If the record is already a version of "something" pass it by.
1342 if ($reqRecord['pid']==-1) {
1343
1344 // (If it turns out not to be a version of the current workspace there will be trouble, but that is handled inside TCEmain then and in the interface it would clearly be an error of links if the user accesses such a scenario)
1345 return $reqRecord;
1346 } else { // The input record was online and an offline version must be found or made:
1347
1348 // Look for version of this workspace:
1349 $versionRec = t3lib_BEfunc::getWorkspaceVersionOfRecord($GLOBALS['BE_USER']->workspace, $table, $reqRecord['uid'],'uid,pid,t3ver_oid');
1350 return is_array($versionRec) ? $versionRec : $reqRecord;
1351 }
1352 } else return FALSE; // This means that editing cannot occur on this record because it was not supporting versioning which is required inside an offline workspace.
1353 } else return $reqRecord; // In ONLINE workspace, just return the originally requested record:
1354 } else return FALSE; // Return false because the table/uid was not found anyway.
1355 }
1356
1357 /**
1358 * Function, which populates the internal editconf array with editing commands for all tt_content elements from the normal column in normal language from the page pointed to by $this->editRegularContentFromId
1359 *
1360 * @return void
1361 */
1362 function editRegularContentFromId() {
1363 if (t3lib_extMgm::isLoaded('cms')) {
1364 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1365 'uid',
1366 'tt_content',
1367 'pid='.intval($this->editRegularContentFromId).
1368 t3lib_BEfunc::deleteClause('tt_content').
1369 t3lib_BEfunc::versioningPlaceholderClause('tt_content').
1370 ' AND colPos=0 AND sys_language_uid=0',
1371 '',
1372 'sorting'
1373 );
1374 if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) {
1375 $ecUids=array();
1376 while($ecRec = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
1377 $ecUids[]=$ecRec['uid'];
1378 }
1379 $this->editconf['tt_content'][implode(',',$ecUids)]='edit';
1380 }
1381 }
1382 }
1383
1384 /**
1385 * Populates the variables $this->storeArray, $this->storeUrl, $this->storeUrlMd5
1386 *
1387 * @return void
1388 * @see makeDocSel()
1389 */
1390 function compileStoreDat() {
1391 $this->storeArray = t3lib_div::compileSelectedGetVarsFromArray('edit,defVals,overrideVals,columnsOnly,disHelp,noView,editRegularContentFromId',$this->R_URL_getvars);
1392 $this->storeUrl = t3lib_div::implodeArrayForUrl('',$this->storeArray);
1393 $this->storeUrlMd5 = md5($this->storeUrl);
1394 }
1395
1396 /**
1397 * Function used to look for configuration of buttons in the form: Fx. disabling buttons or showing them at various positions.
1398 *
1399 * @param string The table for which the configuration may be specific
1400 * @param string The option for look for. Default is checking if the saveDocNew button should be displayed.
1401 * @return string Return value fetched from USER TSconfig
1402 */
1403 function getNewIconMode($table,$key='saveDocNew') {
1404 global $BE_USER;
1405 $TSconfig = $BE_USER->getTSConfig('options.'.$key);
1406 $output = trim(isset($TSconfig['properties'][$table]) ? $TSconfig['properties'][$table] : $TSconfig['value']);
1407 return $output;
1408 }
1409
1410 /**
1411 * Handling the closing of a document
1412 *
1413 * @param integer Close code: 0/1 will redirect to $this->retUrl, 3 will clear the docHandler (thus closing all documents) and otehr values will call setDocument with ->retUrl
1414 * @return void
1415 */
1416 function closeDocument($code=0) {
1417 global $BE_USER;
1418
1419 // If current document is found in docHandler, then unset it, possibly unset it ALL and finally, write it to the session data:
1420 if (isset($this->docHandler[$this->storeUrlMd5])) {
1421 unset($this->docHandler[$this->storeUrlMd5]);
1422 if ($code=='3') $this->docHandler=array();
1423 $BE_USER->pushModuleData('alt_doc.php',array($this->docHandler,$this->docDat[1]));
1424 }
1425
1426 // If ->returnEditConf is set, then add the current content of editconf to the ->retUrl variable: (used by other scripts, like wizard_add, to know which records was created or so...)
1427 if ($this->returnEditConf && $this->retUrl!='dummy.php') {
1428 $this->retUrl.='&returnEditConf='.rawurlencode(serialize($this->editconf));
1429 }
1430
1431 // If code is NOT set OR set to 1, then make a header location redirect to $this->retUrl
1432 if (!$code || $code==1) {
1433 Header('Location: '.t3lib_div::locationHeaderUrl($this->retUrl));
1434 exit;
1435 } else {
1436 $this->setDocument('',$this->retUrl);
1437 }
1438 }
1439
1440 /**
1441 * Redirects to the document pointed to by $currentDocFromHandlerMD5 OR $retUrl (depending on some internal calculations).
1442 * Most likely you will get a header-location redirect from this function.
1443 *
1444 * @param string Pointer to the document in the docHandler array
1445 * @param string Alternative/Default retUrl
1446 * @return void
1447 */
1448 function setDocument($currentDocFromHandlerMD5='',$retUrl='alt_doc_nodoc.php') {
1449 if (!t3lib_extMgm::isLoaded('cms') && !strcmp($retUrl,'alt_doc_nodoc.php')) return;
1450
1451 if (!$this->modTSconfig['properties']['disableDocSelector'] && is_array($this->docHandler) && count($this->docHandler)) {
1452 if (isset($this->docHandler[$currentDocFromHandlerMD5])) {
1453 $setupArr=$this->docHandler[$currentDocFromHandlerMD5];
1454 } else {
1455 reset($this->docHandler);
1456 $setupArr=current($this->docHandler);
1457 }
1458 if ($setupArr[2]) {
1459 $sParts = parse_url(t3lib_div::getIndpEnv('REQUEST_URI'));
1460 $retUrl = $sParts['path'].'?'.$setupArr[2].'&returnUrl='.rawurlencode($retUrl);
1461 }
1462 }
1463 Header('Location: '.t3lib_div::locationHeaderUrl($retUrl));
1464 exit;
1465 }
1466 }
1467
1468 // Include extension?
1469 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/alt_doc.php']) {
1470 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/alt_doc.php']);
1471 }
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488 // Make instance:
1489 $SOBE = t3lib_div::makeInstance('SC_alt_doc');
1490
1491 // Preprocessing, storing data if submitted to
1492 $SOBE->preInit();
1493 if ($SOBE->doProcessData()) { // Checks, if a save button has been clicked (or the doSave variable is sent)
1494 $SOBE->processData();
1495 }
1496
1497
1498 // Main:
1499 $SOBE->init();
1500 $SOBE->main();
1501 $SOBE->printContent();
1502 ?>