[BUGFIX] Show correct record title
[Packages/TYPO3.CMS.git] / typo3 / alt_doc.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2011 Kasper Skårhøj (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 * Revised for TYPO3 3.6 November/2003 by Kasper Skårhøj
33 * XHTML compliant
34 *
35 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
36 */
37 /**
38 * [CLASS/FUNCTION INDEX of SCRIPT]
39 *
40 *
41 *
42 * 105: class SC_alt_doc
43 * 179: function preInit()
44 * 241: function doProcessData()
45 * 251: function processData()
46 * 379: function init()
47 * 473: function main()
48 * 551: function printContent()
49 *
50 * SECTION: Sub-content functions, rendering specific parts of the module content.
51 * 587: function makeEditForm()
52 * 771: function makeButtonPanel()
53 * 850: function makeDocSel()
54 * 892: function makeCmenu()
55 * 914: function compileForm($panel,$docSel,$cMenu,$editForm, $langSelector='')
56 * 982: function functionMenus()
57 * 1013: function shortCutLink()
58 * 1044: function tceformMessages()
59 *
60 * SECTION: Localization stuff
61 * 1083: function languageSwitch($table, $uid, $pid=NULL)
62 * 1179: function localizationRedirect($justLocalized)
63 * 1213: function getLanguages($id)
64 *
65 * SECTION: Other functions
66 * 1275: function fixWSversioningInEditConf($mapArray=FALSE)
67 * 1324: function getRecordForEdit($table,$theUid)
68 * 1358: function editRegularContentFromId()
69 * 1386: function compileStoreDat()
70 * 1399: function getNewIconMode($table,$key='saveDocNew')
71 * 1412: function closeDocument($code=0)
72 * 1444: function setDocument($currentDocFromHandlerMD5='',$retUrl='alt_doc_nodoc.php')
73 *
74 * TOTAL FUNCTIONS: 24
75 * (This index is automatically created/updated by the extension "extdeveval")
76 *
77 */
78
79
80 require_once('init.php');
81 require_once('template.php');
82 $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_alt_doc.xml');
83
84 t3lib_BEfunc::lockRecords();
85
86
87
88
89 /**
90 * Script Class: Drawing the editing form for editing records in TYPO3.
91 * Notice: It does NOT use tce_db.php to submit data to, rather it handles submissions itself
92 *
93 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
94 * @package TYPO3
95 * @subpackage core
96 */
97 class SC_alt_doc {
98
99 // Internal, static: GPvars:
100 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).
101 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 $GLOBALS['TCA']
102 var $defVals; // Default values for fields (array with tablenames, fields etc. as keys). Can be seen modified internally.
103 var $overrideVals; // Array of values to force being set (as hidden fields). Will be set as $this->defVals IF defVals does not exist.
104 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
105 var $closeDoc; // Close-document command. Not really sure of all options...
106 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).
107
108 var $data; // GPvar (for processing only) : The data array from which the data comes...
109 var $mirror; // GPvar (for processing only) : ?
110 var $cacheCmd; // GPvar (for processing only) : Clear-cache cmd.
111 var $redirect; // GPvar (for processing only) : Redirect (not used???)
112 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.
113 var $vC; // GPvar (for processing only) : Verification code, internal stuff.
114 var $uc; // GPvar : update BE_USER->uc
115
116 var $popViewId; // GPvar (module) : ID for displaying the page in the frontend (used for SAVE/VIEW operations)
117 var $popViewId_addParams; // GPvar (module) : Additional GET vars for the link, eg. "&L=xxx"
118 var $viewUrl; // GPvar (module) : Alternative URL for viewing the frontend pages.
119 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!
120 var $recTitle; // Alternative title for the document handler.
121 var $disHelp; // Disable help... ?
122 var $noView; // If set, then no SAVE/VIEW button is printed
123 var $returnEditConf; // If set, the $this->editconf array is returned to the calling script (used by wizard_add.php for instance)
124 var $localizationMode; // GP var, localization mode for TCEforms (eg. "text")
125
126
127 // Internal, static:
128 /**
129 * document template object
130 *
131 * @var mediumDoc
132 */
133 var $doc;
134 var $template; // a static HTML template, usually in templates/alt_doc.html
135 var $content; // Content accumulation
136
137 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.
138 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...
139 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.)
140 var $R_URI; // Set to the URL of this script including variables which is needed to re-display the form. See main()
141
142 var $storeTitle; // Is loaded with the "title" of the currently "open document" - this is used in the Document Selector box. (see makeDocSel())
143 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())
144 var $storeUrl; // Contains storeArray, but imploded into a GET parameter string (see compileStoreDat())
145 var $storeUrlMd5; // Hashed value of storeURL (see compileStoreDat())
146
147 var $docDat; // Module session data
148 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".
149
150
151 // Internal: Related to the form rendering:
152 var $elementsData; // Array of the elements to create edit forms for.
153 var $firstEl; // Pointer to the first element in $elementsData
154 var $errorC; // Counter, used to count the number of errors (when users do not have edit permissions)
155 var $newC; // Counter, used to count the number of new record forms displayed
156 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
157 var $viewId_addParams; // Is set to additional parameters (like "&L=xxx") if the record supports it.
158 var $modTSconfig; // Module TSconfig, loaded from main() based on the page id value of viewId
159
160 /**
161 * instance of TCEforms class
162 *
163 * @var t3lib_TCEforms
164 */
165 var $tceforms;
166 var $generalPathOfForm; // Contains the root-line path of the currently edited record(s) - for display.
167
168
169 // Internal, dynamic:
170 var $dontStoreDocumentRef; // Used internally to disable the storage of the document reference (eg. new records)
171
172
173
174
175
176
177
178 /**
179 * First initialization.
180 *
181 * @return void
182 */
183 function preInit() {
184 if (t3lib_div::_GP('justLocalized')) {
185 $this->localizationRedirect(t3lib_div::_GP('justLocalized'));
186 }
187
188 // Setting GPvars:
189 $this->editconf = t3lib_div::_GP('edit');
190 $this->defVals = t3lib_div::_GP('defVals');
191 $this->overrideVals = t3lib_div::_GP('overrideVals');
192 $this->columnsOnly = t3lib_div::_GP('columnsOnly');
193 $this->returnUrl = t3lib_div::sanitizeLocalUrl(t3lib_div::_GP('returnUrl'));
194 $this->closeDoc = t3lib_div::_GP('closeDoc');
195 $this->doSave = t3lib_div::_GP('doSave');
196 $this->returnEditConf = t3lib_div::_GP('returnEditConf');
197 $this->localizationMode = t3lib_div::_GP('localizationMode');
198 $this->uc = t3lib_div::_GP('uc');
199
200
201 // Setting override values as default if defVals does not exist.
202 if (!is_array($this->defVals) && is_array($this->overrideVals)) {
203 $this->defVals = $this->overrideVals;
204 }
205
206 // Setting return URL
207 $this->retUrl = $this->returnUrl ? $this->returnUrl : 'dummy.php';
208
209 // Fix $this->editconf if versioning applies to any of the records
210 $this->fixWSversioningInEditConf();
211
212 // Make R_URL (request url) based on input GETvars:
213 $this->R_URL_parts = parse_url(t3lib_div::getIndpEnv('REQUEST_URI'));
214 $this->R_URL_getvars = t3lib_div::_GET();
215 $this->R_URL_getvars['edit'] = $this->editconf;
216
217 // MAKE url for storing
218 $this->compileStoreDat();
219
220 // Initialize more variables.
221 $this->dontStoreDocumentRef=0;
222 $this->storeTitle='';
223
224 // Get session data for the module:
225 $this->docDat = $GLOBALS['BE_USER']->getModuleData('alt_doc.php', 'ses');
226 $this->docHandler = $this->docDat[0];
227
228 // If a request for closing the document has been sent, act accordingly:
229 if ($this->closeDoc>0) {
230 $this->closeDocument($this->closeDoc);
231 }
232
233 // If NO vars are sent to the script, try to read first document:
234 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...
235 $this->setDocument($this->docDat[1]);
236 }
237 }
238
239
240 /**
241 * Detects, if a save command has been triggered.
242 *
243 * @return boolean TRUE, then save the document (data submitted)
244 */
245 function doProcessData() {
246 $out = $this->doSave || isset($_POST['_savedok_x']) || isset($_POST['_saveandclosedok_x']) || isset($_POST['_savedokview_x']) || isset($_POST['_savedoknew_x']) || isset($_POST['_translation_savedok_x']) || isset($_POST['_translation_savedokclear_x']);
247 return $out;
248 }
249
250
251 /**
252 * Do processing of data, submitting it to TCEmain.
253 *
254 * @return void
255 */
256 function processData() {
257 global $TYPO3_CONF_VARS;
258
259 // GPvars specifically for processing:
260 $this->data = t3lib_div::_GP('data');
261 $this->cmd = t3lib_div::_GP('cmd');
262 $this->mirror = t3lib_div::_GP('mirror');
263 $this->cacheCmd = t3lib_div::_GP('cacheCmd');
264 $this->redirect = t3lib_div::_GP('redirect');
265 $this->returnNewPageId = t3lib_div::_GP('returnNewPageId');
266 $this->vC = t3lib_div::_GP('vC');
267
268 // See tce_db.php for relevate options here:
269 // Only options related to $this->data submission are included here.
270 /** @var $tce t3lib_TCEmain */
271 $tce = t3lib_div::makeInstance('t3lib_TCEmain');
272 $tce->stripslashes_values=0;
273
274 if (isset($_POST['_translation_savedok_x'])) {
275 $tce->updateModeL10NdiffData = 'FORCE_FFUPD';
276 }
277 if (isset($_POST['_translation_savedokclear_x'])) {
278 $tce->updateModeL10NdiffData = 'FORCE_FFUPD';
279 $tce->updateModeL10NdiffDataClear = TRUE;
280 }
281
282 // Setting default values specific for the user:
283 $TCAdefaultOverride = $GLOBALS['BE_USER']->getTSConfigProp('TCAdefaults');
284 if (is_array($TCAdefaultOverride)) {
285 $tce->setDefaultsFromUserTS($TCAdefaultOverride);
286 }
287
288 // Setting internal vars:
289 if ($GLOBALS['BE_USER']->uc['neverHideAtCopy']) {
290 $tce->neverHideAtCopy = 1;
291 }
292 $tce->debug=0;
293 $tce->disableRTE = !$GLOBALS['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']) || $GLOBALS['BE_USER']->workspace != 0 && count($this->data)) {
303 t3lib_BEfunc::setUpdateSignal('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 != $GLOBALS['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']) || isset($_POST['_translation_savedok_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']) || isset($_POST['_translation_savedok_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
416 // Setting more GPvars:
417 $this->popViewId = t3lib_div::_GP('popViewId');
418 $this->popViewId_addParams = t3lib_div::_GP('popViewId_addParams');
419 $this->viewUrl = t3lib_div::_GP('viewUrl');
420 $this->editRegularContentFromId = t3lib_div::_GP('editRegularContentFromId');
421 $this->recTitle = t3lib_div::_GP('recTitle');
422 $this->disHelp = t3lib_div::_GP('disHelp');
423 $this->noView = t3lib_div::_GP('noView');
424
425 $this->perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
426
427 // Set other internal variables:
428 $this->R_URL_getvars['returnUrl']=$this->retUrl;
429 $this->R_URI = $this->R_URL_parts['path'].'?'.t3lib_div::implodeArrayForUrl('',$this->R_URL_getvars);
430
431 // MENU-ITEMS:
432 // If array, then it's a selector box menu
433 // If empty string it's just a variable, that'll be saved.
434 // Values NOT in this array will not be saved in the settings-array for the module.
435 $this->MOD_MENU = array(
436 'showPalettes' => ''
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 = $GLOBALS['TBE_TEMPLATE'];
447 $this->doc->backPath = $GLOBALS['BACK_PATH'];
448 $this->doc->setModuleTemplate('templates/alt_doc.html');
449 $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);">';
450
451 $this->doc->getPageRenderer()->loadPrototype();
452 $this->doc->JScode = $this->doc->wrapScriptTags('
453 function jumpToUrl(URL,formEl) { //
454 if (!TBE_EDITOR.isFormChanged()) {
455 window.location.href = URL;
456 } else if (formEl && formEl.type=="checkbox") {
457 formEl.checked = formEl.checked ? 0 : 1;
458 }
459 }
460 // Object: TS:
461 // passwordDummy and decimalSign are used by tbe_editor.js and have to be declared here as
462 // TS object overwrites the object declared in tbe_editor.js
463 function typoSetup () { //
464 this.uniqueID = "";
465 this.passwordDummy = "********";
466 this.decimalSign = ".";
467 }
468 var TS = new typoSetup();
469
470 // Info view:
471 function launchView(table,uid,bP) { //
472 var backPath= bP ? bP : "";
473 var thePreviewWindow="";
474 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");
475 if (thePreviewWindow && thePreviewWindow.focus) {
476 thePreviewWindow.focus();
477 }
478 }
479 function deleteRecord(table,id,url) { //
480 if (
481 ' . ($GLOBALS['BE_USER']->jsConfirmation(4) ? 'confirm(' . $GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->getLL('deleteWarning')) . ')' : '1==1') . '
482 ) {
483 window.location.href = "tce_db.php?cmd["+table+"]["+id+"][delete]=1' . t3lib_BEfunc::getUrlToken('tceAction') . '&redirect="+escape(url)+"&vC=' . $GLOBALS['BE_USER']->veriCode() . '&prErr=1&uPT=1";
484 }
485 return false;
486 }
487 '.(isset($_POST['_savedokview_x']) && $this->popViewId ?
488 'if (window.opener) { '.
489 t3lib_BEfunc::viewOnClick($this->popViewId,'',t3lib_BEfunc::BEgetRootLine($this->popViewId),'',$this->viewUrl,$this->popViewId_addParams,FALSE).
490 ' } else { '.
491 t3lib_BEfunc::viewOnClick($this->popViewId,'',t3lib_BEfunc::BEgetRootLine($this->popViewId),'',$this->viewUrl,$this->popViewId_addParams).
492 ' } '
493 : '')
494 );
495
496 // Setting up the context sensitive menu:
497 $this->doc->getContextMenuCode();
498 $this->doc->bodyTagAdditions = 'onload="window.scrollTo(0,'.t3lib_div::intInRange(t3lib_div::_GP('_scrollPosition'),0,10000).');"';
499 }
500
501 /**
502 * Main module operation
503 *
504 * @return void
505 */
506 function main() {
507
508 // Begin edit:
509 if (is_array($this->editconf)) {
510
511 // Initialize TCEforms (rendering the forms)
512 $this->tceforms = t3lib_div::makeInstance('t3lib_TCEforms');
513 $this->tceforms->initDefaultBEMode();
514 $this->tceforms->doSaveFieldName = 'doSave';
515 $this->tceforms->localizationMode = t3lib_div::inList('text,media',$this->localizationMode) ? $this->localizationMode : ''; // text,media is keywords defined in TYPO3 Core API..., see "l10n_cat"
516 $this->tceforms->returnUrl = $this->R_URI;
517 $this->tceforms->palettesCollapsed = !$this->MOD_SETTINGS['showPalettes'];
518 $this->tceforms->disableRTE = !$GLOBALS['BE_USER']->isRTE();
519 $this->tceforms->enableClickMenu = TRUE;
520 $this->tceforms->enableTabMenu = TRUE;
521
522 // Clipboard is initialized:
523 $this->tceforms->clipObj = t3lib_div::makeInstance('t3lib_clipboard'); // Start clipboard
524 $this->tceforms->clipObj->initializeClipboard(); // Initialize - reads the clipboard content from the user session
525
526 // Setting external variables:
527 $this->tceforms->edit_showFieldHelp = $GLOBALS['BE_USER']->uc['edit_showFieldHelp'];
528
529 if ($this->editRegularContentFromId) {
530 $this->editRegularContentFromId();
531 }
532
533
534 // Creating the editing form, wrap it with buttons, document selector etc.
535 $editForm = $this->makeEditForm();
536
537 if ($editForm) {
538 $this->firstEl = reset($this->elementsData);
539
540 // Checking if the currently open document is stored in the list of "open documents" - if not, then add it:
541 if ((strcmp($this->docDat[1], $this->storeUrlMd5) || !isset($this->docHandler[$this->storeUrlMd5])) && !$this->dontStoreDocumentRef) {
542 $this->docHandler[$this->storeUrlMd5] = array($this->storeTitle, $this->storeArray, $this->storeUrl, $this->firstEl);
543 $GLOBALS['BE_USER']->pushModuleData('alt_doc.php', array($this->docHandler, $this->storeUrlMd5));
544 t3lib_BEfunc::setUpdateSignal('tx_opendocs::updateNumber', count($this->docHandler));
545 }
546
547
548 // Module configuration
549 $this->modTSconfig = ($this->viewId ? t3lib_BEfunc::getModTSconfig($this->viewId,'mod.xMOD_alt_doc') : array());
550
551 $body.= $this->tceforms->printNeededJSFunctions_top();
552 $body.= $this->compileForm($editForm);
553 $body.= $this->tceforms->printNeededJSFunctions();
554 $body.= $this->functionMenus();
555 $body.= $this->tceformMessages();
556 }
557 }
558
559 // Access check...
560 // The page will show only if there is a valid page and if this page may be viewed by the user
561 $this->pageinfo = t3lib_BEfunc::readPageAccess($this->viewId, $this->perms_clause);
562
563 // Setting up the buttons and markers for docheader
564 $docHeaderButtons = $this->getButtons();
565 $markers = array(
566 'LANGSELECTOR' => $this->langSelector(),
567 'EXTRAHEADER' => $this->extraFormHeaders(),
568 'CSH' => $docHeaderButtons['csh'],
569 'CONTENT' => $body
570 );
571
572 // Build the <body> for the module
573 $this->content = $this->doc->startPage('TYPO3 Edit Document');
574 $this->content.= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
575 $this->content.= $this->doc->endPage();
576 $this->content = $this->doc->insertStylesAndJS($this->content);
577 }
578
579
580 /**
581 * Outputting the accumulated content to screen
582 *
583 * @return void
584 */
585 function printContent() {
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
621 // Initialize variables:
622 $this->elementsData=array();
623 $this->errorC=0;
624 $this->newC=0;
625 $thePrevUid='';
626 $editForm='';
627 $trData = NULL;
628
629 // Traverse the GPvar edit array
630 foreach($this->editconf as $table => $conf) { // Tables:
631 if (is_array($conf) && $GLOBALS['TCA'][$table] && $GLOBALS['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 // Permissions for the parent page
665 $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms($calcPRec);
666 if ($table=='pages') { // If pages:
667 $hasAccess = $CALC_PERMS&8 ? 1 : 0;
668 #$this->viewId = $calcPRec['pid'];
669 $this->viewId = 0;
670 } else {
671 $hasAccess = $CALC_PERMS&16 ? 1 : 0;
672 $this->viewId = $calcPRec['uid'];
673 }
674 }
675 }
676 $this->dontStoreDocumentRef=1; // Don't save this document title in the document selector if the document is new.
677 } else { // Edit:
678 $calcPRec = t3lib_BEfunc::getRecord($table,$theUid);
679 t3lib_BEfunc::fixVersioningPid($table,$calcPRec);
680 if (is_array($calcPRec)) {
681 if ($table=='pages') { // If pages:
682 $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms($calcPRec);
683 $hasAccess = $CALC_PERMS&2 ? 1 : 0;
684 $deleteAccess = $CALC_PERMS&4 ? 1 : 0;
685 $this->viewId = $calcPRec['uid'];
686 } else {
687 // Fetching pid-record first
688 $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages', $calcPRec['pid']));
689 $hasAccess = $CALC_PERMS&16 ? 1 : 0;
690 $deleteAccess = $CALC_PERMS&16 ? 1 : 0;
691 $this->viewId = $calcPRec['pid'];
692
693 // Adding "&L=xx" if the record being edited has a languageField with a value larger than zero!
694 if ($GLOBALS['TCA'][$table]['ctrl']['languageField'] && $calcPRec[$GLOBALS['TCA'][$table]['ctrl']['languageField']] > 0) {
695 $this->viewId_addParams = '&L=' . $calcPRec[$GLOBALS['TCA'][$table]['ctrl']['languageField']];
696 }
697 }
698
699 // Check internals regarding access:
700 if ($hasAccess) {
701 $hasAccess = $GLOBALS['BE_USER']->recordEditAccessInternals($table, $calcPRec);
702 $deniedAccessReason = $GLOBALS['BE_USER']->errorMsg;
703 }
704 } else $hasAccess = 0;
705 }
706
707 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/alt_doc.php']['makeEditForm_accessCheck'])) {
708 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/alt_doc.php']['makeEditForm_accessCheck'] as $_funcRef) {
709 $_params = array(
710 'table' => $table,
711 'uid' => $theUid,
712 'cmd' => $cmd,
713 'hasAccess' => $hasAccess
714 );
715 $hasAccess = t3lib_div::callUserFunction($_funcRef, $_params, $this);
716 }
717 }
718
719 // 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:
720
721 if ($hasAccess) {
722 $prevPageID = is_object($trData)?$trData->prevPageID:'';
723 $trData = t3lib_div::makeInstance('t3lib_transferData');
724 $trData->addRawData = TRUE;
725 $trData->defVals = $this->defVals;
726 $trData->lockRecords=1;
727 $trData->disableRTE = !$GLOBALS['BE_USER']->isRTE();
728 $trData->prevPageID = $prevPageID;
729 $trData->fetchRecord($table,$theUid,$cmd=='new'?'new':''); // 'new'
730 reset($trData->regTableItems_data);
731 $rec = current($trData->regTableItems_data);
732 $rec['uid'] = $cmd=='new' ? uniqid('NEW') : $theUid;
733 if ($cmd=='new') {
734 $rec['pid'] = $theUid=='prev'?$thePrevUid:$theUid;
735 }
736 $this->elementsData[]=array(
737 'table' => $table,
738 'uid' => $rec['uid'],
739 'pid' => $rec['pid'],
740 'cmd' => $cmd,
741 'deleteAccess' => $deleteAccess
742 );
743
744 // Now, render the form:
745 if (is_array($rec)) {
746
747 // Setting visual path / title of form:
748 $this->generalPathOfForm = $this->tceforms->getRecordPath($table,$rec);
749 if (!$this->storeTitle) {
750 $this->storeTitle = $this->recTitle ? htmlspecialchars($this->recTitle) : t3lib_BEfunc::getRecordTitle($table,$rec,TRUE);
751 }
752
753 // Setting variables in TCEforms object:
754 $this->tceforms->hiddenFieldList = '';
755 $this->tceforms->globalShowHelp = $this->disHelp ? 0 : 1;
756 if (is_array($this->overrideVals[$table])) {
757 $this->tceforms->hiddenFieldListArr = array_keys($this->overrideVals[$table]);
758 }
759
760 // Register default language labels, if any:
761 $this->tceforms->registerDefaultLanguageData($table,$rec);
762
763 // Create form for the record (either specific list of fields or the whole record):
764 $panel = '';
765 if ($this->columnsOnly) {
766 if(is_array($this->columnsOnly)){
767 $panel.= $this->tceforms->getListedFields($table,$rec,$this->columnsOnly[$table]);
768 } else {
769 $panel.= $this->tceforms->getListedFields($table,$rec,$this->columnsOnly);
770 }
771 } else {
772 $panel.= $this->tceforms->getMainFields($table,$rec);
773 }
774 $panel = $this->tceforms->wrapTotal($panel,$rec,$table);
775
776 // Setting the pid value for new records:
777 if ($cmd=='new') {
778 $panel.= '<input type="hidden" name="data['.$table.']['.$rec['uid'].'][pid]" value="'.$rec['pid'].'" />';
779 $this->newC++;
780 }
781
782 // Display "is-locked" message:
783 if ($lockInfo = t3lib_BEfunc::isRecordLocked($table, $rec['uid'])) {
784 $lockedMessage = t3lib_div::makeInstance(
785 't3lib_FlashMessage',
786 htmlspecialchars($lockInfo['msg']),
787 '',
788 t3lib_FlashMessage::WARNING
789 );
790 t3lib_FlashMessageQueue::addMessage($lockedMessage);
791 }
792
793 // Combine it all:
794 $editForm .= $panel;
795 }
796
797 $thePrevUid = $rec['uid'];
798 } else {
799 $this->errorC++;
800 $editForm .= $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.noEditPermission',1) . '<br /><br />' .
801 ($deniedAccessReason ? 'Reason: ' . htmlspecialchars($deniedAccessReason) . '<br /><br />' : '');
802 }
803 }
804 }
805 }
806 }
807 }
808
809 return $editForm;
810 }
811
812 /**
813 * Create the panel of buttons for submitting the form or otherwise perform operations.
814 *
815 * @return array all available buttons as an assoc. array
816 */
817 protected function getButtons() {
818 $buttons = array(
819 'save' => '',
820 'save_view' => '',
821 'save_new' => '',
822 'save_close' => '',
823 'close' => '',
824 'delete' => '',
825 'undo' => '',
826 'history' => '',
827 'columns_only' => '',
828 'csh' => '',
829 'translation_save' => '',
830 'translation_saveclear' => ''
831 );
832
833 // Render SAVE type buttons:
834 // The action of each button is decided by its name attribute. (See doProcessData())
835 if (!$this->errorC && !$GLOBALS['TCA'][$this->firstEl['table']]['ctrl']['readOnly']) {
836
837 // SAVE button:
838 $buttons['save'] = t3lib_iconWorks::getSpriteIcon('actions-document-save', array( 'html' => '<input type="image" name="_savedok" class="c-inputButton" src="clear.gif" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:rm.saveDoc', 1) . '" />' ));
839
840 // SAVE / VIEW button:
841 if ($this->viewId && !$this->noView && t3lib_extMgm::isLoaded('cms') && $this->getNewIconMode($this->firstEl['table'], 'saveDocView')) {
842 $buttons['save_view'] = t3lib_iconWorks::getSpriteIcon('actions-document-save-view', array('html'=>'<input type="image" class="c-inputButton" name="_savedokview" src="clear.gif" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:rm.saveDocShow', 1) . '" />'));
843 }
844
845 // SAVE / NEW button:
846 if (count($this->elementsData)==1 && $this->getNewIconMode($this->firstEl['table'])) {
847 $buttons['save_new'] = t3lib_iconWorks::getSpriteIcon('actions-document-save-new', array('html'=>'<input type="image" class="c-inputButton" name="_savedoknew" src="clear.gif" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:rm.saveNewDoc', 1) . '" />'));
848 }
849
850 // SAVE / CLOSE
851 $buttons['save_close'] = t3lib_iconWorks::getSpriteIcon('actions-document-save-close', array('html'=>'<input type="image" class="c-inputButton" name="_saveandclosedok" src="clear.gif" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:rm.saveCloseDoc', 1) . '" />'));
852
853 // FINISH TRANSLATION / SAVE / CLOSE
854 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['explicitConfirmationOfTranslation']) {
855 $buttons['translation_save'] = '<input type="image" class="c-inputButton" name="_translation_savedok" src="' . t3lib_iconWorks::skinImg($this->doc->backPath, 'gfx/translationsavedok.gif', '', 1) . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:rm.translationSaveDoc', 1) . '" />';
856 $buttons['translation_saveclear'] = '<input type="image" class="c-inputButton" name="_translation_savedokclear" src="' . t3lib_iconWorks::skinImg($this->doc->backPath, 'gfx/translationsavedok_clear.gif', '', 1) . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:rm.translationSaveDocClear', 1) . '" />';
857 }
858 }
859
860 // CLOSE button:
861 $buttons['close'] = '<a href="#" onclick="document.editform.closeDoc.value=1; document.editform.submit(); return false;" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:rm.closeDoc', TRUE) . '">' .
862 t3lib_iconWorks::getSpriteIcon('actions-document-close') .
863 '</a>';
864
865
866 // DELETE + UNDO buttons:
867 if (!$this->errorC && !$GLOBALS['TCA'][$this->firstEl['table']]['ctrl']['readOnly'] && count($this->elementsData)==1) {
868 if ($this->firstEl['cmd']!='new' && t3lib_div::testInt($this->firstEl['uid'])) {
869
870 // Delete:
871 if ($this->firstEl['deleteAccess'] && !$GLOBALS['TCA'][$this->firstEl['table']]['ctrl']['readOnly'] && !$this->getNewIconMode($this->firstEl['table'],'disableDelete')) {
872 $aOnClick = 'return deleteRecord(\''.$this->firstEl['table'].'\',\''.$this->firstEl['uid'].'\',unescape(\''.rawurlencode($this->retUrl).'\'));';
873 $buttons['delete'] = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '" title="' . $GLOBALS['LANG']->getLL('deleteItem', TRUE) . '">' .
874 t3lib_iconWorks::getSpriteIcon('actions-edit-delete') .
875 '</a>';
876 }
877
878 // Undo:
879 $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');
880 if ($undoButtonR = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($undoRes)) {
881 $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;';
882 $buttons['undo'] = '<a href="#" onclick="'.htmlspecialchars($aOnClick).'"'.
883 ' title="' . htmlspecialchars(sprintf($GLOBALS['LANG']->getLL('undoLastChange'), t3lib_BEfunc::calcAge($GLOBALS['EXEC_TIME'] - $undoButtonR['tstamp'], $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.minutesHoursDaysYears')))) . '">' .
884 t3lib_iconWorks::getSpriteIcon('actions-edit-undo') .
885 '</a>';
886 }
887 if ($this->getNewIconMode($this->firstEl['table'],'showHistory')) {
888 $aOnClick = 'window.location.href=\'show_rechis.php?element='.rawurlencode($this->firstEl['table'].':'.$this->firstEl['uid']).'&returnUrl='.rawurlencode($this->R_URI).'\'; return false;';
889 $buttons['history'] = '<a href="#" onclick="'.htmlspecialchars($aOnClick).'">'.
890 t3lib_iconWorks::getSpriteIcon('actions-document-history-open') .
891 '</a>';
892 }
893
894 // If only SOME fields are shown in the form, this will link the user to the FULL form:
895 if ($this->columnsOnly) {
896 $buttons['columns_only'] = '<a href="'.htmlspecialchars($this->R_URI.'&columnsOnly=').'" title="' . $GLOBALS['LANG']->getLL('editWholeRecord', TRUE) . '">' .
897 t3lib_iconWorks::getSpriteIcon('actions-document-open') .
898 '</a>';
899 }
900 }
901 }
902
903 // add the CSH icon
904 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'TCEforms', $GLOBALS['BACK_PATH'], '', TRUE);
905 $buttons['shortcut'] = $this->shortCutLink();
906 $buttons['open_in_new_window'] = $this->openInNewWindowLink();
907 return $buttons;
908 }
909
910 /**
911 * Returns the language switch/selector for editing,
912 * show only when a single record is edited
913 * - multiple records are too confusing
914 * @return string the HTML
915 */
916 function langSelector() {
917 $langSelector = '';
918 if (count($this->elementsData) == 1) {
919 $langSelector = $this->languageSwitch($this->firstEl['table'], $this->firstEl['uid'], $this->firstEl['pid']);
920 }
921 return $langSelector;
922 }
923
924
925 /**
926 * Compiles the extra form headers if the tceforms
927 *
928 * @return string the HTML
929 */
930 function extraFormHeaders() {
931 $extraTemplate = '';
932
933 if (is_array($this->tceforms->extraFormHeaders)) {
934 $extraTemplate = t3lib_parsehtml::getSubpart($this->doc->moduleTemplate, '###DOCHEADER_EXTRAHEADER###');
935 $extraTemplate = t3lib_parsehtml::substituteMarker($extraTemplate, '###EXTRAHEADER###', implode(LF, $this->tceforms->extraFormHeaders));
936 }
937 return $extraTemplate;
938 }
939
940
941 /**
942 * Put together the various elements (buttons, selectors, form) into a table
943 *
944 * @param string HTML form.
945 * @return string Composite HTML
946 */
947 function compileForm($editForm) {
948 $formContent = '
949 <!-- EDITING FORM -->
950 '.$editForm.'
951
952 <input type="hidden" name="returnUrl" value="'.htmlspecialchars($this->retUrl).'" />
953 <input type="hidden" name="viewUrl" value="'.htmlspecialchars($this->viewUrl).'" />';
954
955 if ($this->returnNewPageId) {
956 $formContent .= '<input type="hidden" name="returnNewPageId" value="1" />';
957 }
958 $formContent .= '<input type="hidden" name="popViewId" value="'.htmlspecialchars($this->viewId).'" />';
959 if ($this->viewId_addParams) {
960 $formContent .= '<input type="hidden" name="popViewId_addParams" value="'.htmlspecialchars($this->viewId_addParams).'" />';
961 }
962 $formContent .= '
963 <input type="hidden" name="closeDoc" value="0" />
964 <input type="hidden" name="doSave" value="0" />
965 <input type="hidden" name="_serialNumber" value="'.md5(microtime()).'" />
966 <input type="hidden" name="_scrollPosition" value="" />' . t3lib_TCEforms::getHiddenTokenField('editRecord');
967
968 return $formContent;
969 }
970
971 /**
972 * Create the checkbox buttons in the bottom of the pages.
973 *
974 * @return string HTML for function menus.
975 */
976 function functionMenus() {
977 if ($GLOBALS['BE_USER']->getTSConfigVal('options.enableShowPalettes')) {
978 // Show palettes:
979 return '
980 <!-- Function menu (checkbox for showing all palettes): -->
981 <br />'.t3lib_BEfunc::getFuncCheck(
982 '',
983 'SET[showPalettes]',
984 $this->MOD_SETTINGS['showPalettes'],
985 'alt_doc.php',
986 t3lib_div::implodeArrayForUrl(
987 '',
988 array_merge($this->R_URL_getvars, array('SET'=>''))
989 ) . t3lib_BEfunc::getUrlToken('editRecord'),'id="checkShowPalettes"') . '<label for="checkShowPalettes">' .
990 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showPalettes', 1) . '</label>';
991 }
992 else {
993 return '';
994 }
995 }
996
997
998 /**
999 * Create shortcut icon
1000 *
1001 * @return string
1002 */
1003 function shortCutLink() {
1004 if ($this->returnUrl == 'close.html' || !$GLOBALS['BE_USER']->mayMakeShortcut()) {
1005 return '';
1006 }
1007 return $this->doc->makeShortcutIcon('returnUrl,edit,defVals,overrideVals,columnsOnly,returnNewPageId,editRegularContentFromId,disHelp,noView',implode(',',array_keys($this->MOD_MENU)),$this->MCONF['name'],1);
1008 }
1009
1010
1011 /**
1012 * Creates open-in-window link
1013 *
1014 * @return string
1015 */
1016 function openInNewWindowLink() {
1017 if ($this->returnUrl == 'close.html') {
1018 return '';
1019 }
1020 $aOnClick = 'vHWin=window.open(\''.t3lib_div::linkThisScript(array('returnUrl'=>'close.html')).'\',\''.md5($this->R_URI).'\',\'width=670,height=500,status=0,menubar=0,scrollbars=1,resizable=1\');vHWin.focus();return false;';
1021 return '<a href="#" onclick="'.htmlspecialchars($aOnClick).'" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.openInNewWindow', TRUE) . '">' .
1022 t3lib_iconWorks::getSpriteIcon('actions-window-open') .
1023 '</a>';
1024 }
1025
1026
1027 /**
1028 * Reads comment messages from TCEforms and prints them in a HTML comment in the bottom of the page.
1029 *
1030 * @return void
1031 */
1032 function tceformMessages() {
1033 if (count($this->tceforms->commentMessages)) {
1034 $tceformMessages = '
1035 <!-- TCEFORM messages
1036 '.htmlspecialchars(implode(LF,$this->tceforms->commentMessages)).'
1037 -->
1038 ';
1039 }
1040 return $tceformMessages;
1041 }
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055 /***************************
1056 *
1057 * Localization stuff
1058 *
1059 ***************************/
1060
1061 /**
1062 * Make selector box for creating new translation for a record or switching to edit the record in an existing language.
1063 * Displays only languages which are available for the current page.
1064 *
1065 * @param string Table name
1066 * @param integer uid for which to create a new language
1067 * @param integer pid of the record
1068 * @return string <select> HTML element (if there were items for the box anyways...)
1069 */
1070 function languageSwitch($table, $uid, $pid=NULL) {
1071 $content = '';
1072
1073 $languageField = $GLOBALS['TCA'][$table]['ctrl']['languageField'];
1074 $transOrigPointerField = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'];
1075
1076 // table editable and activated for languages?
1077 if ($GLOBALS['BE_USER']->check('tables_modify',$table) && $languageField && $transOrigPointerField && !$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable']) {
1078
1079 if(is_null($pid)) {
1080 $row = t3lib_befunc::getRecord($table, $uid, 'pid');
1081 $pid = $row['pid'];
1082 }
1083
1084 // get all avalibale languages for the page
1085 $langRows = $this->getLanguages($pid);
1086
1087 // page available in other languages than default language?
1088 if (is_array($langRows) && count($langRows)>1) {
1089
1090 $rowsByLang = array();
1091 $fetchFields = 'uid,'.$languageField.','.$transOrigPointerField;
1092
1093 // get record in current language
1094 $rowCurrent = t3lib_befunc::getLiveVersionOfRecord($table, $uid, $fetchFields);
1095 if (!is_array($rowCurrent)) {
1096 $rowCurrent = t3lib_befunc::getRecord($table, $uid, $fetchFields);
1097 }
1098
1099 $currentLanguage = $rowCurrent[$languageField];
1100
1101 if ($currentLanguage>-1) { // Disabled for records with [all] language!
1102 // get record in default language if needed
1103 if ($currentLanguage) {
1104 $rowsByLang[0] = t3lib_befunc::getLiveVersionOfRecord($table, $rowCurrent[$transOrigPointerField], $fetchFields);
1105 if (!is_array($rowsByLang[0])) {
1106 $rowsByLang[0] = t3lib_befunc::getRecord($table, $rowCurrent[$transOrigPointerField], $fetchFields);
1107 }
1108 } else {
1109 $rowsByLang[0] = $rowCurrent;
1110 }
1111
1112 // get record in other languages to see what's already available
1113 $translations = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1114 $fetchFields,
1115 $table,
1116 'pid='.intval($pid).
1117 ' AND '.$languageField.'>0'.
1118 ' AND '.$transOrigPointerField.'='.intval($rowsByLang[0]['uid']).
1119 t3lib_BEfunc::deleteClause($table).
1120 t3lib_BEfunc::versioningPlaceholderClause($table)
1121 );
1122 foreach ($translations as $row) {
1123 $rowsByLang[$row[$languageField]] = $row;
1124 }
1125
1126 $langSelItems=array();
1127 foreach ($langRows as $lang) {
1128 if ($GLOBALS['BE_USER']->checkLanguageAccess($lang['uid'])) {
1129
1130 $newTranslation = isset($rowsByLang[$lang['uid']]) ? '' : ' ['.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:labels.new',1).']';
1131
1132 // create url for creating a localized record
1133 if($newTranslation) {
1134 $href = $this->doc->issueCommand(
1135 '&cmd['.$table.']['.$rowsByLang[0]['uid'].'][localize]='.$lang['uid'],
1136 $this->backPath.'alt_doc.php?justLocalized='.rawurlencode($table.':'.$rowsByLang[0]['uid'].':'.$lang['uid']).'&returnUrl='.rawurlencode($this->retUrl) . t3lib_BEfunc::getUrlToken('editRecord')
1137 );
1138
1139 // create edit url
1140 } else {
1141 $href = $this->backPath.'alt_doc.php?';
1142 $href .= '&edit['.$table.']['.$rowsByLang[$lang['uid']]['uid'].']=edit';
1143 $href .= '&returnUrl='.rawurlencode($this->retUrl) . t3lib_BEfunc::getUrlToken('editRecord');
1144 }
1145
1146 $langSelItems[$lang['uid']]='
1147 <option value="'.htmlspecialchars($href).'"'.($currentLanguage==$lang['uid']?' selected="selected"':'').'>'.htmlspecialchars($lang['title'].$newTranslation).'</option>';
1148 }
1149 }
1150
1151 // If any languages are left, make selector:
1152 if (count($langSelItems)>1) {
1153 $onChange = 'if(this.options[this.selectedIndex].value){window.location.href=(this.options[this.selectedIndex].value);}';
1154 $content = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_general.xml:LGL.language',1).' <select name="_langSelector" onchange="'.htmlspecialchars($onChange).'">
1155 '.implode('',$langSelItems).'
1156 </select>';
1157 }
1158 }
1159 }
1160 }
1161 return $content;
1162 }
1163
1164
1165 /**
1166 * Redirects to alt_doc with new parameters to edit a just created localized record
1167 *
1168 * @param string String passed by GET &justLocalized=
1169 * @return void
1170 */
1171 function localizationRedirect($justLocalized) {
1172 list($table,$orig_uid,$language) = explode(':',$justLocalized);
1173
1174 if ($GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) {
1175 $localizedRecord = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
1176 'uid',
1177 $table,
1178 $GLOBALS['TCA'][$table]['ctrl']['languageField'].'='.intval($language).' AND '.
1179 $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'].'='.intval($orig_uid).
1180 t3lib_BEfunc::deleteClause($table).
1181 t3lib_BEfunc::versioningPlaceholderClause($table)
1182 );
1183
1184 if (is_array($localizedRecord)) {
1185 // Create parameters and finally run the classic page module for creating a new page translation
1186 $params = '&edit['.$table.']['.$localizedRecord['uid'].']=edit';
1187 $returnUrl = '&returnUrl='.rawurlencode(t3lib_div::sanitizeLocalUrl(t3lib_div::_GP('returnUrl')));
1188 $location = $GLOBALS['BACK_PATH'].'alt_doc.php?'.$params.$returnUrl . t3lib_BEfunc::getUrlToken('editRecord');
1189
1190 t3lib_utility_Http::redirect($location);
1191 }
1192 }
1193 }
1194
1195
1196 /**
1197 * Returns sys_language records.
1198 *
1199 * @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)
1200 * @return array Language records including faked record for default language
1201 */
1202 function getLanguages($id) {
1203 $modSharedTSconfig = t3lib_BEfunc::getModTSconfig($id, 'mod.SHARED');
1204
1205 // fallback non sprite-configuration
1206 if (preg_match('/\.gif$/', $modSharedTSconfig['properties']['defaultLanguageFlag'])) {
1207 $modSharedTSconfig['properties']['defaultLanguageFlag'] = str_replace('.gif', '', $modSharedTSconfig['properties']['defaultLanguageFlag']);
1208 }
1209
1210 $languages = array(
1211 0 => array(
1212 'uid' => 0,
1213 'pid' => 0,
1214 'hidden' => 0,
1215 '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'),
1216 'flag' => $modSharedTSconfig['properties']['defaultLanguageFlag'],
1217 )
1218 );
1219
1220 $exQ = $GLOBALS['BE_USER']->isAdmin() ? '' : ' AND sys_language.hidden=0';
1221 if ($id) {
1222 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1223 'sys_language.*',
1224 'pages_language_overlay,sys_language',
1225 'pages_language_overlay.sys_language_uid=sys_language.uid AND pages_language_overlay.pid='.intval($id).$exQ,
1226 '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',
1227 'sys_language.title'
1228 );
1229 } else {
1230 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1231 'sys_language.*',
1232 'sys_language',
1233 'sys_language.hidden=0',
1234 '',
1235 'sys_language.title'
1236 );
1237 }
1238 if ($rows) {
1239 foreach ($rows as $row) {
1240 $languages[$row['uid']] = $row;
1241 }
1242 }
1243 return $languages;
1244 }
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255 /***************************
1256 *
1257 * Other functions
1258 *
1259 ***************************/
1260
1261 /**
1262 * Fix $this->editconf if versioning applies to any of the records
1263 *
1264 * @param array Mapping between old and new ids if auto-versioning has been performed.
1265 * @return void
1266 */
1267 function fixWSversioningInEditConf($mapArray=FALSE) {
1268
1269 // Traverse the editConf array
1270 if (is_array($this->editconf)) {
1271 foreach($this->editconf as $table => $conf) { // Tables:
1272 if (is_array($conf) && $GLOBALS['TCA'][$table]) {
1273
1274 // Traverse the keys/comments of each table (keys can be a commalist of uids)
1275 $newConf = array();
1276 foreach($conf as $cKey => $cmd) {
1277 if ($cmd=='edit') {
1278 // Traverse the ids:
1279 $ids = t3lib_div::trimExplode(',', $cKey, 1);
1280 foreach($ids as $idKey => $theUid) {
1281 if (is_array($mapArray)) {
1282 if ($mapArray[$table][$theUid]) {
1283 $ids[$idKey] = $mapArray[$table][$theUid];
1284 }
1285 } else { // Default, look for versions in workspace for record:
1286 $calcPRec = $this->getRecordForEdit($table,$theUid);
1287 if (is_array($calcPRec)) {
1288 // Setting UID again if it had changed, eg. due to workspace versioning.
1289 $ids[$idKey] = $calcPRec['uid'];
1290 }
1291 }
1292 #else unset($ids[$idKey]);
1293 }
1294
1295 // Add the possibly manipulated IDs to the new-build newConf array:
1296 $newConf[implode(',',$ids)] = $cmd;
1297 } else {
1298 $newConf[$cKey] = $cmd;
1299 }
1300 }
1301 // Store the new conf array:
1302 $this->editconf[$table] = $newConf;
1303 }
1304 }
1305 }
1306 }
1307
1308 /**
1309 * Get record for editing.
1310 *
1311 * @param string Table name
1312 * @param integer Record UID
1313 * @return array Returns record to edit, FALSE if none
1314 */
1315 function getRecordForEdit($table,$theUid) {
1316
1317 // Fetch requested record:
1318 $reqRecord = t3lib_BEfunc::getRecord($table,$theUid,'uid,pid');
1319
1320 if (is_array($reqRecord)) {
1321 // If workspace is OFFLINE:
1322 if ($GLOBALS['BE_USER']->workspace!=0) {
1323
1324 // Check for versioning support of the table:
1325 if ($GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
1326
1327 // If the record is already a version of "something" pass it by.
1328 if ($reqRecord['pid']==-1) {
1329
1330 // (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)
1331 return $reqRecord;
1332 } else { // The input record was online and an offline version must be found or made:
1333
1334 // Look for version of this workspace:
1335 $versionRec = t3lib_BEfunc::getWorkspaceVersionOfRecord($GLOBALS['BE_USER']->workspace, $table, $reqRecord['uid'],'uid,pid,t3ver_oid');
1336 return is_array($versionRec) ? $versionRec : $reqRecord;
1337 }
1338 } 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.
1339 } else return $reqRecord; // In ONLINE workspace, just return the originally requested record:
1340 } else return FALSE; // Return FALSE because the table/uid was not found anyway.
1341 }
1342
1343 /**
1344 * 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
1345 *
1346 * @return void
1347 */
1348 function editRegularContentFromId() {
1349 if (t3lib_extMgm::isLoaded('cms')) {
1350 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1351 'uid',
1352 'tt_content',
1353 'pid='.intval($this->editRegularContentFromId).
1354 t3lib_BEfunc::deleteClause('tt_content').
1355 t3lib_BEfunc::versioningPlaceholderClause('tt_content').
1356 ' AND colPos=0 AND sys_language_uid=0',
1357 '',
1358 'sorting'
1359 );
1360 if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) {
1361 $ecUids=array();
1362 while($ecRec = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
1363 $ecUids[]=$ecRec['uid'];
1364 }
1365 $this->editconf['tt_content'][implode(',',$ecUids)]='edit';
1366 }
1367 }
1368 }
1369
1370 /**
1371 * Populates the variables $this->storeArray, $this->storeUrl, $this->storeUrlMd5
1372 *
1373 * @return void
1374 * @see makeDocSel()
1375 */
1376 function compileStoreDat() {
1377 $this->storeArray = t3lib_div::compileSelectedGetVarsFromArray('edit,defVals,overrideVals,columnsOnly,disHelp,noView,editRegularContentFromId',$this->R_URL_getvars);
1378 $this->storeUrl = t3lib_div::implodeArrayForUrl('',$this->storeArray);
1379 $this->storeUrlMd5 = md5($this->storeUrl);
1380 }
1381
1382 /**
1383 * Function used to look for configuration of buttons in the form: Fx. disabling buttons or showing them at various positions.
1384 *
1385 * @param string The table for which the configuration may be specific
1386 * @param string The option for look for. Default is checking if the saveDocNew button should be displayed.
1387 * @return string Return value fetched from USER TSconfig
1388 */
1389 function getNewIconMode($table, $key = 'saveDocNew') {
1390 $TSconfig = $GLOBALS['BE_USER']->getTSConfig('options.'.$key);
1391 $output = trim(isset($TSconfig['properties'][$table]) ? $TSconfig['properties'][$table] : $TSconfig['value']);
1392 return $output;
1393 }
1394
1395 /**
1396 * Handling the closing of a document
1397 *
1398 * @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
1399 * @return void
1400 */
1401 function closeDocument($code=0) {
1402
1403 // If current document is found in docHandler,
1404 // then unset it, possibly unset it ALL and finally, write it to the session data
1405 if (isset($this->docHandler[$this->storeUrlMd5])) {
1406
1407 // add the closing document to the recent documents
1408 $recentDocs = $GLOBALS['BE_USER']->getModuleData('opendocs::recent');
1409 if (!is_array($recentDocs)) {
1410 $recentDocs = array();
1411 }
1412 $closedDoc = $this->docHandler[$this->storeUrlMd5];
1413 $recentDocs = array_merge(array($this->storeUrlMd5 => $closedDoc), $recentDocs);
1414 if (count($recentDocs) > 8) {
1415 $recentDocs = array_slice($recentDocs, 0, 8);
1416 }
1417
1418 // remove it from the list of the open documents
1419 unset($this->docHandler[$this->storeUrlMd5]);
1420 if ($code == '3') {
1421 $recentDocs = array_merge($this->docHandler, $recentDocs);
1422 $this->docHandler = array();
1423 }
1424 $GLOBALS['BE_USER']->pushModuleData('opendocs::recent', $recentDocs);
1425 $GLOBALS['BE_USER']->pushModuleData('alt_doc.php', array($this->docHandler, $this->docDat[1]));
1426 t3lib_BEfunc::setUpdateSignal('tx_opendocs::updateNumber', count($this->docHandler));
1427 }
1428
1429
1430 // 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...)
1431 if ($this->returnEditConf && $this->retUrl!='dummy.php') {
1432 $this->retUrl.='&returnEditConf='.rawurlencode(serialize($this->editconf));
1433 }
1434
1435 // If code is NOT set OR set to 1, then make a header location redirect to $this->retUrl
1436 if (!$code || $code==1) {
1437 t3lib_utility_Http::redirect($this->retUrl);
1438 } else {
1439 $this->setDocument('',$this->retUrl);
1440 }
1441 }
1442
1443 /**
1444 * Redirects to the document pointed to by $currentDocFromHandlerMD5 OR $retUrl (depending on some internal calculations).
1445 * Most likely you will get a header-location redirect from this function.
1446 *
1447 * @param string Pointer to the document in the docHandler array
1448 * @param string Alternative/Default retUrl
1449 * @return void
1450 */
1451 function setDocument($currentDocFromHandlerMD5='',$retUrl='alt_doc_nodoc.php') {
1452 if (!t3lib_extMgm::isLoaded('cms') && !strcmp($retUrl,'alt_doc_nodoc.php')) return;
1453
1454 if (!$this->modTSconfig['properties']['disableDocSelector'] && is_array($this->docHandler) && count($this->docHandler)) {
1455 if (isset($this->docHandler[$currentDocFromHandlerMD5])) {
1456 $setupArr=$this->docHandler[$currentDocFromHandlerMD5];
1457 } else {
1458 reset($this->docHandler);
1459 $setupArr=current($this->docHandler);
1460 }
1461 if ($setupArr[2]) {
1462 $sParts = parse_url(t3lib_div::getIndpEnv('REQUEST_URI'));
1463 $retUrl = $sParts['path'].'?'.$setupArr[2].'&returnUrl='.rawurlencode($retUrl);
1464 }
1465 }
1466 t3lib_utility_Http::redirect($retUrl);
1467 }
1468 }
1469
1470
1471 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/alt_doc.php'])) {
1472 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/alt_doc.php']);
1473 }
1474
1475
1476
1477 // Make instance:
1478 $SOBE = t3lib_div::makeInstance('SC_alt_doc');
1479
1480 // Preprocessing, storing data if submitted to
1481 $SOBE->preInit();
1482
1483 $formprotection = t3lib_formprotection_Factory::get();
1484
1485 if ($SOBE->doProcessData()) { // Checks, if a save button has been clicked (or the doSave variable is sent)
1486 if ($formprotection->validateToken(t3lib_div::_GP('formToken'), 'editRecord')) {
1487 $SOBE->processData();
1488 }
1489 }
1490
1491 // Main:
1492 $SOBE->init();
1493 $SOBE->main();
1494 $SOBE->printContent();
1495
1496 ?>