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