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