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