[API][!!!] Fix API compatibility break in tslib_pibase
[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.decimalSign = ".";
424 }
425 var TS = new typoSetup();
426
427 // Info view:
428 function launchView(table,uid,bP) { //
429 var backPath= bP ? bP : "";
430 var thePreviewWindow="";
431 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");
432 if (thePreviewWindow && thePreviewWindow.focus) {
433 thePreviewWindow.focus();
434 }
435 }
436 function deleteRecord(table,id,url) { //
437 if (
438 ' . ($GLOBALS['BE_USER']->jsConfirmation(4) ? 'confirm(' . $GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->getLL('deleteWarning')) . ')' : '1==1') . '
439 ) {
440 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";
441 }
442 return false;
443 }
444 '.(isset($_POST['_savedokview_x']) && $this->popViewId ?
445 'if (window.opener) { '.
446 t3lib_BEfunc::viewOnClick($this->popViewId,'',t3lib_BEfunc::BEgetRootLine($this->popViewId),'',$this->viewUrl,$this->popViewId_addParams,FALSE).
447 ' } else { '.
448 t3lib_BEfunc::viewOnClick($this->popViewId,'',t3lib_BEfunc::BEgetRootLine($this->popViewId),'',$this->viewUrl,$this->popViewId_addParams).
449 ' } '
450 : '')
451 );
452
453 // Setting up the context sensitive menu:
454 $this->doc->getContextMenuCode();
455 $this->doc->bodyTagAdditions = 'onload="window.scrollTo(0,'.t3lib_utility_Math::forceIntegerInRange(t3lib_div::_GP('_scrollPosition'),0,10000).');"';
456 }
457
458 /**
459 * Main module operation
460 *
461 * @return void
462 */
463 function main() {
464
465 // Begin edit:
466 if (is_array($this->editconf)) {
467
468 // Initialize TCEforms (rendering the forms)
469 $this->tceforms = t3lib_div::makeInstance('t3lib_TCEforms');
470 $this->tceforms->initDefaultBEMode();
471 $this->tceforms->doSaveFieldName = 'doSave';
472 $this->tceforms->localizationMode = t3lib_div::inList('text,media',$this->localizationMode) ? $this->localizationMode : ''; // text,media is keywords defined in TYPO3 Core API..., see "l10n_cat"
473 $this->tceforms->returnUrl = $this->R_URI;
474 $this->tceforms->palettesCollapsed = !$this->MOD_SETTINGS['showPalettes'];
475 $this->tceforms->disableRTE = !$GLOBALS['BE_USER']->isRTE();
476 $this->tceforms->enableClickMenu = TRUE;
477 $this->tceforms->enableTabMenu = TRUE;
478
479 // Clipboard is initialized:
480 $this->tceforms->clipObj = t3lib_div::makeInstance('t3lib_clipboard'); // Start clipboard
481 $this->tceforms->clipObj->initializeClipboard(); // Initialize - reads the clipboard content from the user session
482
483 // Setting external variables:
484 $this->tceforms->edit_showFieldHelp = $GLOBALS['BE_USER']->uc['edit_showFieldHelp'];
485
486 if ($this->editRegularContentFromId) {
487 $this->editRegularContentFromId();
488 }
489
490
491 // Creating the editing form, wrap it with buttons, document selector etc.
492 $editForm = $this->makeEditForm();
493
494 if ($editForm) {
495 $this->firstEl = reset($this->elementsData);
496
497 // Checking if the currently open document is stored in the list of "open documents" - if not, then add it:
498 if ((strcmp($this->docDat[1], $this->storeUrlMd5) || !isset($this->docHandler[$this->storeUrlMd5])) && !$this->dontStoreDocumentRef) {
499 $this->docHandler[$this->storeUrlMd5] = array($this->storeTitle, $this->storeArray, $this->storeUrl, $this->firstEl);
500 $GLOBALS['BE_USER']->pushModuleData('alt_doc.php', array($this->docHandler, $this->storeUrlMd5));
501 t3lib_BEfunc::setUpdateSignal('tx_opendocs::updateNumber', count($this->docHandler));
502 }
503
504
505 // Module configuration
506 $this->modTSconfig = ($this->viewId ? t3lib_BEfunc::getModTSconfig($this->viewId,'mod.xMOD_alt_doc') : array());
507
508 $body.= $this->tceforms->printNeededJSFunctions_top();
509 $body.= $this->compileForm($editForm);
510 $body.= $this->tceforms->printNeededJSFunctions();
511 $body.= $this->functionMenus();
512 $body.= $this->tceformMessages();
513 }
514 }
515
516 // Access check...
517 // The page will show only if there is a valid page and if this page may be viewed by the user
518 $this->pageinfo = t3lib_BEfunc::readPageAccess($this->viewId, $this->perms_clause);
519
520 // Setting up the buttons and markers for docheader
521 $docHeaderButtons = $this->getButtons();
522 $markers = array(
523 'LANGSELECTOR' => $this->langSelector(),
524 'EXTRAHEADER' => $this->extraFormHeaders(),
525 'CSH' => $docHeaderButtons['csh'],
526 'CONTENT' => $body
527 );
528
529 // Build the <body> for the module
530 $this->content = $this->doc->startPage('TYPO3 Edit Document');
531 $this->content.= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
532 $this->content.= $this->doc->endPage();
533 $this->content = $this->doc->insertStylesAndJS($this->content);
534 }
535
536
537 /**
538 * Outputting the accumulated content to screen
539 *
540 * @return void
541 */
542 function printContent() {
543 echo $this->content;
544 }
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565 /***************************
566 *
567 * Sub-content functions, rendering specific parts of the module content.
568 *
569 ***************************/
570
571 /**
572 * Creates the editing form with TCEforms, based on the input from GPvars.
573 *
574 * @return string HTML form elements wrapped in tables
575 */
576 function makeEditForm() {
577
578 // Initialize variables:
579 $this->elementsData=array();
580 $this->errorC=0;
581 $this->newC=0;
582 $thePrevUid='';
583 $editForm='';
584 $trData = NULL;
585
586 // Traverse the GPvar edit array
587 foreach($this->editconf as $table => $conf) { // Tables:
588 if (is_array($conf) && $GLOBALS['TCA'][$table] && $GLOBALS['BE_USER']->check('tables_modify',$table)) {
589
590 // Traverse the keys/comments of each table (keys can be a commalist of uids)
591 foreach($conf as $cKey => $cmd) {
592 if ($cmd=='edit' || $cmd=='new') {
593
594 // Get the ids:
595 $ids = t3lib_div::trimExplode(',',$cKey,1);
596
597 // Traverse the ids:
598 foreach($ids as $theUid) {
599
600 // 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...)
601 // First, resetting flags.
602 $hasAccess = 1;
603 $deniedAccessReason = '';
604 $deleteAccess = 0;
605 $this->viewId = 0;
606
607 // If the command is to create a NEW record...:
608 if ($cmd=='new') {
609 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.
610
611 // Find parent page on which the new record reside
612 if ($theUid<0) { // Less than zero - find parent page
613 $calcPRec=t3lib_BEfunc::getRecord($table,abs($theUid));
614 $calcPRec=t3lib_BEfunc::getRecord('pages',$calcPRec['pid']);
615 } else { // always a page
616 $calcPRec=t3lib_BEfunc::getRecord('pages',abs($theUid));
617 }
618
619 // Now, calculate whether the user has access to creating new records on this position:
620 if (is_array($calcPRec)) {
621 // Permissions for the parent page
622 $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms($calcPRec);
623 if ($table=='pages') { // If pages:
624 $hasAccess = $CALC_PERMS&8 ? 1 : 0;
625 #$this->viewId = $calcPRec['pid'];
626 $this->viewId = 0;
627 } else {
628 $hasAccess = $CALC_PERMS&16 ? 1 : 0;
629 $this->viewId = $calcPRec['uid'];
630 }
631 }
632 }
633 $this->dontStoreDocumentRef=1; // Don't save this document title in the document selector if the document is new.
634 } else { // Edit:
635 $calcPRec = t3lib_BEfunc::getRecord($table,$theUid);
636 t3lib_BEfunc::fixVersioningPid($table,$calcPRec);
637 if (is_array($calcPRec)) {
638 if ($table=='pages') { // If pages:
639 $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms($calcPRec);
640 $hasAccess = $CALC_PERMS&2 ? 1 : 0;
641 $deleteAccess = $CALC_PERMS&4 ? 1 : 0;
642 $this->viewId = $calcPRec['uid'];
643 } else {
644 // Fetching pid-record first
645 $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages', $calcPRec['pid']));
646 $hasAccess = $CALC_PERMS&16 ? 1 : 0;
647 $deleteAccess = $CALC_PERMS&16 ? 1 : 0;
648 $this->viewId = $calcPRec['pid'];
649
650 // Adding "&L=xx" if the record being edited has a languageField with a value larger than zero!
651 if ($GLOBALS['TCA'][$table]['ctrl']['languageField'] && $calcPRec[$GLOBALS['TCA'][$table]['ctrl']['languageField']] > 0) {
652 $this->viewId_addParams = '&L=' . $calcPRec[$GLOBALS['TCA'][$table]['ctrl']['languageField']];
653 }
654 }
655
656 // Check internals regarding access:
657 if ($hasAccess) {
658 $hasAccess = $GLOBALS['BE_USER']->recordEditAccessInternals($table, $calcPRec);
659 $deniedAccessReason = $GLOBALS['BE_USER']->errorMsg;
660 }
661 } else $hasAccess = 0;
662 }
663
664 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/alt_doc.php']['makeEditForm_accessCheck'])) {
665 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/alt_doc.php']['makeEditForm_accessCheck'] as $_funcRef) {
666 $_params = array(
667 'table' => $table,
668 'uid' => $theUid,
669 'cmd' => $cmd,
670 'hasAccess' => $hasAccess
671 );
672 $hasAccess = t3lib_div::callUserFunction($_funcRef, $_params, $this);
673 }
674 }
675
676 // 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:
677
678 if ($hasAccess) {
679 $prevPageID = is_object($trData)?$trData->prevPageID:'';
680 $trData = t3lib_div::makeInstance('t3lib_transferData');
681 $trData->addRawData = TRUE;
682 $trData->defVals = $this->defVals;
683 $trData->lockRecords=1;
684 $trData->disableRTE = !$GLOBALS['BE_USER']->isRTE();
685 $trData->prevPageID = $prevPageID;
686 $trData->fetchRecord($table,$theUid,$cmd=='new'?'new':''); // 'new'
687 $rec = reset($trData->regTableItems_data);
688 $rec['uid'] = $cmd=='new' ? uniqid('NEW') : $theUid;
689 if ($cmd=='new') {
690 $rec['pid'] = $theUid=='prev'?$thePrevUid:$theUid;
691 }
692 $this->elementsData[]=array(
693 'table' => $table,
694 'uid' => $rec['uid'],
695 'pid' => $rec['pid'],
696 'cmd' => $cmd,
697 'deleteAccess' => $deleteAccess
698 );
699
700 // Now, render the form:
701 if (is_array($rec)) {
702
703 // Setting visual path / title of form:
704 $this->generalPathOfForm = $this->tceforms->getRecordPath($table,$rec);
705 if (!$this->storeTitle) {
706 $this->storeTitle = $this->recTitle ? htmlspecialchars($this->recTitle) : t3lib_BEfunc::getRecordTitle($table,$rec,TRUE);
707 }
708
709 // Setting variables in TCEforms object:
710 $this->tceforms->hiddenFieldList = '';
711 $this->tceforms->globalShowHelp = $this->disHelp ? 0 : 1;
712 if (is_array($this->overrideVals[$table])) {
713 $this->tceforms->hiddenFieldListArr = array_keys($this->overrideVals[$table]);
714 }
715
716 // Register default language labels, if any:
717 $this->tceforms->registerDefaultLanguageData($table,$rec);
718
719 // Create form for the record (either specific list of fields or the whole record):
720 $panel = '';
721 if ($this->columnsOnly) {
722 if(is_array($this->columnsOnly)){
723 $panel.= $this->tceforms->getListedFields($table,$rec,$this->columnsOnly[$table]);
724 } else {
725 $panel.= $this->tceforms->getListedFields($table,$rec,$this->columnsOnly);
726 }
727 } else {
728 $panel.= $this->tceforms->getMainFields($table,$rec);
729 }
730 $panel = $this->tceforms->wrapTotal($panel,$rec,$table);
731
732 // Setting the pid value for new records:
733 if ($cmd=='new') {
734 $panel.= '<input type="hidden" name="data['.$table.']['.$rec['uid'].'][pid]" value="'.$rec['pid'].'" />';
735 $this->newC++;
736 }
737
738 // Display "is-locked" message:
739 if ($lockInfo = t3lib_BEfunc::isRecordLocked($table, $rec['uid'])) {
740 $lockedMessage = t3lib_div::makeInstance(
741 't3lib_FlashMessage',
742 htmlspecialchars($lockInfo['msg']),
743 '',
744 t3lib_FlashMessage::WARNING
745 );
746 t3lib_FlashMessageQueue::addMessage($lockedMessage);
747 }
748
749 // Combine it all:
750 $editForm .= $panel;
751 }
752
753 $thePrevUid = $rec['uid'];
754 } else {
755 $this->errorC++;
756 $editForm .= $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.noEditPermission',1) . '<br /><br />' .
757 ($deniedAccessReason ? 'Reason: ' . htmlspecialchars($deniedAccessReason) . '<br /><br />' : '');
758 }
759 }
760 }
761 }
762 }
763 }
764
765 return $editForm;
766 }
767
768 /**
769 * Create the panel of buttons for submitting the form or otherwise perform operations.
770 *
771 * @return array all available buttons as an assoc. array
772 */
773 protected function getButtons() {
774 $buttons = array(
775 'save' => '',
776 'save_view' => '',
777 'save_new' => '',
778 'save_close' => '',
779 'close' => '',
780 'delete' => '',
781 'undo' => '',
782 'history' => '',
783 'columns_only' => '',
784 'csh' => '',
785 'translation_save' => '',
786 'translation_saveclear' => ''
787 );
788
789 // Render SAVE type buttons:
790 // The action of each button is decided by its name attribute. (See doProcessData())
791 if (!$this->errorC && !$GLOBALS['TCA'][$this->firstEl['table']]['ctrl']['readOnly']) {
792
793 // SAVE button:
794 $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) . '" />' ));
795
796 // SAVE / VIEW button:
797 if ($this->viewId && !$this->noView && t3lib_extMgm::isLoaded('cms') && $this->getNewIconMode($this->firstEl['table'], 'saveDocView')) {
798 $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) . '" />'));
799 }
800
801 // SAVE / NEW button:
802 if (count($this->elementsData)==1 && $this->getNewIconMode($this->firstEl['table'])) {
803 $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) . '" />'));
804 }
805
806 // SAVE / CLOSE
807 $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) . '" />'));
808
809 // FINISH TRANSLATION / SAVE / CLOSE
810 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['explicitConfirmationOfTranslation']) {
811 $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) . '" />';
812 $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) . '" />';
813 }
814 }
815
816 // CLOSE button:
817 $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) . '">' .
818 t3lib_iconWorks::getSpriteIcon('actions-document-close') .
819 '</a>';
820
821
822 // DELETE + UNDO buttons:
823 if (!$this->errorC && !$GLOBALS['TCA'][$this->firstEl['table']]['ctrl']['readOnly'] && count($this->elementsData)==1) {
824 if ($this->firstEl['cmd']!='new' && t3lib_utility_Math::canBeInterpretedAsInteger($this->firstEl['uid'])) {
825
826 // Delete:
827 if ($this->firstEl['deleteAccess'] && !$GLOBALS['TCA'][$this->firstEl['table']]['ctrl']['readOnly'] && !$this->getNewIconMode($this->firstEl['table'],'disableDelete')) {
828 $aOnClick = 'return deleteRecord(\''.$this->firstEl['table'].'\',\''.$this->firstEl['uid'].'\',unescape(\''.rawurlencode($this->retUrl).'\'));';
829 $buttons['delete'] = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '" title="' . $GLOBALS['LANG']->getLL('deleteItem', TRUE) . '">' .
830 t3lib_iconWorks::getSpriteIcon('actions-edit-delete') .
831 '</a>';
832 }
833
834 // Undo:
835 $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');
836 if ($undoButtonR = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($undoRes)) {
837 $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;';
838 $buttons['undo'] = '<a href="#" onclick="'.htmlspecialchars($aOnClick).'"'.
839 ' 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')))) . '">' .
840 t3lib_iconWorks::getSpriteIcon('actions-edit-undo') .
841 '</a>';
842 }
843 if ($this->getNewIconMode($this->firstEl['table'],'showHistory')) {
844 $aOnClick = 'window.location.href=\'show_rechis.php?element='.rawurlencode($this->firstEl['table'].':'.$this->firstEl['uid']).'&returnUrl='.rawurlencode($this->R_URI).'\'; return false;';
845 $buttons['history'] = '<a href="#" onclick="'.htmlspecialchars($aOnClick).'">'.
846 t3lib_iconWorks::getSpriteIcon('actions-document-history-open') .
847 '</a>';
848 }
849
850 // If only SOME fields are shown in the form, this will link the user to the FULL form:
851 if ($this->columnsOnly) {
852 $buttons['columns_only'] = '<a href="'.htmlspecialchars($this->R_URI.'&columnsOnly=').'" title="' . $GLOBALS['LANG']->getLL('editWholeRecord', TRUE) . '">' .
853 t3lib_iconWorks::getSpriteIcon('actions-document-open') .
854 '</a>';
855 }
856 }
857 }
858
859 // add the CSH icon
860 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'TCEforms', $GLOBALS['BACK_PATH'], '', TRUE);
861 $buttons['shortcut'] = $this->shortCutLink();
862 $buttons['open_in_new_window'] = $this->openInNewWindowLink();
863 return $buttons;
864 }
865
866 /**
867 * Returns the language switch/selector for editing,
868 * show only when a single record is edited
869 * - multiple records are too confusing
870 * @return string the HTML
871 */
872 function langSelector() {
873 $langSelector = '';
874 if (count($this->elementsData) == 1) {
875 $langSelector = $this->languageSwitch($this->firstEl['table'], $this->firstEl['uid'], $this->firstEl['pid']);
876 }
877 return $langSelector;
878 }
879
880
881 /**
882 * Compiles the extra form headers if the tceforms
883 *
884 * @return string the HTML
885 */
886 function extraFormHeaders() {
887 $extraTemplate = '';
888
889 if (is_array($this->tceforms->extraFormHeaders)) {
890 $extraTemplate = t3lib_parsehtml::getSubpart($this->doc->moduleTemplate, '###DOCHEADER_EXTRAHEADER###');
891 $extraTemplate = t3lib_parsehtml::substituteMarker($extraTemplate, '###EXTRAHEADER###', implode(LF, $this->tceforms->extraFormHeaders));
892 }
893 return $extraTemplate;
894 }
895
896
897 /**
898 * Put together the various elements (buttons, selectors, form) into a table
899 *
900 * @param string HTML form.
901 * @return string Composite HTML
902 */
903 function compileForm($editForm) {
904 $formContent = '
905 <!-- EDITING FORM -->
906 '.$editForm.'
907
908 <input type="hidden" name="returnUrl" value="'.htmlspecialchars($this->retUrl).'" />
909 <input type="hidden" name="viewUrl" value="'.htmlspecialchars($this->viewUrl).'" />';
910
911 if ($this->returnNewPageId) {
912 $formContent .= '<input type="hidden" name="returnNewPageId" value="1" />';
913 }
914 $formContent .= '<input type="hidden" name="popViewId" value="'.htmlspecialchars($this->viewId).'" />';
915 if ($this->viewId_addParams) {
916 $formContent .= '<input type="hidden" name="popViewId_addParams" value="'.htmlspecialchars($this->viewId_addParams).'" />';
917 }
918 $formContent .= '
919 <input type="hidden" name="closeDoc" value="0" />
920 <input type="hidden" name="doSave" value="0" />
921 <input type="hidden" name="_serialNumber" value="'.md5(microtime()).'" />
922 <input type="hidden" name="_scrollPosition" value="" />' . t3lib_TCEforms::getHiddenTokenField('editRecord');
923
924 return $formContent;
925 }
926
927 /**
928 * Create the checkbox buttons in the bottom of the pages.
929 *
930 * @return string HTML for function menus.
931 */
932 function functionMenus() {
933 if ($GLOBALS['BE_USER']->getTSConfigVal('options.enableShowPalettes')) {
934 // Show palettes:
935 return '
936 <!-- Function menu (checkbox for showing all palettes): -->
937 <br />'.t3lib_BEfunc::getFuncCheck(
938 '',
939 'SET[showPalettes]',
940 $this->MOD_SETTINGS['showPalettes'],
941 'alt_doc.php',
942 t3lib_div::implodeArrayForUrl(
943 '',
944 array_merge($this->R_URL_getvars, array('SET'=>''))
945 ) . t3lib_BEfunc::getUrlToken('editRecord'),'id="checkShowPalettes"') . '<label for="checkShowPalettes">' .
946 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showPalettes', 1) . '</label>';
947 }
948 else {
949 return '';
950 }
951 }
952
953
954 /**
955 * Create shortcut icon
956 *
957 * @return string
958 */
959 function shortCutLink() {
960 if ($this->returnUrl == 'close.html' || !$GLOBALS['BE_USER']->mayMakeShortcut()) {
961 return '';
962 }
963 return $this->doc->makeShortcutIcon('returnUrl,edit,defVals,overrideVals,columnsOnly,returnNewPageId,editRegularContentFromId,disHelp,noView',implode(',',array_keys($this->MOD_MENU)),$this->MCONF['name'],1);
964 }
965
966
967 /**
968 * Creates open-in-window link
969 *
970 * @return string
971 */
972 function openInNewWindowLink() {
973 if ($this->returnUrl == 'close.html') {
974 return '';
975 }
976 $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;';
977 return '<a href="#" onclick="'.htmlspecialchars($aOnClick).'" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.openInNewWindow', TRUE) . '">' .
978 t3lib_iconWorks::getSpriteIcon('actions-window-open') .
979 '</a>';
980 }
981
982
983 /**
984 * Reads comment messages from TCEforms and prints them in a HTML comment in the bottom of the page.
985 *
986 * @return void
987 */
988 function tceformMessages() {
989 if (count($this->tceforms->commentMessages)) {
990 $tceformMessages = '
991 <!-- TCEFORM messages
992 '.htmlspecialchars(implode(LF,$this->tceforms->commentMessages)).'
993 -->
994 ';
995 }
996 return $tceformMessages;
997 }
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011 /***************************
1012 *
1013 * Localization stuff
1014 *
1015 ***************************/
1016
1017 /**
1018 * Make selector box for creating new translation for a record or switching to edit the record in an existing language.
1019 * Displays only languages which are available for the current page.
1020 *
1021 * @param string $table Table name
1022 * @param integer $uid uid for which to create a new language
1023 * @param integer $pid pid of the record
1024 * @return string <select> HTML element (if there were items for the box anyways...)
1025 */
1026 function languageSwitch($table, $uid, $pid=NULL) {
1027 $content = '';
1028
1029 $languageField = $GLOBALS['TCA'][$table]['ctrl']['languageField'];
1030 $transOrigPointerField = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'];
1031
1032 // table editable and activated for languages?
1033 if ($GLOBALS['BE_USER']->check('tables_modify',$table) && $languageField && $transOrigPointerField && !$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable']) {
1034
1035 if(is_null($pid)) {
1036 $row = t3lib_befunc::getRecord($table, $uid, 'pid');
1037 $pid = $row['pid'];
1038 }
1039
1040 // get all avalibale languages for the page
1041 $langRows = $this->getLanguages($pid);
1042
1043 // page available in other languages than default language?
1044 if (is_array($langRows) && count($langRows)>1) {
1045
1046 $rowsByLang = array();
1047 $fetchFields = 'uid,'.$languageField.','.$transOrigPointerField;
1048
1049 // get record in current language
1050 $rowCurrent = t3lib_befunc::getLiveVersionOfRecord($table, $uid, $fetchFields);
1051 if (!is_array($rowCurrent)) {
1052 $rowCurrent = t3lib_befunc::getRecord($table, $uid, $fetchFields);
1053 }
1054
1055 $currentLanguage = $rowCurrent[$languageField];
1056
1057 if ($currentLanguage > -1) { // Disabled for records with [all] language!
1058 // get record in default language if needed
1059 if ($currentLanguage && $rowCurrent[$transOrigPointerField]) {
1060 $rowsByLang[0] = t3lib_befunc::getLiveVersionOfRecord($table, $rowCurrent[$transOrigPointerField], $fetchFields);
1061 if (!is_array($rowsByLang[0])) {
1062 $rowsByLang[0] = t3lib_befunc::getRecord($table, $rowCurrent[$transOrigPointerField], $fetchFields);
1063 }
1064 } else {
1065 $rowsByLang[$rowCurrent[$languageField]] = $rowCurrent;
1066 }
1067
1068 if ($rowCurrent[$transOrigPointerField] || $currentLanguage === '0') {
1069 // get record in other languages to see what's already available
1070 $translations = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1071 $fetchFields,
1072 $table,
1073 'pid='.intval($pid).
1074 ' AND '.$languageField.'>0'.
1075 ' AND '.$transOrigPointerField.'='.intval($rowsByLang[0]['uid']).
1076 t3lib_BEfunc::deleteClause($table).
1077 t3lib_BEfunc::versioningPlaceholderClause($table)
1078 );
1079 foreach ($translations as $row) {
1080 $rowsByLang[$row[$languageField]] = $row;
1081 }
1082 }
1083
1084 $langSelItems=array();
1085 foreach ($langRows as $lang) {
1086 if ($GLOBALS['BE_USER']->checkLanguageAccess($lang['uid'])) {
1087
1088 $newTranslation = isset($rowsByLang[$lang['uid']]) ? '' : ' ['.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:labels.new',1).']';
1089
1090 // create url for creating a localized record
1091 if($newTranslation) {
1092 $href = $this->doc->issueCommand(
1093 '&cmd['.$table.']['.$rowsByLang[0]['uid'].'][localize]='.$lang['uid'],
1094 $this->backPath.'alt_doc.php?justLocalized='.rawurlencode($table.':'.$rowsByLang[0]['uid'].':'.$lang['uid']).'&returnUrl='.rawurlencode($this->retUrl) . t3lib_BEfunc::getUrlToken('editRecord')
1095 );
1096
1097 // create edit url
1098 } else {
1099 $href = $this->backPath.'alt_doc.php?';
1100 $href .= '&edit['.$table.']['.$rowsByLang[$lang['uid']]['uid'].']=edit';
1101 $href .= '&returnUrl='.rawurlencode($this->retUrl) . t3lib_BEfunc::getUrlToken('editRecord');
1102 }
1103
1104 $langSelItems[$lang['uid']]='
1105 <option value="'.htmlspecialchars($href).'"'.($currentLanguage==$lang['uid']?' selected="selected"':'').'>'.htmlspecialchars($lang['title'].$newTranslation).'</option>';
1106 }
1107 }
1108
1109 // If any languages are left, make selector:
1110 if (count($langSelItems)>1) {
1111 $onChange = 'if(this.options[this.selectedIndex].value){window.location.href=(this.options[this.selectedIndex].value);}';
1112 $content = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_general.xml:LGL.language',1).' <select name="_langSelector" onchange="'.htmlspecialchars($onChange).'">
1113 '.implode('',$langSelItems).'
1114 </select>';
1115 }
1116 }
1117 }
1118 }
1119 return $content;
1120 }
1121
1122
1123 /**
1124 * Redirects to alt_doc with new parameters to edit a just created localized record
1125 *
1126 * @param string String passed by GET &justLocalized=
1127 * @return void
1128 */
1129 function localizationRedirect($justLocalized) {
1130 list($table,$orig_uid,$language) = explode(':',$justLocalized);
1131
1132 if ($GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) {
1133 $localizedRecord = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
1134 'uid',
1135 $table,
1136 $GLOBALS['TCA'][$table]['ctrl']['languageField'].'='.intval($language).' AND '.
1137 $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'].'='.intval($orig_uid).
1138 t3lib_BEfunc::deleteClause($table).
1139 t3lib_BEfunc::versioningPlaceholderClause($table)
1140 );
1141
1142 if (is_array($localizedRecord)) {
1143 // Create parameters and finally run the classic page module for creating a new page translation
1144 $params = '&edit['.$table.']['.$localizedRecord['uid'].']=edit';
1145 $returnUrl = '&returnUrl='.rawurlencode(t3lib_div::sanitizeLocalUrl(t3lib_div::_GP('returnUrl')));
1146 $location = $GLOBALS['BACK_PATH'].'alt_doc.php?'.$params.$returnUrl . t3lib_BEfunc::getUrlToken('editRecord');
1147
1148 t3lib_utility_Http::redirect($location);
1149 }
1150 }
1151 }
1152
1153
1154 /**
1155 * Returns sys_language records.
1156 *
1157 * @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)
1158 * @return array Language records including faked record for default language
1159 */
1160 function getLanguages($id) {
1161 $modSharedTSconfig = t3lib_BEfunc::getModTSconfig($id, 'mod.SHARED');
1162
1163 // fallback non sprite-configuration
1164 if (preg_match('/\.gif$/', $modSharedTSconfig['properties']['defaultLanguageFlag'])) {
1165 $modSharedTSconfig['properties']['defaultLanguageFlag'] = str_replace('.gif', '', $modSharedTSconfig['properties']['defaultLanguageFlag']);
1166 }
1167
1168 $languages = array(
1169 0 => array(
1170 'uid' => 0,
1171 'pid' => 0,
1172 'hidden' => 0,
1173 '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'),
1174 'flag' => $modSharedTSconfig['properties']['defaultLanguageFlag'],
1175 )
1176 );
1177
1178 $exQ = $GLOBALS['BE_USER']->isAdmin() ? '' : ' AND sys_language.hidden=0';
1179 if ($id) {
1180 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1181 'sys_language.*',
1182 'pages_language_overlay,sys_language',
1183 'pages_language_overlay.sys_language_uid=sys_language.uid AND pages_language_overlay.pid='.intval($id).$exQ,
1184 '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',
1185 'sys_language.title'
1186 );
1187 } else {
1188 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1189 'sys_language.*',
1190 'sys_language',
1191 'sys_language.hidden=0',
1192 '',
1193 'sys_language.title'
1194 );
1195 }
1196 if ($rows) {
1197 foreach ($rows as $row) {
1198 $languages[$row['uid']] = $row;
1199 }
1200 }
1201 return $languages;
1202 }
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213 /***************************
1214 *
1215 * Other functions
1216 *
1217 ***************************/
1218
1219 /**
1220 * Fix $this->editconf if versioning applies to any of the records
1221 *
1222 * @param array Mapping between old and new ids if auto-versioning has been performed.
1223 * @return void
1224 */
1225 function fixWSversioningInEditConf($mapArray=FALSE) {
1226
1227 // Traverse the editConf array
1228 if (is_array($this->editconf)) {
1229 foreach($this->editconf as $table => $conf) { // Tables:
1230 if (is_array($conf) && $GLOBALS['TCA'][$table]) {
1231
1232 // Traverse the keys/comments of each table (keys can be a commalist of uids)
1233 $newConf = array();
1234 foreach($conf as $cKey => $cmd) {
1235 if ($cmd=='edit') {
1236 // Traverse the ids:
1237 $ids = t3lib_div::trimExplode(',', $cKey, 1);
1238 foreach($ids as $idKey => $theUid) {
1239 if (is_array($mapArray)) {
1240 if ($mapArray[$table][$theUid]) {
1241 $ids[$idKey] = $mapArray[$table][$theUid];
1242 }
1243 } else { // Default, look for versions in workspace for record:
1244 $calcPRec = $this->getRecordForEdit($table,$theUid);
1245 if (is_array($calcPRec)) {
1246 // Setting UID again if it had changed, eg. due to workspace versioning.
1247 $ids[$idKey] = $calcPRec['uid'];
1248 }
1249 }
1250 #else unset($ids[$idKey]);
1251 }
1252
1253 // Add the possibly manipulated IDs to the new-build newConf array:
1254 $newConf[implode(',',$ids)] = $cmd;
1255 } else {
1256 $newConf[$cKey] = $cmd;
1257 }
1258 }
1259 // Store the new conf array:
1260 $this->editconf[$table] = $newConf;
1261 }
1262 }
1263 }
1264 }
1265
1266 /**
1267 * Get record for editing.
1268 *
1269 * @param string Table name
1270 * @param integer Record UID
1271 * @return array Returns record to edit, FALSE if none
1272 */
1273 function getRecordForEdit($table,$theUid) {
1274
1275 // Fetch requested record:
1276 $reqRecord = t3lib_BEfunc::getRecord($table,$theUid,'uid,pid');
1277
1278 if (is_array($reqRecord)) {
1279 // If workspace is OFFLINE:
1280 if ($GLOBALS['BE_USER']->workspace!=0) {
1281
1282 // Check for versioning support of the table:
1283 if ($GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
1284
1285 // If the record is already a version of "something" pass it by.
1286 if ($reqRecord['pid']==-1) {
1287
1288 // (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)
1289 return $reqRecord;
1290 } else { // The input record was online and an offline version must be found or made:
1291
1292 // Look for version of this workspace:
1293 $versionRec = t3lib_BEfunc::getWorkspaceVersionOfRecord($GLOBALS['BE_USER']->workspace, $table, $reqRecord['uid'],'uid,pid,t3ver_oid');
1294 return is_array($versionRec) ? $versionRec : $reqRecord;
1295 }
1296 } 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.
1297 } else return $reqRecord; // In ONLINE workspace, just return the originally requested record:
1298 } else return FALSE; // Return FALSE because the table/uid was not found anyway.
1299 }
1300
1301 /**
1302 * 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
1303 *
1304 * @return void
1305 */
1306 function editRegularContentFromId() {
1307 if (t3lib_extMgm::isLoaded('cms')) {
1308 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1309 'uid',
1310 'tt_content',
1311 'pid='.intval($this->editRegularContentFromId).
1312 t3lib_BEfunc::deleteClause('tt_content').
1313 t3lib_BEfunc::versioningPlaceholderClause('tt_content').
1314 ' AND colPos=0 AND sys_language_uid=0',
1315 '',
1316 'sorting'
1317 );
1318 if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) {
1319 $ecUids=array();
1320 while($ecRec = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
1321 $ecUids[]=$ecRec['uid'];
1322 }
1323 $this->editconf['tt_content'][implode(',',$ecUids)]='edit';
1324 }
1325 }
1326 }
1327
1328 /**
1329 * Populates the variables $this->storeArray, $this->storeUrl, $this->storeUrlMd5
1330 *
1331 * @return void
1332 * @see makeDocSel()
1333 */
1334 function compileStoreDat() {
1335 $this->storeArray = t3lib_div::compileSelectedGetVarsFromArray('edit,defVals,overrideVals,columnsOnly,disHelp,noView,editRegularContentFromId',$this->R_URL_getvars);
1336 $this->storeUrl = t3lib_div::implodeArrayForUrl('',$this->storeArray);
1337 $this->storeUrlMd5 = md5($this->storeUrl);
1338 }
1339
1340 /**
1341 * Function used to look for configuration of buttons in the form: Fx. disabling buttons or showing them at various positions.
1342 *
1343 * @param string The table for which the configuration may be specific
1344 * @param string The option for look for. Default is checking if the saveDocNew button should be displayed.
1345 * @return string Return value fetched from USER TSconfig
1346 */
1347 function getNewIconMode($table, $key = 'saveDocNew') {
1348 $TSconfig = $GLOBALS['BE_USER']->getTSConfig('options.'.$key);
1349 $output = trim(isset($TSconfig['properties'][$table]) ? $TSconfig['properties'][$table] : $TSconfig['value']);
1350 return $output;
1351 }
1352
1353 /**
1354 * Handling the closing of a document
1355 *
1356 * @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
1357 * @return void
1358 */
1359 function closeDocument($code=0) {
1360
1361 // If current document is found in docHandler,
1362 // then unset it, possibly unset it ALL and finally, write it to the session data
1363 if (isset($this->docHandler[$this->storeUrlMd5])) {
1364
1365 // add the closing document to the recent documents
1366 $recentDocs = $GLOBALS['BE_USER']->getModuleData('opendocs::recent');
1367 if (!is_array($recentDocs)) {
1368 $recentDocs = array();
1369 }
1370 $closedDoc = $this->docHandler[$this->storeUrlMd5];
1371 $recentDocs = array_merge(array($this->storeUrlMd5 => $closedDoc), $recentDocs);
1372 if (count($recentDocs) > 8) {
1373 $recentDocs = array_slice($recentDocs, 0, 8);
1374 }
1375
1376 // remove it from the list of the open documents
1377 unset($this->docHandler[$this->storeUrlMd5]);
1378 if ($code == '3') {
1379 $recentDocs = array_merge($this->docHandler, $recentDocs);
1380 $this->docHandler = array();
1381 }
1382 $GLOBALS['BE_USER']->pushModuleData('opendocs::recent', $recentDocs);
1383 $GLOBALS['BE_USER']->pushModuleData('alt_doc.php', array($this->docHandler, $this->docDat[1]));
1384 t3lib_BEfunc::setUpdateSignal('tx_opendocs::updateNumber', count($this->docHandler));
1385 }
1386
1387
1388 // 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...)
1389 if ($this->returnEditConf && $this->retUrl!='dummy.php') {
1390 $this->retUrl.='&returnEditConf='.rawurlencode(serialize($this->editconf));
1391 }
1392
1393 // If code is NOT set OR set to 1, then make a header location redirect to $this->retUrl
1394 if (!$code || $code==1) {
1395 t3lib_utility_Http::redirect($this->retUrl);
1396 } else {
1397 $this->setDocument('',$this->retUrl);
1398 }
1399 }
1400
1401 /**
1402 * Redirects to the document pointed to by $currentDocFromHandlerMD5 OR $retUrl (depending on some internal calculations).
1403 * Most likely you will get a header-location redirect from this function.
1404 *
1405 * @param string Pointer to the document in the docHandler array
1406 * @param string Alternative/Default retUrl
1407 * @return void
1408 */
1409 function setDocument($currentDocFromHandlerMD5='',$retUrl='alt_doc_nodoc.php') {
1410 if (!t3lib_extMgm::isLoaded('cms') && !strcmp($retUrl,'alt_doc_nodoc.php')) return;
1411
1412 if (!$this->modTSconfig['properties']['disableDocSelector'] && is_array($this->docHandler) && count($this->docHandler)) {
1413 if (isset($this->docHandler[$currentDocFromHandlerMD5])) {
1414 $setupArr=$this->docHandler[$currentDocFromHandlerMD5];
1415 } else {
1416 $setupArr = reset($this->docHandler);
1417 }
1418 if ($setupArr[2]) {
1419 $sParts = parse_url(t3lib_div::getIndpEnv('REQUEST_URI'));
1420 $retUrl = $sParts['path'].'?'.$setupArr[2].'&returnUrl='.rawurlencode($retUrl);
1421 }
1422 }
1423 t3lib_utility_Http::redirect($retUrl);
1424 }
1425 }
1426
1427
1428 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/alt_doc.php'])) {
1429 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/alt_doc.php']);
1430 }
1431
1432
1433
1434 // Make instance:
1435 $SOBE = t3lib_div::makeInstance('SC_alt_doc');
1436
1437 // Preprocessing, storing data if submitted to
1438 $SOBE->preInit();
1439
1440 $formprotection = t3lib_formprotection_Factory::get();
1441
1442 if ($SOBE->doProcessData()) { // Checks, if a save button has been clicked (or the doSave variable is sent)
1443 if ($formprotection->validateToken(t3lib_div::_GP('formToken'), 'editRecord')) {
1444 $SOBE->processData();
1445 }
1446 }
1447
1448 // Main:
1449 $SOBE->init();
1450 $SOBE->main();
1451 $SOBE->printContent();
1452
1453 ?>