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