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