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