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