TYPO3 API  SVNRelease
class.t3lib_tceforms.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003  *  Copyright notice
00004  *
00005  *  (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
00006  *  All rights reserved
00007  *
00008  *  This script is part of the TYPO3 project. The TYPO3 project is
00009  *  free software; you can redistribute it and/or modify
00010  *  it under the terms of the GNU General Public License as published by
00011  *  the Free Software Foundation; either version 2 of the License, or
00012  *  (at your option) any later version.
00013  *
00014  *  The GNU General Public License can be found at
00015  *  http://www.gnu.org/copyleft/gpl.html.
00016  *  A copy is found in the textfile GPL.txt and important notices to the license
00017  *  from the author is found in LICENSE.txt distributed with these scripts.
00018  *
00019  *
00020  *  This script is distributed in the hope that it will be useful,
00021  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  *  GNU General Public License for more details.
00024  *
00025  *  This copyright notice MUST APPEAR in all copies of the script!
00026  ***************************************************************/
00027 /**
00028  * Contains TYPO3 Core Form generator - AKA "TCEforms"
00029  *
00030  * $Id: class.t3lib_tceforms.php 10577 2011-02-23 09:04:29Z francois $
00031  * Revised for TYPO3 3.6 August/2003 by Kasper Skårhøj
00032  * XHTML compliant
00033  *
00034  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00035  */
00036 /**
00037  * [CLASS/FUNCTION INDEX of SCRIPT]
00038  *
00039  *
00040  *
00041  *  196: class t3lib_TCEforms
00042  *  302:     function t3lib_TCEforms()
00043  *  338:     function initDefaultBEmode()
00044  *
00045  *            SECTION: Rendering the forms, fields etc
00046  *  385:     function getSoloField($table,$row,$theFieldToReturn)
00047  *  424:     function getMainFields($table,$row,$depth=0)
00048  *  618:     function getListedFields($table,$row,$list)
00049  *  660:     function getPaletteFields($table,$row,$palette,$header='',$itemList='',$collapsedHeader='')
00050  *  737:     function getSingleField($table,$field,$row,$altName='',$palette=0,$extra='',$pal=0)
00051  *  900:     function getSingleField_SW($table,$field,$row,&$PA)
00052  *
00053  *            SECTION: Rendering of each TCEform field type
00054  *  976:     function getSingleField_typeInput($table,$field,$row,&$PA)
00055  * 1057:     function getSingleField_typeText($table,$field,$row,&$PA)
00056  * 1178:     function getSingleField_typeCheck($table,$field,$row,&$PA)
00057  * 1244:     function getSingleField_typeRadio($table,$field,$row,&$PA)
00058  * 1279:     function getSingleField_typeSelect($table,$field,$row,&$PA)
00059  * 1359:     function getSingleField_typeSelect_single($table,$field,$row,&$PA,$config,$selItems,$nMV_label)
00060  * 1490:     function getSingleField_typeSelect_checkbox($table,$field,$row,&$PA,$config,$selItems,$nMV_label)
00061  * 1609:     function getSingleField_typeSelect_singlebox($table,$field,$row,&$PA,$config,$selItems,$nMV_label)
00062  * 1719:     function getSingleField_typeSelect_multiple($table,$field,$row,&$PA,$config,$selItems,$nMV_label)
00063  * 1823:     function getSingleField_typeGroup($table,$field,$row,&$PA)
00064  * 1992:     function getSingleField_typeNone($table,$field,$row,&$PA)
00065  * 2008:     function getSingleField_typeNone_render($config,$itemValue)
00066  * 2070:     function getSingleField_typeFlex($table,$field,$row,&$PA)
00067  * 2205:     function getSingleField_typeFlex_langMenu($languages,$elName,$selectedLanguage,$multi=1)
00068  * 2224:     function getSingleField_typeFlex_sheetMenu($sArr,$elName,$sheetKey)
00069  * 2259:     function getSingleField_typeFlex_draw($dataStruct,$editData,$cmdData,$table,$field,$row,&$PA,$formPrefix='',$level=0,$tRows=array())
00070  * 2452:     function getSingleField_typeUnknown($table,$field,$row,&$PA)
00071  * 2467:     function getSingleField_typeUser($table,$field,$row,&$PA)
00072  *
00073  *            SECTION: Field content processing
00074  * 2496:     function formatValue ($config, $itemValue)
00075  *
00076  *            SECTION: "Configuration" fetching/processing functions
00077  * 2588:     function getRTypeNum($table,$row)
00078  * 2614:     function rearrange($fields)
00079  * 2640:     function getExcludeElements($table,$row,$typeNum)
00080  * 2688:     function getFieldsToAdd($table,$row,$typeNum)
00081  * 2713:     function mergeFieldsWithAddedFields($fields,$fieldsToAdd)
00082  * 2745:     function setTSconfig($table,$row,$field='')
00083  * 2767:     function getSpecConfForField($table,$row,$field)
00084  * 2788:     function getSpecConfFromString($extraString, $defaultExtras)
00085  * 3007:     function loadPaletteElements($table, $row, $palette, $itemList='')
00086  *
00087  *            SECTION: Display of localized content etc.
00088  * 2816:     function registerDefaultLanguageData($table,$rec)
00089  * 2848:     function getLanguageOverlayRawValue($table, $row, $field, $fieldConf)
00090  * 2876:     function renderDefaultLanguageContent($table,$field,$row,$item)
00091  * 2899:     function renderDefaultLanguageDiff($table,$field,$row,$item)
00092  *
00093  *            SECTION: Form element helper functions
00094  * 2955:     function dbFileIcons($fName,$mode,$allowed,$itemArray,$selector='',$params=array(),$onFocus='')
00095  * 3108:     function getClipboardElements($allowed,$mode)
00096  * 3157:     function getClickMenu($str,$table,$uid='')
00097  * 3178:     function renderWizards($itemKinds,$wizConf,$table,$row,$field,&$PA,$itemName,$specConf,$RTE=0)
00098  * 3382:     function getIcon($icon)
00099  * 3409:     function optionTagStyle($iconString)
00100  * 3425:     function extractValuesOnlyFromValueLabelList($itemFormElValue)
00101  * 3447:     function wrapOpenPalette($header,$table,$row,$palette,$retFunc=0)
00102  * 3471:     function checkBoxParams($itemName,$thisValue,$c,$iCount,$addFunc='')
00103  * 3485:     function elName($itemName)
00104  * 3496:     function noTitle($str,$wrapParts=array())
00105  * 3505:     function blur()
00106  * 3514:     function thisReturnUrl()
00107  * 3527:     function getSingleHiddenField($table,$field,$row)
00108  * 3549:     function formWidth($size=48,$textarea=0)
00109  * 3576:     function formWidthText($size=48,$wrap='')
00110  * 3592:     function formElStyle($type)
00111  * 3603:     function formElClass($type)
00112  * 3614:     function formElStyleClassValue($type, $class=FALSE)
00113  * 3638:     function insertDefStyle($type)
00114  * 3657:     function getDynTabMenu($parts, $idString)
00115  *
00116  *            SECTION: Item-array manipulation functions (check/select/radio)
00117  * 3696:     function initItemArray($fieldValue)
00118  * 3714:     function addItems($items,$iArray)
00119  * 3736:     function procItems($items,$iArray,$config,$table,$row,$field)
00120  * 3760:     function addSelectOptionsToItemArray($items,$fieldValue,$TSconfig,$field)
00121  * 3980:     function addSelectOptionsToItemArray_makeModuleData($value)
00122  * 4002:     function foreignTable($items,$fieldValue,$TSconfig,$field,$pFFlag=0)
00123  *
00124  *            SECTION: Template functions
00125  * 4083:     function setNewBEDesign()
00126  * 4138:     function intoTemplate($inArr,$altTemplate='')
00127  * 4162:     function addUserTemplateMarkers($marker,$table,$field,$row,&$PA)
00128  * 4173:     function wrapLabels($str)
00129  * 4186:     function wrapTotal($c,$rec,$table)
00130  * 4199:     function replaceTableWrap($arr,$rec,$table)
00131  * 4236:     function wrapBorder(&$out_array,&$out_pointer)
00132  * 4258:     function rplColorScheme($inTemplate)
00133  * 4278:     function getDivider()
00134  * 4288:     function printPalette($palArr)
00135  * 4339:     function helpTextIcon($table,$field,$force=0)
00136  * 4359:     function helpText($table,$field)
00137  * 4380:     function setColorScheme($scheme)
00138  * 4404:     function resetSchemes()
00139  * 4415:     function storeSchemes()
00140  * 4427:     function restoreSchemes()
00141  *
00142  *            SECTION: JavaScript related functions
00143  * 4457:     function JStop()
00144  * 4508:     function JSbottom($formname='forms[0]')
00145  * 4835:     function dbFileCon($formObj='document.forms[0]')
00146  * 5053:     function printNeededJSFunctions()
00147  * 5080:     function printNeededJSFunctions_top()
00148  *
00149  *            SECTION: Various helper functions
00150  * 5128:     function getDefaultRecord($table,$pid=0)
00151  * 5167:     function getRecordPath($table,$rec)
00152  * 5181:     function readPerms()
00153  * 5195:     function sL($str)
00154  * 5208:     function getLL($str)
00155  * 5229:     function isPalettesCollapsed($table,$palette)
00156  * 5245:     function isDisplayCondition($displayCond,$row,$ffValueKey='')
00157  * 5349:     function getTSCpid($table,$uid,$pid)
00158  * 5363:     function doLoadTableDescr($table)
00159  * 5375:     function getAvailableLanguages($onlyIsoCoded=1,$setDefault=1)
00160  *
00161  *
00162  * 5417: class t3lib_TCEforms_FE extends t3lib_TCEforms
00163  * 5425:     function wrapLabels($str)
00164  * 5435:     function printPalette($palArr)
00165  * 5460:     function setFancyDesign()
00166  *
00167  * TOTAL FUNCTIONS: 100
00168  * (This index is automatically created/updated by the extension "extdeveval")
00169  *
00170  */
00171 
00172 
00173 /**
00174  * 'TCEforms' - Class for creating the backend editing forms.
00175  *
00176  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00177  * @coauthor    René Fritz <r.fritz@colorcube.de>
00178  * @package TYPO3
00179  * @subpackage t3lib
00180  */
00181 class t3lib_TCEforms {
00182 
00183         // variables not commented yet.... (do so...)
00184     var $palFieldArr = array();
00185     var $disableWizards = 0;
00186     var $isPalettedoc = 0;
00187     var $paletteMargin = 1;
00188     var $defStyle = ''; // 'font-family:Verdana;font-size:10px;';
00189     var $cachedTSconfig = array();
00190     var $cachedTSconfig_fieldLevel = array();
00191     var $cachedLanguageFlag = array();
00192     var $cachedAdditionalPreviewLanguages = NULL;
00193     var $transformedRow = array();
00194     var $extJSCODE = '';
00195     var $printNeededJS = array();
00196     var $hiddenFieldAccum = array();
00197     var $TBE_EDITOR_fieldChanged_func = '';
00198     var $loadMD5_JS = 1;
00199     var $prevBorderStyle = '[nothing here...]'; // Something unique...
00200     var $allowUpload = 0; // If set direct upload fields will be shown
00201     var $titleLen = 15; // @deprecated since TYPO3 4.1: $BE_USER->uc['titleLen'] but what is default??
00202     var $defaultLanguageData = array(); // Array where records in the default language is stored. (processed by transferdata)
00203     var $defaultLanguageData_diff = array(); // Array where records in the default language is stored (raw without any processing. used for making diff)
00204     var $additionalPreviewLanguageData = array();
00205 
00206 
00207         // EXTERNAL, static
00208     var $backPath = ''; // Set this to the 'backPath' pointing back to the typo3 admin directory from the script where this form is displayed.
00209     var $returnUrl = ''; // Alternative return URL path (default is t3lib_div::linkThisScript())
00210     var $doSaveFieldName = ''; // Can be set to point to a field name in the form which will be set to '1' when the form is submitted with a *save* button. This way the recipient script can determine that the form was submitted for save and not "close" for example.
00211     var $palettesCollapsed = 0; // Can be set true/false to whether palettes (secondary options) are in the topframe or in form. True means they are NOT IN-form. So a collapsed palette is one, which is shown in the top frame, not in the page.
00212     var $disableRTE = 0; // If set, the RTE is disabled (from form display, eg. by checkbox in the bottom of the page!)
00213     var $globalShowHelp = 1; // If false, then all CSH will be disabled, regardless of settings in $this->edit_showFieldHelp
00214     var $localizationMode = ''; // If true, the forms are rendering only localization relevant fields of the records.
00215     var $fieldOrder = ''; // Overrule the field order set in TCA[types][showitem], eg for tt_content this value, 'bodytext,image', would make first the 'bodytext' field, then the 'image' field (if set for display)... and then the rest in the old order.
00216     var $doPrintPalette = 1; // If set to false, palettes will NEVER be rendered.
00217 
00218     /**
00219      * Set to initialized clipboard object; Then the element browser will offer a link to paste in records from clipboard.
00220      *
00221      * @var t3lib_clipboard
00222      */
00223     var $clipObj = FALSE;
00224     var $enableClickMenu = FALSE; // Enable click menu on reference icons.
00225     var $enableTabMenu = FALSE; // Enable Tab Menus.
00226     var $renderReadonly = FALSE; // When enabled all fields are rendered non-editable.
00227 
00228     var $form_rowsToStylewidth = 9.58; // Form field width compensation: Factor from NN4 form field widths to style-aware browsers (like NN6+ and MSIE, with the $CLIENT[FORMSTYLE] value set)
00229     var $form_largeComp = 1.33; // Form field width compensation: Compensation for large documents, doc-tab (editing)
00230     var $charsPerRow = 40; // The number of chars expected per row when the height of a text area field is automatically calculated based on the number of characters found in the field content.
00231     var $maxTextareaWidth = 48; // The maximum abstract value for textareas
00232     var $maxInputWidth = 48; // The maximum abstract value for input fields
00233     var $defaultMultipleSelectorStyle = 'width:250px;'; // Default style for the selector boxes used for multiple items in "select" and "group" types.
00234 
00235 
00236         // INTERNAL, static
00237     var $prependFormFieldNames = 'data'; // The string to prepend formfield names with.
00238     var $prependCmdFieldNames = 'cmd'; // The string to prepend commands for tcemain::process_cmdmap with.
00239     var $prependFormFieldNames_file = 'data_files'; // The string to prepend FILE form field names with.
00240     var $formName = 'editform'; // The name attribute of the form.
00241     var $allowOverrideMatrix = array(); // Whitelist that allows TCA field configuration to be overridden by TSconfig, @see overrideFieldConf()
00242 
00243 
00244         // INTERNAL, dynamic
00245     var $perms_clause = ''; // Set by readPerms()  (caching)
00246     var $perms_clause_set = 0; // Set by readPerms()  (caching-flag)
00247     var $edit_showFieldHelp = ''; // Used to indicate the mode of CSH (Context Sensitive Help), whether it should be icons-only ('icon'), full description ('text') or not at all (blank).
00248     var $docLarge = 0; // If set, the forms will be rendered a little wider, more precisely with a factor of $this->form_largeComp.
00249     var $clientInfo = array(); // Loaded with info about the browser when class is instantiated.
00250     var $RTEenabled = 0; // True, if RTE is possible for the current user (based on result from BE_USER->isRTE())
00251     var $RTEenabled_notReasons = ''; // If $this->RTEenabled was false, you can find the reasons listed in this array which is filled with reasons why the RTE could not be loaded)
00252     var $RTEcounter = 0; // Counter that is incremented before an RTE is created. Can be used for unique ids etc.
00253 
00254     var $colorScheme; // Contains current color scheme
00255     var $classScheme; // Contains current class scheme
00256     var $defColorScheme; // Contains the default color scheme
00257     var $defClassScheme; // Contains the default class scheme
00258     var $fieldStyle; // Contains field style values
00259     var $borderStyle; // Contains border style values.
00260 
00261     var $commentMessages = array(); // An accumulation of messages from the class.
00262 
00263         // INTERNAL, templates
00264     var $totalWrap = '<hr />|<hr />'; // Total wrapping for the table rows.
00265     var $fieldTemplate = '<strong>###FIELD_NAME###</strong><br />###FIELD_ITEM###<hr />'; // Field template
00266     var $sectionWrap = ''; // Wrapping template code for a section
00267     var $palFieldTemplateHeader = ''; // Template for palette headers
00268     var $palFieldTemplate = ''; // Template for palettes
00269 
00270         // INTERNAL, working memory
00271     var $excludeElements = ''; // Set to the fields NOT to display, if any.
00272     var $palettesRendered = array(); // During rendering of forms this will keep track of which palettes has already been rendered (so they are not rendered twice by mistake)
00273     var $hiddenFieldListArr = array(); // This array of fields will be set as hidden-fields instead of rendered normally! For instance palette fields edited in the top frame are set as hidden fields since the main form has to submit the values. The top frame actually just sets the value in the main form!
00274     var $requiredFields = array(); // Used to register input-field names, which are required. (Done during rendering of the fields). This information is then used later when the JavaScript is made.
00275     var $requiredAdditional = array(); // Used to register input-field names, which are required an have additional requirements (e.g. like a date/time must be positive integer). The information of this array is merged with $this->requiredFields later.
00276     var $requiredElements = array(); // Used to register the min and max number of elements for selectorboxes where that apply (in the "group" type for instance)
00277     var $requiredNested = array(); // Used to determine where $requiredFields or $requiredElements are nested (in Tabs or IRRE)
00278     var $renderDepth = 0; // Keeps track of the rendering depth of nested records.
00279     var $savedSchemes = array(); // Color scheme buffer.
00280     var $dynNestedStack = array(); // holds the path an element is nested in (e.g. required for RTEhtmlarea)
00281 
00282         // Internal, registers for user defined functions etc.
00283     var $additionalCode_pre = array(); // Additional HTML code, printed before the form.
00284     var $additionalJS_pre = array(); // Additional JavaScript, printed before the form
00285     var $additionalJS_post = array(); // Additional JavaScript printed after the form
00286     var $additionalJS_submit = array(); // Additional JavaScript executed on submit; If you set "OK" variable it will raise an error about RTEs not being loaded and offer to block further submission.
00287     var $additionalJS_delete = array(); // Additional JavaScript executed when section element is deleted. This is neceessary, for example, to correctly clean up HTMLArea RTE (bug #8232)
00288 
00289     /**
00290      * Instance of t3lib_tceforms_inline
00291      *
00292      * @var t3lib_TCEforms_inline
00293      */
00294     var $inline;
00295     var $hookObjectsMainFields = array(); // Array containing hook class instances called once for a form
00296     var $hookObjectsSingleField = array(); // Array containing hook class instances called for each field
00297     var $extraFormHeaders = array(); // Rows gettings inserted into the alt_doc headers (when called from alt_doc.php)
00298 
00299     public $templateFile = ''; // Form templates, relative to typo3 directory
00300 
00301 
00302     /**
00303      * Constructor function, setting internal variables, loading the styles used.
00304      *
00305      * @return  void
00306      */
00307     function t3lib_TCEforms() {
00308         global $CLIENT, $TYPO3_CONF_VARS;
00309 
00310         $this->clientInfo = t3lib_div::clientInfo();
00311 
00312         $this->RTEenabled = $GLOBALS['BE_USER']->isRTE();
00313         if (!$this->RTEenabled) {
00314             $this->RTEenabled_notReasons = implode(LF, $GLOBALS['BE_USER']->RTE_errors);
00315             $this->commentMessages[] = 'RTE NOT ENABLED IN SYSTEM due to:' . LF . $this->RTEenabled_notReasons;
00316         }
00317 
00318             // Default color+class scheme
00319         $this->defColorScheme = array(
00320             $GLOBALS['SOBE']->doc->bgColor, // Background for the field AND palette
00321             t3lib_div::modifyHTMLColorAll($GLOBALS['SOBE']->doc->bgColor, -20), // Background for the field header
00322             t3lib_div::modifyHTMLColorAll($GLOBALS['SOBE']->doc->bgColor, -10), // Background for the palette field header
00323             'black', // Field header font color
00324             '#666666' // Palette field header font color
00325         );
00326         $this->defColorScheme = array();
00327 
00328             // Override / Setting defaults from TBE_STYLES array
00329         $this->resetSchemes();
00330 
00331             // Setting the current colorScheme to default.
00332         $this->defColorScheme = $this->colorScheme;
00333         $this->defClassScheme = $this->classScheme;
00334 
00335             // Define whitelist that allows TCA field configuration to be overridden by TSconfig, @see overrideFieldConf():
00336         $this->allowOverrideMatrix = array(
00337             'input' => array('size', 'max'),
00338             'text' => array('cols', 'rows', 'wrap'),
00339             'check' => array('cols', 'showIfRTE'),
00340             'select' => array('size', 'autoSizeMax', 'maxitems', 'minitems'),
00341             'group' => array('size', 'autoSizeMax', 'max_size', 'show_thumbs', 'maxitems', 'minitems', 'disable_controls'),
00342             'inline' => array('appearance', 'behaviour', 'foreign_label', 'foreign_selector', 'foreign_unique', 'maxitems', 'minitems', 'size', 'autoSizeMax', 'symmetric_label'),
00343         );
00344 
00345             // Create instance of t3lib_TCEforms_inline only if this a non-IRRE-AJAX call:
00346         if (!isset($GLOBALS['ajaxID']) || strpos($GLOBALS['ajaxID'], 't3lib_TCEforms_inline::') !== 0) {
00347             $this->inline = t3lib_div::makeInstance('t3lib_TCEforms_inline');
00348         }
00349             // Create instance of t3lib_TCEforms_suggest only if this a non-Suggest-AJAX call:
00350         if (!isset($GLOBALS['ajaxID']) || strpos($GLOBALS['ajaxID'], 't3lib_TCEforms_suggest::') !== 0) {
00351             $this->suggest = t3lib_div::makeInstance('t3lib_TCEforms_suggest');
00352         }
00353 
00354             // Prepare user defined objects (if any) for hooks which extend this function:
00355         $this->hookObjectsMainFields = array();
00356         if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getMainFieldsClass'])) {
00357             foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getMainFieldsClass'] as $classRef) {
00358                 $this->hookObjectsMainFields[] = t3lib_div::getUserObj($classRef);
00359             }
00360         }
00361         $this->hookObjectsSingleField = array();
00362         if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getSingleFieldClass'])) {
00363             foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getSingleFieldClass'] as $classRef) {
00364                 $this->hookObjectsSingleField[] = t3lib_div::getUserObj($classRef);
00365             }
00366         }
00367 
00368         $this->templateFile = 'templates/tceforms.html';
00369 
00370     }
00371 
00372     /**
00373      * Initialize various internal variables.
00374      *
00375      * @return  void
00376      */
00377     function initDefaultBEmode() {
00378         global $BE_USER;
00379         $this->prependFormFieldNames = 'data';
00380         $this->formName = 'editform';
00381         $this->setNewBEDesign();
00382         $this->docLarge = $BE_USER->uc['edit_wideDocument'] ? 1 : 0;
00383         $this->edit_showFieldHelp = $BE_USER->uc['edit_showFieldHelp'];
00384 
00385         $this->edit_docModuleUpload = $BE_USER->uc['edit_docModuleUpload'];
00386         $this->titleLen = $BE_USER->uc['titleLen']; // @deprecated since TYPO3 4.1
00387 
00388         $this->inline->init($this);
00389         $this->suggest->init($this);
00390     }
00391 
00392 
00393     /*******************************************************
00394      *
00395      * Rendering the forms, fields etc
00396      *
00397      *******************************************************/
00398 
00399     /**
00400      * Will return the TCEform element for just a single field from a record.
00401      * The field must be listed in the currently displayed fields (as found in [types][showitem]) for the record.
00402      * This also means that the $table/$row supplied must be complete so the list of fields to show can be found correctly
00403      *
00404      * @param   string      The table name
00405      * @param   array       The record from the table for which to render a field.
00406      * @param   string      The field name to return the TCEform element for.
00407      * @return  string      HTML output
00408      * @see getMainFields()
00409      */
00410     function getSoloField($table, $row, $theFieldToReturn) {
00411         global $TCA;
00412 
00413         if ($TCA[$table]) {
00414             t3lib_div::loadTCA($table);
00415             $typeNum = $this->getRTypeNum($table, $row);
00416             if ($TCA[$table]['types'][$typeNum]) {
00417                 $itemList = $TCA[$table]['types'][$typeNum]['showitem'];
00418                 if ($itemList) {
00419                     $fields = t3lib_div::trimExplode(',', $itemList, 1);
00420                     $excludeElements = $this->excludeElements = $this->getExcludeElements($table, $row, $typeNum);
00421 
00422                     foreach ($fields as $fieldInfo) {
00423                         $parts = explode(';', $fieldInfo);
00424 
00425                         $theField = trim($parts[0]);
00426                         if (!in_array($theField, $excludeElements) && !strcmp($theField, $theFieldToReturn)) {
00427                             if ($TCA[$table]['columns'][$theField]) {
00428                                 $sField = $this->getSingleField($table, $theField, $row, $parts[1], 1, $parts[3], $parts[2]);
00429                                 return $sField['ITEM'];
00430                             }
00431                         }
00432                     }
00433                 }
00434             }
00435         }
00436     }
00437 
00438     /**
00439      * Based on the $table and $row of content, this displays the complete TCEform for the record.
00440      * The input-$row is required to be preprocessed if necessary by eg. the t3lib_transferdata class. For instance the RTE content should be transformed through this class first.
00441      *
00442      * @param   string      The table name
00443      * @param   array       The record from the table for which to render a field.
00444      * @param   integer     Depth level
00445      * @return  string      HTML output
00446      * @see getSoloField()
00447      */
00448     function getMainFields($table, $row, $depth = 0) {
00449         global $TCA, $TYPO3_CONF_VARS;
00450 
00451         $this->renderDepth = $depth;
00452 
00453             // Init vars:
00454         $out_array = array(array());
00455         $out_array_meta = array(array(
00456                                     'title' => $this->getLL('l_generalTab')
00457                                 ));
00458 
00459         $out_pointer = 0;
00460         $out_sheet = 0;
00461         $this->palettesRendered = array();
00462         $this->palettesRendered[$this->renderDepth][$table] = array();
00463 
00464             // Hook: getMainFields_preProcess (requested by Thomas Hempel for use with the "dynaflex" extension)
00465         foreach ($this->hookObjectsMainFields as $hookObj) {
00466             if (method_exists($hookObj, 'getMainFields_preProcess')) {
00467                 $hookObj->getMainFields_preProcess($table, $row, $this);
00468             }
00469         }
00470 
00471         if ($TCA[$table]) {
00472 
00473                 // Load the full TCA for the table.
00474             t3lib_div::loadTCA($table);
00475 
00476                 // Get dividers2tabs setting from TCA of the current table:
00477             $dividers2tabs =& $TCA[$table]['ctrl']['dividers2tabs'];
00478 
00479                 // Load the description content for the table.
00480             if ($this->edit_showFieldHelp || $this->doLoadTableDescr($table)) {
00481                 $GLOBALS['LANG']->loadSingleTableDescription($table);
00482             }
00483                 // Get the current "type" value for the record.
00484             $typeNum = $this->getRTypeNum($table, $row);
00485 
00486                 // Find the list of fields to display:
00487             if ($TCA[$table]['types'][$typeNum]) {
00488                 $itemList = $TCA[$table]['types'][$typeNum]['showitem'];
00489                 if ($itemList) { // If such a list existed...
00490                         // Explode the field list and possibly rearrange the order of the fields, if configured for
00491                     $fields = t3lib_div::trimExplode(',', $itemList, 1);
00492                     if ($this->fieldOrder) {
00493                         $fields = $this->rearrange($fields);
00494                     }
00495 
00496                         // Get excluded fields, added fiels and put it together:
00497                     $excludeElements = $this->excludeElements = $this->getExcludeElements($table, $row, $typeNum);
00498                     $fields = $this->mergeFieldsWithAddedFields($fields, $this->getFieldsToAdd($table, $row, $typeNum));
00499 
00500                         // If TCEforms will render a tab menu in the next step, push the name to the tab stack:
00501                     $tabIdentString = '';
00502                     $tabIdentStringMD5 = '';
00503                     if (strstr($itemList, '--div--') !== false && $this->enableTabMenu && $dividers2tabs) {
00504                         $tabIdentString = 'TCEforms:' . $table . ':' . $row['uid'];
00505                         $tabIdentStringMD5 = $GLOBALS['TBE_TEMPLATE']->getDynTabMenuId($tabIdentString);
00506                             // Remember that were currently working on the general tab:
00507                         if (isset($fields[0]) && strpos($fields[0], '--div--') !== 0) {
00508                             $this->pushToDynNestedStack('tab', $tabIdentStringMD5 . '-1');
00509                         }
00510                     }
00511 
00512                         // Traverse the fields to render:
00513                     $cc = 0;
00514                     foreach ($fields as $fieldInfo) {
00515                             // Exploding subparts of the field configuration:
00516                         $parts = explode(';', $fieldInfo);
00517 
00518                             // Getting the style information out:
00519                         $color_style_parts = t3lib_div::trimExplode('-', $parts[4]);
00520                         if (strcmp($color_style_parts[0], '')) {
00521                             $this->setColorScheme($GLOBALS['TBE_STYLES']['colorschemes'][intval($color_style_parts[0])]);
00522                         }
00523                         if (strcmp($color_style_parts[1], '')) {
00524                             $this->fieldStyle = $GLOBALS['TBE_STYLES']['styleschemes'][intval($color_style_parts[1])];
00525                             if (!isset($this->fieldStyle)) {
00526                                 $this->fieldStyle = $GLOBALS['TBE_STYLES']['styleschemes'][0];
00527                             }
00528                         }
00529                         if (strcmp($color_style_parts[2], '')) {
00530                             $this->wrapBorder($out_array[$out_sheet], $out_pointer);
00531                             $this->borderStyle = $GLOBALS['TBE_STYLES']['borderschemes'][intval($color_style_parts[2])];
00532                             if (!isset($this->borderStyle)) {
00533                                 $this->borderStyle = $GLOBALS['TBE_STYLES']['borderschemes'][0];
00534                             }
00535                         }
00536 
00537                             // Render the field:
00538                         $theField = $parts[0];
00539                         if (!in_array($theField, $excludeElements)) {
00540                             if ($TCA[$table]['columns'][$theField]) {
00541                                 $sFieldPal = '';
00542 
00543                                 if ($parts[2] && !isset($this->palettesRendered[$this->renderDepth][$table][$parts[2]])) {
00544                                     $sFieldPal = $this->getPaletteFields($table, $row, $parts[2]);
00545                                     $this->palettesRendered[$this->renderDepth][$table][$parts[2]] = 1;
00546                                 }
00547                                 $sField = $this->getSingleField($table, $theField, $row, $parts[1], 0, $parts[3], $parts[2]);
00548                                 if ($sField) {
00549                                     $sField .= $sFieldPal;
00550                                 }
00551 
00552                                 $out_array[$out_sheet][$out_pointer] .= $sField;
00553                             } elseif ($theField == '--div--') {
00554                                 if ($cc > 0) {
00555                                     $out_array[$out_sheet][$out_pointer] .= $this->getDivider();
00556 
00557                                     if ($this->enableTabMenu && $dividers2tabs) {
00558                                         $this->wrapBorder($out_array[$out_sheet], $out_pointer);
00559                                             // Remove last tab entry from the dynNestedStack:
00560                                         $out_sheet++;
00561                                             // Remove the previous sheet from stack (if any):
00562                                         $this->popFromDynNestedStack('tab', $tabIdentStringMD5 . '-' . ($out_sheet));
00563                                             // Remember on which sheet we're currently working:
00564                                         $this->pushToDynNestedStack('tab', $tabIdentStringMD5 . '-' . ($out_sheet + 1));
00565                                         $out_array[$out_sheet] = array();
00566                                         $out_array_meta[$out_sheet]['title'] = $this->sL($parts[1]);
00567                                             // Register newline for Tab
00568                                         $out_array_meta[$out_sheet]['newline'] = ($parts[2] == "newline");
00569                                     }
00570                                 } else { // Setting alternative title for "General" tab if "--div--" is the very first element.
00571                                     $out_array_meta[$out_sheet]['title'] = $this->sL($parts[1]);
00572                                         // Only add the first tab to the dynNestedStack if there are more tabs:
00573                                     if ($tabIdentString && strpos($itemList, '--div--', strlen($fieldInfo))) {
00574                                         $this->pushToDynNestedStack('tab', $tabIdentStringMD5 . '-1');
00575                                     }
00576                                 }
00577                             } elseif ($theField == '--palette--') {
00578                                 if ($parts[2] && !isset($this->palettesRendered[$this->renderDepth][$table][$parts[2]])) {
00579                                         // render a 'header' if not collapsed
00580                                     if ($TCA[$table]['palettes'][$parts[2]]['canNotCollapse'] AND $parts[1]) {
00581                                         $out_array[$out_sheet][$out_pointer] .= $this->getPaletteFields($table, $row, $parts[2], $this->sL($parts[1]));
00582                                     } else {
00583                                         $out_array[$out_sheet][$out_pointer] .= $this->getPaletteFields($table, $row, $parts[2], '', '', $this->sL($parts[1]));
00584                                     }
00585                                     $this->palettesRendered[$this->renderDepth][$table][$parts[2]] = 1;
00586                                 }
00587                             }
00588                         }
00589 
00590                         $cc++;
00591                     }
00592                 }
00593             }
00594         }
00595 
00596             // Hook: getMainFields_postProcess (requested by Thomas Hempel for use with the "dynaflex" extension)
00597         foreach ($this->hookObjectsMainFields as $hookObj) {
00598             if (method_exists($hookObj, 'getMainFields_postProcess')) {
00599                 $hookObj->getMainFields_postProcess($table, $row, $this);
00600             }
00601         }
00602 
00603             // Wrapping a border around it all:
00604         $this->wrapBorder($out_array[$out_sheet], $out_pointer);
00605 
00606             // Resetting styles:
00607         $this->resetSchemes();
00608 
00609             // Rendering Main palettes, if any
00610         $mParr = t3lib_div::trimExplode(',', $TCA[$table]['ctrl']['mainpalette']);
00611         $i = 0;
00612         if (count($mParr)) {
00613             foreach ($mParr as $mP) {
00614                 if (!isset($this->palettesRendered[$this->renderDepth][$table][$mP])) {
00615                     $temp_palettesCollapsed = $this->palettesCollapsed;
00616                     $this->palettesCollapsed = 0;
00617                     $label = ($i == 0 ? $this->getLL('l_generalOptions') : $this->getLL('l_generalOptions_more'));
00618                     $out_array[$out_sheet][$out_pointer] .= $this->getPaletteFields($table, $row, $mP, $label);
00619                     $this->palettesCollapsed = $temp_palettesCollapsed;
00620                     $this->palettesRendered[$this->renderDepth][$table][$mP] = 1;
00621                 }
00622                 $this->wrapBorder($out_array[$out_sheet], $out_pointer);
00623                 $i++;
00624                 if ($this->renderDepth) {
00625                     $this->renderDepth--;
00626                 }
00627             }
00628         }
00629 
00630             // Return the imploded $out_array:
00631         if ($out_sheet > 0) { // There were --div-- dividers around...
00632 
00633                 // Create parts array for the tab menu:
00634             $parts = array();
00635             foreach ($out_array as $idx => $sheetContent) {
00636                 $content = implode('', $sheetContent);
00637                 if ($content) {
00638                         // Wrap content (row) with table-tag, otherwise tab/sheet will be disabled (see getdynTabMenu() )
00639                     $content = '<table border="0" cellspacing="0" cellpadding="0" width="100%">' . $content . '</table>';
00640                 }
00641                 $parts[$idx] = array(
00642                     'label' => $out_array_meta[$idx]['title'],
00643                     'content' => $content,
00644                     'newline' => $out_array_meta[$idx]['newline'], // Newline for this tab/sheet
00645                 );
00646             }
00647 
00648             if (count($parts) > 1) {
00649                     // Unset the current level of tab menus:
00650                 $this->popFromDynNestedStack('tab', $tabIdentStringMD5 . '-' . ($out_sheet + 1));
00651                 $dividersToTabsBehaviour = (isset($TCA[$table]['ctrl']['dividers2tabs']) ? $TCA[$table]['ctrl']['dividers2tabs'] : 1);
00652                 $output = $this->getDynTabMenu($parts, $tabIdentString, $dividersToTabsBehaviour);
00653 
00654             } else {
00655                     // If there is only one tab/part there is no need to wrap it into the dynTab code
00656                 $output = isset($parts[0]) ? trim($parts[0]['content']) : '';
00657             }
00658 
00659             $output = '
00660                 <tr>
00661                     <td colspan="2">
00662                     ' . $output . '
00663                     </td>
00664                 </tr>';
00665 
00666         } else {
00667                 // Only one, so just implode:
00668             $output = implode('', $out_array[$out_sheet]);
00669         }
00670 
00671         return $output;
00672     }
00673 
00674     /**
00675      * Will return the TCEform elements for a pre-defined list of fields.
00676      * Notice that this will STILL use the configuration found in the list [types][showitem] for those fields which are found there. So ideally the list of fields given as argument to this function should also be in the current [types][showitem] list of the record.
00677      * Used for displaying forms for the frontend edit icons for instance.
00678      *
00679      * @param   string      The table name
00680      * @param   array       The record array.
00681      * @param   string      Commalist of fields from the table. These will be shown in the specified order in a form.
00682      * @return  string      TCEform elements in a string.
00683      */
00684     function getListedFields($table, $row, $list) {
00685         global $TCA;
00686 
00687         t3lib_div::loadTCA($table);
00688         if ($this->edit_showFieldHelp || $this->doLoadTableDescr($table)) {
00689             $GLOBALS['LANG']->loadSingleTableDescription($table);
00690         }
00691 
00692         $out = '';
00693         $types_fieldConfig = t3lib_BEfunc::getTCAtypes($table, $row, 1);
00694 
00695         $editFieldList = array_unique(t3lib_div::trimExplode(',', $list, 1));
00696         foreach ($editFieldList as $theFieldC) {
00697             list($theField, $palFields) = preg_split('/\[|\]/', $theFieldC);
00698             $theField = trim($theField);
00699             $palFields = trim($palFields);
00700             if ($TCA[$table]['columns'][$theField]) {
00701                 $parts = t3lib_div::trimExplode(';', $types_fieldConfig[$theField]['origString']);
00702                 $sField = $this->getSingleField($table, $theField, $row, $parts[1], 0, $parts[3], 0); // Don't sent palette pointer - there are no options anyways for a field-list.
00703                 $out .= $sField;
00704             } elseif ($theField == '--div--') {
00705                 $out .= $this->getDivider();
00706             }
00707             if ($palFields) {
00708                 $out .= $this->getPaletteFields($table, $row, '', '', implode(',', t3lib_div::trimExplode('|', $palFields, 1)));
00709             }
00710         }
00711 
00712         return $out;
00713     }
00714 
00715     /**
00716      * Creates a palette (collection of secondary options).
00717      *
00718      * @param   string      The table name
00719      * @param   array       The row array
00720      * @param   string      The palette number/pointer
00721      * @param   string      Header string for the palette (used when in-form). If not set, no header item is made.
00722      * @param   string      Optional alternative list of fields for the palette
00723      * @param   string      Optional Link text for activating a palette (when palettes does not have another form element to belong to).
00724      * @return  string      HTML code.
00725      */
00726     function getPaletteFields($table, $row, $palette, $header = '', $itemList = '', $collapsedHeader = NULL) {
00727         if (!$this->doPrintPalette) {
00728             return '';
00729         }
00730 
00731         $out = '';
00732         $parts = $this->loadPaletteElements($table, $row, $palette, $itemList);
00733 
00734             // Put palette together if there are fields in it:
00735         if (count($parts)) {
00736 
00737             $realFields = 0;
00738 
00739             foreach ($parts as $part) {
00740                 if ($part['NAME'] !== '--linebreak--') {
00741                     $realFields++;
00742                 }
00743             }
00744 
00745             if ($realFields > 0) {
00746 
00747                 if ($header) {
00748                     $out .= $this->intoTemplate(
00749                         array('HEADER' => htmlspecialchars($header)),
00750                         $this->palFieldTemplateHeader
00751                     );
00752                 }
00753 
00754                 $collapsed = $this->isPalettesCollapsed($table, $palette);
00755 
00756                 $thePalIcon = '';
00757                 if ($collapsed && $collapsedHeader !== NULL) {
00758                     list($thePalIcon,) = $this->wrapOpenPalette(
00759                         t3lib_iconWorks::getSpriteIcon(
00760                             'actions-system-options-view',
00761                             array('title' => htmlspecialchars($this->getLL('l_moreOptions')))
00762                         ), $table, $row, $palette, 1);
00763                     $thePalIcon = '<span style="margin-left: 20px;">' . $thePalIcon . $collapsedHeader . '</span>';
00764                 }
00765 
00766                 $paletteHtml = $this->wrapPaletteField($this->printPalette($parts), $table, $row, $palette, $collapsed);
00767 
00768                 $out .= $this->intoTemplate(
00769                     array('PALETTE' => $thePalIcon . $paletteHtml),
00770                     $this->palFieldTemplate
00771                 );
00772             }
00773         }
00774         return $out;
00775     }
00776 
00777     /**
00778      * Returns the form HTML code for a database table field.
00779      *
00780      * @param   string      The table name
00781      * @param   string      The field name
00782      * @param   array       The record to edit from the database table.
00783      * @param   string      Alternative field name label to show.
00784      * @param   boolean     Set this if the field is on a palette (in top frame), otherwise not. (if set, field will render as a hidden field).
00785      * @param   string      The "extra" options from "Part 4" of the field configurations found in the "types" "showitem" list. Typically parsed by $this->getSpecConfFromString() in order to get the options as an associative array.
00786      * @param   integer     The palette pointer.
00787      * @return  mixed       String (normal) or array (palettes)
00788      */
00789     function getSingleField($table, $field, $row, $altName = '', $palette = 0, $extra = '', $pal = 0) {
00790         global $TCA, $BE_USER;
00791 
00792             // Hook: getSingleField_preProcess
00793         foreach ($this->hookObjectsSingleField as $hookObj) {
00794             if (method_exists($hookObj, 'getSingleField_preProcess')) {
00795                 $hookObj->getSingleField_preProcess($table, $field, $row, $altName, $palette, $extra, $pal, $this);
00796             }
00797         }
00798 
00799         $out = '';
00800         $PA = array();
00801         $PA['altName'] = $altName;
00802         $PA['palette'] = $palette;
00803         $PA['extra'] = $extra;
00804         $PA['pal'] = $pal;
00805 
00806             // Make sure to load full $TCA array for the table:
00807         t3lib_div::loadTCA($table);
00808 
00809             // Get the TCA configuration for the current field:
00810         $PA['fieldConf'] = $TCA[$table]['columns'][$field];
00811         $PA['fieldConf']['config']['form_type'] = $PA['fieldConf']['config']['form_type'] ? $PA['fieldConf']['config']['form_type'] : $PA['fieldConf']['config']['type']; // Using "form_type" locally in this script
00812 
00813         $skipThisField = $this->inline->skipField($table, $field, $row, $PA['fieldConf']['config']);
00814 
00815             // Now, check if this field is configured and editable (according to excludefields + other configuration)
00816         if (is_array($PA['fieldConf']) &&
00817             !$skipThisField &&
00818             (!$PA['fieldConf']['exclude'] || $BE_USER->check('non_exclude_fields', $table . ':' . $field)) &&
00819             $PA['fieldConf']['config']['form_type'] != 'passthrough' &&
00820             ($this->RTEenabled || !$PA['fieldConf']['config']['showIfRTE']) &&
00821             (!$PA['fieldConf']['displayCond'] || $this->isDisplayCondition($PA['fieldConf']['displayCond'], $row)) &&
00822             (!$TCA[$table]['ctrl']['languageField'] || $PA['fieldConf']['l10n_display'] || strcmp($PA['fieldConf']['l10n_mode'], 'exclude') || $row[$TCA[$table]['ctrl']['languageField']] <= 0) &&
00823             (!$TCA[$table]['ctrl']['languageField'] || !$this->localizationMode || $this->localizationMode === $PA['fieldConf']['l10n_cat'])
00824         ) {
00825 
00826 
00827                 // Fetching the TSconfig for the current table/field. This includes the $row which means that
00828             $PA['fieldTSConfig'] = $this->setTSconfig($table, $row, $field);
00829 
00830                 // If the field is NOT disabled from TSconfig (which it could have been) then render it
00831             if (!$PA['fieldTSConfig']['disabled']) {
00832                     // Override fieldConf by fieldTSconfig:
00833                 $PA['fieldConf']['config'] = $this->overrideFieldConf($PA['fieldConf']['config'], $PA['fieldTSConfig']);
00834 
00835                     // Init variables:
00836                 $PA['itemFormElName'] = $this->prependFormFieldNames . '[' . $table . '][' . $row['uid'] . '][' . $field . ']'; // Form field name
00837                 $PA['itemFormElName_file'] = $this->prependFormFieldNames_file . '[' . $table . '][' . $row['uid'] . '][' . $field . ']'; // Form field name, in case of file uploads
00838                 $PA['itemFormElValue'] = $row[$field]; // The value to show in the form field.
00839                 $PA['itemFormElID'] = $this->prependFormFieldNames . '_' . $table . '_' . $row['uid'] . '_' . $field;
00840 
00841                     // set field to read-only if configured for translated records to show default language content as readonly
00842                 if ($PA['fieldConf']['l10n_display'] && t3lib_div::inList($PA['fieldConf']['l10n_display'], 'defaultAsReadonly') && $row[$TCA[$table]['ctrl']['languageField']] > 0) {
00843                     $PA['fieldConf']['config']['readOnly'] = true;
00844                     $PA['itemFormElValue'] = $this->defaultLanguageData[$table . ':' . $row['uid']][$field];
00845                 }
00846 
00847                     // Create a JavaScript code line which will ask the user to save/update the form due to changing the element. This is used for eg. "type" fields and others configured with "requestUpdate"
00848                 if (
00849                     ($TCA[$table]['ctrl']['type'] && !strcmp($field, $TCA[$table]['ctrl']['type'])) ||
00850                     ($TCA[$table]['ctrl']['requestUpdate'] && t3lib_div::inList($TCA[$table]['ctrl']['requestUpdate'], $field))) {
00851                     if ($GLOBALS['BE_USER']->jsConfirmation(1)) {
00852                         $alertMsgOnChange = 'if (confirm(TBE_EDITOR.labels.onChangeAlert) && TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };';
00853                     } else {
00854                         $alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };';
00855                     }
00856                 } else {
00857                     $alertMsgOnChange = '';
00858                 }
00859 
00860                     // Render as a hidden field?
00861                 if (in_array($field, $this->hiddenFieldListArr)) {
00862                     $this->hiddenFieldAccum[] = '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
00863                 } else { // Render as a normal field:
00864 
00865                         // If the field is NOT a palette field, then we might create an icon which links to a palette for the field, if one exists.
00866                     if (!$PA['palette']) {
00867                         $paletteFields = $this->loadPaletteElements($table, $row, $PA['pal']);
00868                         if ($PA['pal'] && $this->isPalettesCollapsed($table, $PA['pal']) && count($paletteFields)) {
00869                             list($thePalIcon, $palJSfunc) = $this->wrapOpenPalette(t3lib_iconWorks::getSpriteIcon('actions-system-options-view', array('title' => htmlspecialchars($this->getLL('l_moreOptions')))), $table, $row, $PA['pal'], 1);
00870                         } else {
00871                             $thePalIcon = '';
00872                             $palJSfunc = '';
00873                         }
00874                     }
00875                         // onFocus attribute to add to the field:
00876                     $PA['onFocus'] = ($palJSfunc && !$BE_USER->uc['dontShowPalettesOnFocusInAB']) ? ' onfocus="' . htmlspecialchars($palJSfunc) . '"' : '';
00877 
00878                         // Find item
00879                     $item = '';
00880                     $PA['label'] = ($PA['altName'] ? $PA['altName'] : $PA['fieldConf']['label']);
00881                     $PA['label'] = ($PA['fieldTSConfig']['label'] ? $PA['fieldTSConfig']['label'] : $PA['label']);
00882                     $PA['label'] = ($PA['fieldTSConfig']['label.'][$GLOBALS['LANG']->lang] ? $PA['fieldTSConfig']['label.'][$GLOBALS['LANG']->lang] : $PA['label']);
00883                     $PA['label'] = $this->sL($PA['label']);
00884                         // JavaScript code for event handlers:
00885                     $PA['fieldChangeFunc'] = array();
00886                     $PA['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = "TBE_EDITOR.fieldChanged('" . $table . "','" . $row['uid'] . "','" . $field . "','" . $PA['itemFormElName'] . "');";
00887                     $PA['fieldChangeFunc']['alert'] = $alertMsgOnChange;
00888                         // if this is the child of an inline type and it is the field creating the label
00889                     if ($this->inline->isInlineChildAndLabelField($table, $field)) {
00890                         $inlineObjectId = implode(
00891                             t3lib_TCEforms_inline::Structure_Separator,
00892                             array(
00893                                  $this->inline->inlineNames['object'],
00894                                  $table,
00895                                  $row['uid']
00896                             )
00897                         );
00898                         $PA['fieldChangeFunc']['inline'] = "inline.handleChangedField('" . $PA['itemFormElName'] . "','" . $inlineObjectId . "');";
00899                     }
00900 
00901                         // Based on the type of the item, call a render function:
00902                     $item = $this->getSingleField_SW($table, $field, $row, $PA);
00903 
00904                         // Add language + diff
00905                     if ($PA['fieldConf']['l10n_display'] && (t3lib_div::inList($PA['fieldConf']['l10n_display'], 'hideDiff') || t3lib_div::inList($PA['fieldConf']['l10n_display'], 'defaultAsReadonly'))) {
00906                         $renderLanguageDiff = false;
00907                     } else {
00908                         $renderLanguageDiff = true;
00909                     }
00910 
00911                     if ($renderLanguageDiff) {
00912                         $item = $this->renderDefaultLanguageContent($table, $field, $row, $item);
00913                         $item = $this->renderDefaultLanguageDiff($table, $field, $row, $item);
00914                     }
00915 
00916                         // If the record has been saved and the "linkTitleToSelf" is set, we make the field name into a link, which will load ONLY this field in alt_doc.php
00917                     $label = t3lib_div::deHSCentities(htmlspecialchars($PA['label']));
00918                     if (t3lib_div::testInt($row['uid']) && $PA['fieldTSConfig']['linkTitleToSelf'] && !t3lib_div::_GP('columnsOnly')) {
00919                         $lTTS_url = $this->backPath . 'alt_doc.php?edit[' . $table . '][' . $row['uid'] . ']=edit&columnsOnly=' . $field . '&returnUrl=' . rawurlencode($this->thisReturnUrl());
00920                         $label = '<a href="' . htmlspecialchars($lTTS_url) . '">' . $label . '</a>';
00921                     }
00922 
00923                         // wrap the label with help text
00924                     $PA['label'] = $label = t3lib_BEfunc::wrapInHelp($table, $field, $label);
00925 
00926                         // Create output value:
00927                     if ($PA['fieldConf']['config']['form_type'] == 'user' && $PA['fieldConf']['config']['noTableWrapping']) {
00928                         $out = $item;
00929                     } elseif ($PA['palette']) {
00930                             // Array:
00931                         $out = array(
00932                             'NAME' => $label,
00933                             'ID' => $row['uid'],
00934                             'FIELD' => $field,
00935                             'TABLE' => $table,
00936                             'ITEM' => $item
00937                         );
00938                         $out = $this->addUserTemplateMarkers($out, $table, $field, $row, $PA);
00939                     } else {
00940                             // String:
00941                         $out = array(
00942                             'NAME' => $label,
00943                             'ITEM' => $item,
00944                             'TABLE' => $table,
00945                             'ID' => $row['uid'],
00946                             'PAL_LINK_ICON' => $thePalIcon,
00947                             'FIELD' => $field
00948                         );
00949                         $out = $this->addUserTemplateMarkers($out, $table, $field, $row, $PA);
00950                             // String:
00951                         $out = $this->intoTemplate($out);
00952                     }
00953                 }
00954             } else {
00955                 $this->commentMessages[] = $this->prependFormFieldNames . '[' . $table . '][' . $row['uid'] . '][' . $field . ']: Disabled by TSconfig';
00956             }
00957         }
00958             // Hook: getSingleField_postProcess
00959         foreach ($this->hookObjectsSingleField as $hookObj) {
00960             if (method_exists($hookObj, 'getSingleField_postProcess')) {
00961                 $hookObj->getSingleField_postProcess($table, $field, $row, $out, $PA, $this);
00962             }
00963         }
00964             // Return value (string or array)
00965         return $out;
00966     }
00967 
00968     /**
00969      * Rendering a single item for the form
00970      *
00971      * @param   string      Table name of record
00972      * @param   string      Fieldname to render
00973      * @param   array       The record
00974      * @param   array       parameters array containing a lot of stuff. Value by Reference!
00975      * @return  string      Returns the item as HTML code to insert
00976      * @access private
00977      * @see getSingleField(), getSingleField_typeFlex_draw()
00978      */
00979     function getSingleField_SW($table, $field, $row, &$PA) {
00980         $PA['fieldConf']['config']['form_type'] = $PA['fieldConf']['config']['form_type'] ? $PA['fieldConf']['config']['form_type'] : $PA['fieldConf']['config']['type']; // Using "form_type" locally in this script
00981 
00982             // Hook: getSingleField_beforeRender
00983         foreach ($this->hookObjectsSingleField as $hookObject) {
00984             if (method_exists($hookObject, 'getSingleField_beforeRender')) {
00985                 $hookObject->getSingleField_beforeRender($table, $field, $row, $PA);
00986             }
00987         }
00988 
00989         switch ($PA['fieldConf']['config']['form_type']) {
00990             case 'input':
00991                 $item = $this->getSingleField_typeInput($table, $field, $row, $PA);
00992             break;
00993             case 'text':
00994                 $item = $this->getSingleField_typeText($table, $field, $row, $PA);
00995             break;
00996             case 'check':
00997                 $item = $this->getSingleField_typeCheck($table, $field, $row, $PA);
00998             break;
00999             case 'radio':
01000                 $item = $this->getSingleField_typeRadio($table, $field, $row, $PA);
01001             break;
01002             case 'select':
01003                 $item = $this->getSingleField_typeSelect($table, $field, $row, $PA);
01004             break;
01005             case 'group':
01006                 $item = $this->getSingleField_typeGroup($table, $field, $row, $PA);
01007             break;
01008             case 'inline':
01009                 $item = $this->inline->getSingleField_typeInline($table, $field, $row, $PA);
01010             break;
01011             case 'none':
01012                 $item = $this->getSingleField_typeNone($table, $field, $row, $PA);
01013             break;
01014             case 'user':
01015                 $item = $this->getSingleField_typeUser($table, $field, $row, $PA);
01016             break;
01017             case 'flex':
01018                 $item = $this->getSingleField_typeFlex($table, $field, $row, $PA);
01019             break;
01020             default:
01021                 $item = $this->getSingleField_typeUnknown($table, $field, $row, $PA);
01022             break;
01023         }
01024 
01025         return $item;
01026     }
01027 
01028 
01029     /**********************************************************
01030      *
01031      * Rendering of each TCEform field type
01032      *
01033      ************************************************************/
01034 
01035     /**
01036      * Generation of TCEform elements of the type "input"
01037      * This will render a single-line input form field, possibly with various control/validation features
01038      *
01039      * @param   string      The table name of the record
01040      * @param   string      The field name which this element is supposed to edit
01041      * @param   array       The record data array where the value(s) for the field can be found
01042      * @param   array       An array with additional configuration options.
01043      * @return  string      The HTML code for the TCEform field
01044      */
01045     function getSingleField_typeInput($table, $field, $row, &$PA) {
01046         $config = $PA['fieldConf']['config'];
01047 
01048         $specConf = $this->getSpecConfFromString($PA['extra'], $PA['fieldConf']['defaultExtras']);
01049         $size = t3lib_div::intInRange($config['size'] ? $config['size'] : 30, 5, $this->maxInputWidth);
01050         $evalList = t3lib_div::trimExplode(',', $config['eval'], 1);
01051         $classAndStyleAttributes = $this->formWidthAsArray($size);
01052 
01053         $fieldAppendix = '';
01054         $cssClasses = array($classAndStyleAttributes['class']);
01055         $cssStyle = $classAndStyleAttributes['style'];
01056 
01057         if (!isset($config['checkbox'])) {
01058             $config['checkbox'] = '0';
01059             $checkboxIsset = FALSE;
01060         } else {
01061             $checkboxIsset = TRUE;
01062         }
01063 
01064         if (in_array('date', $evalList) || in_array('datetime', $evalList)) {
01065             if (in_array('datetime', $evalList)) {
01066                 $class = 'datetime';
01067             } else {
01068                 $class = 'date';
01069             }
01070             $dateRange = '';
01071             if (isset($config['range']['lower'])) {
01072                 $dateRange .= ' lower-' . intval($config['range']['lower']);
01073             }
01074             if (isset($config['range']['upper'])) {
01075                 $dateRange .= ' upper-' . intval($config['range']['upper']);
01076             }
01077             $inputId = uniqid('tceforms-' . $class . 'field-');
01078             $cssClasses[] = 'tceforms-textfield tceforms-' . $class . 'field' . $dateRange;
01079             $fieldAppendix = t3lib_iconWorks::getSpriteIcon(
01080                 'actions-edit-pick-date',
01081                 array(
01082                      'style' => 'cursor:pointer;',
01083                      'id' => 'picker-' . $inputId
01084                 )
01085             );
01086         } elseif (in_array('timesec', $evalList)) {
01087             $inputId = uniqid('tceforms-timesecfield-');
01088             $cssClasses[] = 'tceforms-textfield tceforms-timesecfield';
01089         } elseif (in_array('year', $evalList)) {
01090             $inputId = uniqid('tceforms-yearfield-');
01091             $cssClasses[] = 'tceforms-textfield tceforms-yearfield';
01092         } elseif (in_array('time', $evalList)) {
01093             $inputId = uniqid('tceforms-timefield-');
01094             $cssClasses[] = 'tceforms-textfield tceforms-timefield';
01095         } elseif (in_array('int', $evalList)) {
01096             $inputId = uniqid('tceforms-intfield-');
01097             $cssClasses[] = 'tceforms-textfield tceforms-intfield';
01098         } elseif (in_array('double2', $evalList)) {
01099             $inputId = uniqid('tceforms-double2field-');
01100             $cssClasses[] = 'tceforms-textfield tceforms-double2field';
01101         } else {
01102             $inputId = uniqid('tceforms-textfield-');
01103             $cssClasses[] = 'tceforms-textfield';
01104             if ($checkboxIsset === FALSE) {
01105                 $config['checkbox'] = '';
01106             }
01107         }
01108         if (isset($config['wizards']['link'])) {
01109             $inputId = uniqid('tceforms-linkfield-');
01110             $cssClasses[] = 'tceforms-textfield tceforms-linkfield';
01111 
01112         } elseif (isset($config['wizards']['color'])) {
01113             $inputId = uniqid('tceforms-colorfield-');
01114             $cssClasses[] = 'tceforms-textfield tceforms-colorfield';
01115         }
01116 
01117         if ($this->renderReadonly || $config['readOnly']) {
01118             $itemFormElValue = $PA['itemFormElValue'];
01119             if (in_array('date', $evalList)) {
01120                 $config['format'] = 'date';
01121             } elseif (in_array('datetime', $evalList)) {
01122                 $config['format'] = 'datetime';
01123             } elseif (in_array('time', $evalList)) {
01124                 $config['format'] = 'time';
01125             }
01126             if (in_array('password', $evalList)) {
01127                 $itemFormElValue = $itemFormElValue ? '*********' : '';
01128             }
01129             return $this->getSingleField_typeNone_render($config, $itemFormElValue);
01130         }
01131 
01132         foreach ($evalList as $func) {
01133             switch ($func) {
01134                 case 'required':
01135                     $this->registerRequiredProperty('field', $table . '_' . $row['uid'] . '_' . $field, $PA['itemFormElName']);
01136                         // Mark this field for date/time disposal:
01137                     if (array_intersect($evalList, array('date', 'datetime', 'time'))) {
01138                         $this->requiredAdditional[$PA['itemFormElName']]['isPositiveNumber'] = true;
01139                     }
01140                 break;
01141                 default:
01142                     if (substr($func, 0, 3) == 'tx_') {
01143                             // Pair hook to the one in t3lib_TCEmain::checkValue_input_Eval()
01144                         $evalObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func] . ':&' . $func);
01145                         if (is_object($evalObj) && method_exists($evalObj, 'deevaluateFieldValue')) {
01146                             $_params = array(
01147                                 'value' => $PA['itemFormElValue']
01148                             );
01149                             $PA['itemFormElValue'] = $evalObj->deevaluateFieldValue($_params);
01150                         }
01151                     }
01152                 break;
01153             }
01154         }
01155 
01156         $paramsList = "'" . $PA['itemFormElName'] . "','" . implode(',', $evalList) . "','" . trim($config['is_in']) . "'," . (isset($config['checkbox']) ? 1 : 0) . ",'" . $config['checkbox'] . "'";
01157         if ((in_array('date', $evalList) || in_array('datetime', $evalList))) {
01158             $item .= '<span class="t3-tceforms-input-wrapper-datetime" onmouseOver="if (document.getElementById(\'' .
01159                      $inputId . '\').value) {this.className=\'t3-tceforms-input-wrapper-datetime-hover\';} else {this.className=\'t3-tceforms-input-wrapper-datetime\';};" onmouseOut="this.className=\'t3-tceforms-input-wrapper-datetime\';">';
01160 
01161                 // Add server timezone offset to UTC to our stored date
01162             if ($PA['itemFormElValue'] > 0) {
01163                 $PA['itemFormElValue'] += date('Z', $PA['itemFormElValue']);
01164             }
01165         } else {
01166             $item .= '<span class="t3-tceforms-input-wrapper" onmouseOver="if (document.getElementById(\'' . $inputId .
01167                      '\').value) {this.className=\'t3-tceforms-input-wrapper-hover\';} else {this.className=\'t3-tceforms-input-wrapper\';};" onmouseOut="this.className=\'t3-tceforms-input-wrapper\';">';
01168         }
01169 
01170         $PA['fieldChangeFunc'] = array_merge(
01171             array('typo3form.fieldGet' => 'typo3form.fieldGet(' . $paramsList . ');'),
01172             $PA['fieldChangeFunc']
01173         );
01174             // old function "checkbox" now the option to set the date / remove the date
01175         if (isset($config['checkbox'])) {
01176             $item .= t3lib_iconWorks::getSpriteIcon('actions-input-clear', array('tag' => 'a', 'class' => 't3-tceforms-input-clearer', 'onclick' => 'document.getElementById(\'' . $inputId . '\').value=\'\';document.getElementById(\'' . $inputId . '\').focus();' . implode('', $PA['fieldChangeFunc'])));
01177         }
01178         $mLgd = ($config['max'] ? $config['max'] : 256);
01179         $iOnChange = implode('', $PA['fieldChangeFunc']);
01180 
01181         $item .= '<input type="text" id="' . $inputId .
01182                  '" class="' . implode(' ', $cssClasses) . '" name="' . $PA['itemFormElName'] .
01183                  '_hr" value="" style="' . $cssStyle . '" maxlength="' . $mLgd . '" onchange="' .
01184                  htmlspecialchars($iOnChange) . '"' . $PA['onFocus'] . ' />'; // This is the EDITABLE form field.
01185         $item .= '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' .
01186                  htmlspecialchars($PA['itemFormElValue']) . '" />'; // This is the ACTUAL form field - values from the EDITABLE field must be transferred to this field which is the one that is written to the database.
01187         $item .= $fieldAppendix . '</span><div style="clear:both;"></div>';
01188         $this->extJSCODE .= 'typo3form.fieldSet(' . $paramsList . ');';
01189 
01190             // going through all custom evaluations configured for this field
01191         foreach ($evalList as $evalData) {
01192             if (substr($evalData, 0, 3) == 'tx_') {
01193                 $evalObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$evalData] . ':&' . $evalData);
01194                 if (is_object($evalObj) && method_exists($evalObj, 'returnFieldJS')) {
01195                     $this->extJSCODE .= "\n\nfunction " . $evalData . "(value) {\n" . $evalObj->returnFieldJS() . "\n}\n";
01196                 }
01197             }
01198         }
01199 
01200             // Creating an alternative item without the JavaScript handlers.
01201         $altItem = '<input type="hidden" name="' . $PA['itemFormElName'] . '_hr" value="" />';
01202         $altItem .= '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
01203 
01204             // Wrap a wizard around the item?
01205         $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'] . '_hr', $specConf);
01206 
01207         return $item;
01208     }
01209 
01210     /**
01211      * Generation of TCEform elements of the type "text"
01212      * This will render a <textarea> OR RTE area form field, possibly with various control/validation features
01213      *
01214      * @param   string      The table name of the record
01215      * @param   string      The field name which this element is supposed to edit
01216      * @param   array       The record data array where the value(s) for the field can be found
01217      * @param   array       An array with additional configuration options.
01218      * @return  string      The HTML code for the TCEform field
01219      */
01220     function getSingleField_typeText($table, $field, $row, &$PA) {
01221 
01222             // Init config:
01223         $config = $PA['fieldConf']['config'];
01224         $evalList = t3lib_div::trimExplode(',', $config['eval'], 1);
01225 
01226         if ($this->renderReadonly || $config['readOnly']) {
01227             return $this->getSingleField_typeNone_render($config, $PA['itemFormElValue']);
01228         }
01229 
01230             // Setting columns number:
01231         $cols = t3lib_div::intInRange($config['cols'] ? $config['cols'] : 30, 5, $this->maxTextareaWidth);
01232 
01233             // Setting number of rows:
01234         $origRows = $rows = t3lib_div::intInRange($config['rows'] ? $config['rows'] : 5, 1, 20);
01235         if (strlen($PA['itemFormElValue']) > $this->charsPerRow * 2) {
01236             $cols = $this->maxTextareaWidth;
01237             $rows = t3lib_div::intInRange(round(strlen($PA['itemFormElValue']) / $this->charsPerRow), count(explode(LF, $PA['itemFormElValue'])), 20);
01238             if ($rows < $origRows) {
01239                 $rows = $origRows;
01240             }
01241         }
01242 
01243         if (in_array('required', $evalList)) {
01244             $this->requiredFields[$table . '_' . $row['uid'] . '_' . $field] = $PA['itemFormElName'];
01245         }
01246 
01247             // Init RTE vars:
01248         $RTEwasLoaded = 0; // Set true, if the RTE is loaded; If not a normal textarea is shown.
01249         $RTEwouldHaveBeenLoaded = 0; // Set true, if the RTE would have been loaded if it wasn't for the disable-RTE flag in the bottom of the page...
01250 
01251             // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. Traditionally, this is where RTE configuration has been found.
01252         $specConf = $this->getSpecConfFromString($PA['extra'], $PA['fieldConf']['defaultExtras']);
01253 
01254             // Setting up the altItem form field, which is a hidden field containing the value
01255         $altItem = '<input type="hidden" name="' . htmlspecialchars($PA['itemFormElName']) . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
01256 
01257             // If RTE is generally enabled (TYPO3_CONF_VARS and user settings)
01258         if ($this->RTEenabled) {
01259             $p = t3lib_BEfunc::getSpecConfParametersFromArray($specConf['rte_transform']['parameters']);
01260             if (isset($specConf['richtext']) && (!$p['flag'] || !$row[$p['flag']])) { // If the field is configured for RTE and if any flag-field is not set to disable it.
01261                 t3lib_BEfunc::fixVersioningPid($table, $row);
01262                 list($tscPID, $thePidValue) = $this->getTSCpid($table, $row['uid'], $row['pid']);
01263 
01264                     // If the pid-value is not negative (that is, a pid could NOT be fetched)
01265                 if ($thePidValue >= 0) {
01266                     $RTEsetup = $GLOBALS['BE_USER']->getTSConfig('RTE', t3lib_BEfunc::getPagesTSconfig($tscPID));
01267                     $RTEtypeVal = t3lib_BEfunc::getTCAtypeValue($table, $row);
01268                     $thisConfig = t3lib_BEfunc::RTEsetup($RTEsetup['properties'], $table, $field, $RTEtypeVal);
01269 
01270                     if (!$thisConfig['disabled']) {
01271                         if (!$this->disableRTE) {
01272                             $this->RTEcounter++;
01273 
01274                                 // Find alternative relative path for RTE images/links:
01275                             $eFile = t3lib_parsehtml_proc::evalWriteFile($specConf['static_write'], $row);
01276                             $RTErelPath = is_array($eFile) ? dirname($eFile['relEditFile']) : '';
01277 
01278                                 // Get RTE object, draw form and set flag:
01279                             $RTEobj = t3lib_BEfunc::RTEgetObj();
01280                             $item = $RTEobj->drawRTE($this, $table, $field, $row, $PA, $specConf, $thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue);
01281 
01282                                 // Wizard:
01283                             $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'], $specConf, 1);
01284 
01285                             $RTEwasLoaded = 1;
01286                         } else {
01287                             $RTEwouldHaveBeenLoaded = 1;
01288                             $this->commentMessages[] = $PA['itemFormElName'] . ': RTE is disabled by the on-page RTE-flag (probably you can enable it by the check-box in the bottom of this page!)';
01289                         }
01290                     } else {
01291                         $this->commentMessages[] = $PA['itemFormElName'] . ': RTE is disabled by the Page TSconfig, "RTE"-key (eg. by RTE.default.disabled=0 or such)';
01292                     }
01293                 } else {
01294                     $this->commentMessages[] = $PA['itemFormElName'] . ': PID value could NOT be fetched. Rare error, normally with new records.';
01295                 }
01296             } else {
01297                 if (!isset($specConf['richtext'])) {
01298                     $this->commentMessages[] = $PA['itemFormElName'] . ': RTE was not configured for this field in TCA-types';
01299                 }
01300                 if (!(!$p['flag'] || !$row[$p['flag']])) {
01301                     $this->commentMessages[] = $PA['itemFormElName'] . ': Field-flag (' . $PA['flag'] . ') has been set to disable RTE!';
01302                 }
01303             }
01304         }
01305 
01306             // Display ordinary field if RTE was not loaded.
01307         if (!$RTEwasLoaded) {
01308             if ($specConf['rte_only']) { // Show message, if no RTE (field can only be edited with RTE!)
01309                 $item = '<p><em>' . htmlspecialchars($this->getLL('l_noRTEfound')) . '</em></p>';
01310             } else {
01311                 if ($specConf['nowrap']) {
01312                     $wrap = 'off';
01313                 } else {
01314                     $wrap = ($config['wrap'] ? $config['wrap'] : 'virtual');
01315                 }
01316 
01317                 $classes = array();
01318                 if ($specConf['fixed-font']) {
01319                     $classes[] = 'fixed-font';
01320                 }
01321                 if ($specConf['enable-tab']) {
01322                     $classes[] = 'enable-tab';
01323                 }
01324 
01325                 $formWidthText = $this->formWidthText($cols, $wrap);
01326 
01327                     // Extract class attributes from $formWidthText (otherwise it would be added twice to the output)
01328                 $res = array();
01329                 if (preg_match('/ class="(.+?)"/', $formWidthText, $res)) {
01330                     $formWidthText = str_replace(' class="' . $res[1] . '"', '', $formWidthText);
01331                     $classes = array_merge($classes, explode(' ', $res[1]));
01332                 }
01333 
01334                 if (count($classes)) {
01335                     $class = ' class="tceforms-textarea ' . implode(' ', $classes) . '"';
01336                 } else {
01337                     $class = 'tceforms-textarea';
01338                 }
01339 
01340                 $evalList = t3lib_div::trimExplode(',', $config['eval'], 1);
01341                 foreach ($evalList as $func) {
01342                     switch ($func) {
01343                         case 'required':
01344                             $this->registerRequiredProperty('field', $table . '_' . $row['uid'] . '_' . $field, $PA['itemFormElName']);
01345                         break;
01346                         default:
01347                             if (substr($func, 0, 3) == 'tx_') {
01348                                     // Pair hook to the one in t3lib_TCEmain::checkValue_input_Eval() and t3lib_TCEmain::checkValue_text_Eval()
01349                                 $evalObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func] . ':&' . $func);
01350                                 if (is_object($evalObj) && method_exists($evalObj, 'deevaluateFieldValue')) {
01351                                     $_params = array(
01352                                         'value' => $PA['itemFormElValue']
01353                                     );
01354                                     $PA['itemFormElValue'] = $evalObj->deevaluateFieldValue($_params);
01355                                 }
01356                             }
01357                         break;
01358                     }
01359                 }
01360 
01361                 $iOnChange = implode('', $PA['fieldChangeFunc']);
01362                 $item .= '
01363                             <textarea id="' . uniqid('tceforms-textarea-') . '" name="' . $PA['itemFormElName'] . '"' . $formWidthText . $class . ' rows="' . $rows . '" wrap="' . $wrap . '" onchange="' . htmlspecialchars($iOnChange) . '"' . $PA['onFocus'] . '>' .
01364                          t3lib_div::formatForTextarea($PA['itemFormElValue']) .
01365                          '</textarea>';
01366                 $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'], $specConf, $RTEwouldHaveBeenLoaded);
01367             }
01368         }
01369 
01370             // Return field HTML:
01371         return $item;
01372     }
01373 
01374     /**
01375      * Generation of TCEform elements of the type "check"
01376      * This will render a check-box OR an array of checkboxes
01377      *
01378      * @param   string      The table name of the record
01379      * @param   string      The field name which this element is supposed to edit
01380      * @param   array       The record data array where the value(s) for the field can be found
01381      * @param   array       An array with additional configuration options.
01382      * @return  string      The HTML code for the TCEform field
01383      */
01384     function getSingleField_typeCheck($table, $field, $row, &$PA) {
01385         $config = $PA['fieldConf']['config'];
01386 
01387         $disabled = '';
01388         if ($this->renderReadonly || $config['readOnly']) {
01389             $disabled = ' disabled="disabled"';
01390         }
01391 
01392             // Traversing the array of items:
01393         $selItems = $this->initItemArray($PA['fieldConf']);
01394         if ($config['itemsProcFunc']) {
01395             $selItems = $this->procItems($selItems, $PA['fieldTSConfig']['itemsProcFunc.'], $config, $table, $row, $field);
01396         }
01397 
01398         if (!count($selItems)) {
01399             $selItems[] = array('', '');
01400         }
01401         $thisValue = intval($PA['itemFormElValue']);
01402 
01403         $cols = intval($config['cols']);
01404         if ($cols > 1) {
01405             $item .= '<table border="0" cellspacing="0" cellpadding="0" class="typo3-TCEforms-checkboxArray">';
01406             for ($c = 0; $c < count($selItems); $c++) {
01407                 $p = $selItems[$c];
01408                 if (!($c % $cols)) {
01409                     $item .= '<tr>';
01410                 }
01411                 $cBP = $this->checkBoxParams($PA['itemFormElName'], $thisValue, $c, count($selItems), implode('', $PA['fieldChangeFunc']));
01412                 $cBName = $PA['itemFormElName'] . '_' . $c;
01413                 $cBID = $PA['itemFormElID'] . '_' . $c;
01414                 $item .= '<td nowrap="nowrap">' .
01415                          '<input type="checkbox"' . $this->insertDefStyle('check') . ' value="1" name="' . $cBName . '"' . $cBP . $disabled . ' id="' . $cBID . '" />' .
01416                          $this->wrapLabels('<label for="' . $cBID . '">' . htmlspecialchars($p[0]) . '</label>&nbsp;') .
01417                          '</td>';
01418                 if (($c % $cols) + 1 == $cols) {
01419                     $item .= '</tr>';
01420                 }
01421             }
01422             if ($c % $cols) {
01423                 $rest = $cols - ($c % $cols);
01424                 for ($c = 0; $c < $rest; $c++) {
01425                     $item .= '<td></td>';
01426                 }
01427                 if ($c > 0) {
01428                     $item .= '</tr>';
01429                 }
01430             }
01431             $item .= '</table>';
01432         } else {
01433             for ($c = 0; $c < count($selItems); $c++) {
01434                 $p = $selItems[$c];
01435                 $cBP = $this->checkBoxParams($PA['itemFormElName'], $thisValue, $c, count($selItems), implode('', $PA['fieldChangeFunc']));
01436                 $cBName = $PA['itemFormElName'] . '_' . $c;
01437                 $cBID = $PA['itemFormElID'] . '_' . $c;
01438                 $item .= ($c > 0 ? '<br />' : '') .
01439                          '<input type="checkbox"' . $this->insertDefStyle('check') . ' value="1" name="' . $cBName . '"' . $cBP . $PA['onFocus'] . $disabled . ' id="' . $cBID . '" />' .
01440                          $this->wrapLabels('<label for="' . $cBID . '">' . htmlspecialchars($p[0]) . '</label>');
01441             }
01442         }
01443         if (!$disabled) {
01444             $item .= '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($thisValue) . '" />';
01445         }
01446 
01447         return $item;
01448     }
01449 
01450     /**
01451      * Generation of TCEform elements of the type "radio"
01452      * This will render a series of radio buttons.
01453      *
01454      * @param   string      The table name of the record
01455      * @param   string      The field name which this element is supposed to edit
01456      * @param   array       The record data array where the value(s) for the field can be found
01457      * @param   array       An array with additional configuration options.
01458      * @return  string      The HTML code for the TCEform field
01459      */
01460     function getSingleField_typeRadio($table, $field, $row, &$PA) {
01461         $config = $PA['fieldConf']['config'];
01462 
01463         $disabled = '';
01464         if ($this->renderReadonly || $config['readOnly']) {
01465             $disabled = ' disabled="disabled"';
01466         }
01467 
01468             // Get items for the array:
01469         $selItems = $this->initItemArray($PA['fieldConf']);
01470         if ($config['itemsProcFunc']) {
01471             $selItems = $this->procItems($selItems, $PA['fieldTSConfig']['itemsProcFunc.'], $config, $table, $row, $field);
01472         }
01473 
01474             // Traverse the items, making the form elements:
01475         for ($c = 0; $c < count($selItems); $c++) {
01476             $p = $selItems[$c];
01477             $rID = $PA['itemFormElID'] . '_' . $c;
01478             $rOnClick = implode('', $PA['fieldChangeFunc']);
01479             $rChecked = (!strcmp($p[1], $PA['itemFormElValue']) ? ' checked="checked"' : '');
01480             $item .= '<input type="radio"' . $this->insertDefStyle('radio') . ' name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($p[1]) . '" onclick="' . htmlspecialchars($rOnClick) . '"' . $rChecked . $PA['onFocus'] . $disabled . ' id="' . $rID . '" />
01481                     <label for="' . $rID . '">' . htmlspecialchars($p[0]) . '</label>
01482                     <br />';
01483         }
01484 
01485         return $item;
01486     }
01487 
01488     /**
01489      * Generation of TCEform elements of the type "select"
01490      * This will render a selector box element, or possibly a special construction with two selector boxes. That depends on configuration.
01491      *
01492      * @param   string      The table name of the record
01493      * @param   string      The field name which this element is supposed to edit
01494      * @param   array       The record data array where the value(s) for the field can be found
01495      * @param   array       An array with additional configuration options.
01496      * @return  string      The HTML code for the TCEform field
01497      */
01498     function getSingleField_typeSelect($table, $field, $row, &$PA) {
01499         global $TCA;
01500 
01501             // Field configuration from TCA:
01502         $config = $PA['fieldConf']['config'];
01503 
01504         $disabled = '';
01505         if ($this->renderReadonly || $config['readOnly']) {
01506             $disabled = ' disabled="disabled"';
01507         }
01508 
01509             // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. See http://typo3.org/documentation/document-library/doc_core_api/Wizards_Configuratio/.
01510         $specConf = $this->getSpecConfFromString($PA['extra'], $PA['fieldConf']['defaultExtras']);
01511 
01512             // Getting the selector box items from the system
01513         $selItems = $this->addSelectOptionsToItemArray(
01514             $this->initItemArray($PA['fieldConf']),
01515             $PA['fieldConf'],
01516             $this->setTSconfig($table, $row),
01517             $field
01518         );
01519             // Possibly filter some items:
01520         $keepItemsFunc = create_function('$value', 'return $value[1];');
01521         $selItems = t3lib_div::keepItemsInArray($selItems, $PA['fieldTSConfig']['keepItems'], $keepItemsFunc);
01522             // Possibly add some items:
01523         $selItems = $this->addItems($selItems, $PA['fieldTSConfig']['addItems.']);
01524             // Process items by a user function:
01525         if (isset($config['itemsProcFunc']) && $config['itemsProcFunc']) {
01526             $selItems = $this->procItems($selItems, $PA['fieldTSConfig']['itemsProcFunc.'], $config, $table, $row, $field);
01527         }
01528 
01529             // Possibly remove some items:
01530         $removeItems = t3lib_div::trimExplode(',', $PA['fieldTSConfig']['removeItems'], 1);
01531         foreach ($selItems as $tk => $p) {
01532 
01533                 // Checking languages and authMode:
01534             $languageDeny = $TCA[$table]['ctrl']['languageField'] && !strcmp($TCA[$table]['ctrl']['languageField'], $field) && !$GLOBALS['BE_USER']->checkLanguageAccess($p[1]);
01535             $authModeDeny = $config['form_type'] == 'select' && $config['authMode'] && !$GLOBALS['BE_USER']->checkAuthMode($table, $field, $p[1], $config['authMode']);
01536             if (in_array($p[1], $removeItems) || $languageDeny || $authModeDeny) {
01537                 unset($selItems[$tk]);
01538             } elseif (isset($PA['fieldTSConfig']['altLabels.'][$p[1]])) {
01539                 $selItems[$tk][0] = $this->sL($PA['fieldTSConfig']['altLabels.'][$p[1]]);
01540             }
01541 
01542                 // Removing doktypes with no access:
01543             if (($table === 'pages' || $table === 'pages_language_overlay') && $field === 'doktype') {
01544                 if (!($GLOBALS['BE_USER']->isAdmin() || t3lib_div::inList($GLOBALS['BE_USER']->groupData['pagetypes_select'], $p[1]))) {
01545                     unset($selItems[$tk]);
01546                 }
01547             }
01548         }
01549 
01550             // Creating the label for the "No Matching Value" entry.
01551         $nMV_label = isset($PA['fieldTSConfig']['noMatchingValue_label']) ? $this->sL($PA['fieldTSConfig']['noMatchingValue_label']) : '[ ' . $this->getLL('l_noMatchingValue') . ' ]';
01552 
01553             // Prepare some values:
01554         $maxitems = intval($config['maxitems']);
01555 
01556             // If a SINGLE selector box...
01557         if ($maxitems <= 1 && $config['renderMode'] !== 'tree') {
01558             $item = $this->getSingleField_typeSelect_single($table, $field, $row, $PA, $config, $selItems, $nMV_label);
01559         } elseif (!strcmp($config['renderMode'], 'checkbox')) { // Checkbox renderMode
01560             $item = $this->getSingleField_typeSelect_checkbox($table, $field, $row, $PA, $config, $selItems, $nMV_label);
01561         } elseif (!strcmp($config['renderMode'], 'singlebox')) { // Single selector box renderMode
01562             $item = $this->getSingleField_typeSelect_singlebox($table, $field, $row, $PA, $config, $selItems, $nMV_label);
01563         } elseif (!strcmp($config['renderMode'], 'tree')) { // Tree renderMode
01564             $treeClass = t3lib_div::makeInstance('t3lib_TCEforms_Tree', $this);
01565             $item = $treeClass->renderField($table, $field, $row, $PA, $config, $selItems, $nMV_label);
01566         } else { // Traditional multiple selector box:
01567             $item = $this->getSingleField_typeSelect_multiple($table, $field, $row, $PA, $config, $selItems, $nMV_label);
01568         }
01569 
01570             // Wizards:
01571         if (!$disabled) {
01572             $altItem = '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
01573             $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'], $specConf);
01574         }
01575 
01576         return $item;
01577     }
01578 
01579     /**
01580      * Creates a single-selector box
01581      * (Render function for getSingleField_typeSelect())
01582      *
01583      * @param   string      See getSingleField_typeSelect()
01584      * @param   string      See getSingleField_typeSelect()
01585      * @param   array       See getSingleField_typeSelect()
01586      * @param   array       See getSingleField_typeSelect()
01587      * @param   array       (Redundant) content of $PA['fieldConf']['config'] (for convenience)
01588      * @param   array       Items available for selection
01589      * @param   string      Label for no-matching-value
01590      * @return  string      The HTML code for the item
01591      * @see getSingleField_typeSelect()
01592      */
01593     function getSingleField_typeSelect_single($table, $field, $row, &$PA, $config, $selItems, $nMV_label) {
01594             // check against inline uniqueness
01595         $inlineParent = $this->inline->getStructureLevel(-1);
01596         if (is_array($inlineParent) && $inlineParent['uid']) {
01597             if ($inlineParent['config']['foreign_table'] == $table && $inlineParent['config']['foreign_unique'] == $field) {
01598                 $uniqueIds = $this->inline->inlineData['unique'][$this->inline->inlineNames['object'] . '[' . $table . ']']['used'];
01599                 $PA['fieldChangeFunc']['inlineUnique'] = "inline.updateUnique(this,'" . $this->inline->inlineNames['object'] . '[' . $table . "]','" . $this->inline->inlineNames['form'] . "','" . $row['uid'] . "');";
01600             }
01601                 // hide uid of parent record for symmetric relations
01602             if ($inlineParent['config']['foreign_table'] == $table && ($inlineParent['config']['foreign_field'] == $field || $inlineParent['config']['symmetric_field'] == $field)) {
01603                 $uniqueIds[] = $inlineParent['uid'];
01604             }
01605         }
01606 
01607             // Initialization:
01608         $c = 0;
01609         $sI = 0;
01610         $noMatchingValue = 1;
01611         $opt = array();
01612         $selicons = array();
01613         $onlySelectedIconShown = 0;
01614         $size = intval($config['size']);
01615         $selectedStyle = ''; // Style set on <select/>
01616 
01617         $disabled = '';
01618         if ($this->renderReadonly || $config['readOnly']) {
01619             $disabled = ' disabled="disabled"';
01620             $onlySelectedIconShown = 1;
01621         }
01622 
01623             // Icon configuration:
01624         if ($config['suppress_icons'] == 'IF_VALUE_FALSE') {
01625             $suppressIcons = !$PA['itemFormElValue'] ? 1 : 0;
01626         } elseif ($config['suppress_icons'] == 'ONLY_SELECTED') {
01627             $suppressIcons = 0;
01628             $onlySelectedIconShown = 1;
01629         } elseif ($config['suppress_icons']) {
01630             $suppressIcons = 1;
01631         } else {
01632             $suppressIcons = 0;
01633         }
01634 
01635             // Traverse the Array of selector box items:
01636         $optGroupStart = array();
01637         $optGroupOpen = FALSE;
01638         $classesForSelectTag = array();
01639         foreach ($selItems as $p) {
01640             $sM = (!strcmp($PA['itemFormElValue'], $p[1]) ? ' selected="selected"' : '');
01641             if ($sM) {
01642                 $sI = $c;
01643                 $noMatchingValue = 0;
01644             }
01645 
01646                 // Getting style attribute value (for icons):
01647             if ($config['iconsInOptionTags']) {
01648                 $styleAttrValue = $this->optionTagStyle($p[2]);
01649                 if ($sM) {
01650                     list($selectIconFile, $selectIconInfo) = $this->getIcon($p[2]);
01651                     if (!empty($selectIconInfo)) {
01652                         $selectedStyle = ' style="background-image:url(' . $selectIconFile . ');"';
01653                         $classesForSelectTag[] = 'typo3-TCEforms-select-selectedItemWithBackgroundImage';
01654                     }
01655                 }
01656             }
01657 
01658                 // Compiling the <option> tag:
01659             if (!($p[1] != $PA['itemFormElValue'] && is_array($uniqueIds) && in_array($p[1], $uniqueIds))) {
01660                 if (!strcmp($p[1], '--div--')) {
01661                     $optGroupStart[0] = $p[0];
01662                     if ($config['iconsInOptionTags']) {
01663                         $optGroupStart[1] = $this->optgroupTagStyle($p[2]);
01664                     } else {
01665                         $optGroupStart[1] = $styleAttrValue;
01666                     }
01667 
01668                 } else {
01669                     if (count($optGroupStart)) {
01670                         if ($optGroupOpen) { // Closing last optgroup before next one starts
01671                             $opt[] = '</optgroup>' . LF;
01672                         }
01673                         $opt[] = '<optgroup label="' . t3lib_div::deHSCentities(htmlspecialchars($optGroupStart[0])) . '"' .
01674                                  ($optGroupStart[1] ? ' style="' . htmlspecialchars($optGroupStart[1]) . '"' : '') .
01675                                  ' class="c-divider">' . LF;
01676                         $optGroupOpen = TRUE;
01677                         $c--;
01678                         $optGroupStart = array();
01679                     }
01680                     $opt[] = '<option value="' . htmlspecialchars($p[1]) . '"' .
01681                              $sM .
01682                              ($styleAttrValue ? ' style="' . htmlspecialchars($styleAttrValue) . '"' : '') .
01683                              '>' . t3lib_div::deHSCentities(($p[0])) . '</option>' . LF;
01684                 }
01685             }
01686 
01687                 // If there is an icon for the selector box (rendered in selicon-table below)...:
01688                 // if there is an icon ($p[2]), icons should be shown, and, if only selected are visible, is it selected
01689             if ($p[2] && !$suppressIcons && (!$onlySelectedIconShown || $sM)) {
01690                 list($selIconFile, $selIconInfo) = $this->getIcon($p[2]);
01691                 if (!empty($selIconInfo)) {
01692                     $iOnClick = $this->elName($PA['itemFormElName']) . '.selectedIndex=' . $c . '; ' .
01693                         $this->elName($PA['itemFormElName']) . '.style.backgroundImage=' . $this->elName($PA['itemFormElName']) . '.options[' . $c . '].style.backgroundImage; ' .
01694                         implode('', $PA['fieldChangeFunc']) . $this->blur() . 'return false;';
01695                 } else {
01696                     $iOnClick = $this->elName($PA['itemFormElName']) . '.selectedIndex=' . $c . '; ' .
01697                         $this->elName($PA['itemFormElName']) . '.className=' . $this->elName($PA['itemFormElName']) . '.options[' . $c . '].className; ' .
01698                         implode('', $PA['fieldChangeFunc']) . $this->blur() . 'return false;';
01699                 }
01700                 $selicons[] = array(
01701                     (!$onlySelectedIconShown ? '<a href="#" onclick="' . htmlspecialchars($iOnClick) . '">' : '') .
01702                     $this->getIconHtml($p[2], htmlspecialchars($p[0]), htmlspecialchars($p[0])) .
01703                     (!$onlySelectedIconShown ? '</a>' : ''),
01704                     $c, $sM);
01705             }
01706             $c++;
01707         }
01708 
01709         if ($optGroupOpen) { // Closing optgroup if open
01710             $opt[] = '</optgroup>';
01711             $optGroupOpen = false;
01712         }
01713 
01714             // No-matching-value:
01715         if ($PA['itemFormElValue'] && $noMatchingValue && !$PA['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
01716             $nMV_label = @sprintf($nMV_label, $PA['itemFormElValue']);
01717             $opt[] = '<option value="' . htmlspecialchars($PA['itemFormElValue']) . '" selected="selected">' . htmlspecialchars($nMV_label) . '</option>';
01718         }
01719 
01720             // Create item form fields:
01721         $sOnChange = 'if (this.options[this.selectedIndex].value==\'--div--\') {this.selectedIndex=' . $sI . ';} ' . implode('', $PA['fieldChangeFunc']);
01722         if (!$disabled) {
01723             $item .= '<input type="hidden" name="' . $PA['itemFormElName'] . '_selIconVal" value="' . htmlspecialchars($sI) . '" />'; // MUST be inserted before the selector - else is the value of the hiddenfield here mysteriously submitted...
01724         }
01725         if ($config['iconsInOptionTags']) {
01726             $classesForSelectTag[] = 'icon-select';
01727         }
01728         $item .= '<select' . $selectedStyle . ' id="' . uniqid('tceforms-select-') . '" name="' . $PA['itemFormElName'] . '"' .
01729                  $this->insertDefStyle('select', implode(' ', $classesForSelectTag)) .
01730                  ($size ? ' size="' . $size . '"' : '') .
01731                  ' onchange="' . htmlspecialchars($onChangeIcon . $sOnChange) . '"' .
01732                  $PA['onFocus'] . $disabled . '>';
01733         $item .= implode('', $opt);
01734         $item .= '</select>';
01735 
01736             // Create icon table:
01737         if (count($selicons) && !$config['noIconsBelowSelect']) {
01738             $item .= '<table border="0" cellpadding="0" cellspacing="0" class="typo3-TCEforms-selectIcons">';
01739             $selicon_cols = intval($config['selicon_cols']);
01740             if (!$selicon_cols) {
01741                 $selicon_cols = count($selicons);
01742             }
01743             $sR = ceil(count($selicons) / $selicon_cols);
01744             $selicons = array_pad($selicons, $sR * $selicon_cols, '');
01745             for ($sa = 0; $sa < $sR; $sa++) {
01746                 $item .= '<tr>';
01747                 for ($sb = 0; $sb < $selicon_cols; $sb++) {
01748                     $sk = ($sa * $selicon_cols + $sb);
01749                     $imgN = 'selIcon_' . $table . '_' . $row['uid'] . '_' . $field . '_' . $selicons[$sk][1];
01750                     $imgS = ($selicons[$sk][2] ? $this->backPath . 'gfx/content_selected.gif' : 'clear.gif');
01751                     $item .= '<td><img name="' . htmlspecialchars($imgN) . '" src="' . $imgS . '" width="7" height="10" alt="" /></td>';
01752                     $item .= '<td>' . $selicons[$sk][0] . '</td>';
01753                 }
01754                 $item .= '</tr>';
01755             }
01756             $item .= '</table>';
01757         }
01758 
01759         return $item;
01760     }
01761 
01762     /**
01763      * Creates a checkbox list (renderMode = "checkbox")
01764      * (Render function for getSingleField_typeSelect())
01765      *
01766      * @param   string      See getSingleField_typeSelect()
01767      * @param   string      See getSingleField_typeSelect()
01768      * @param   array       See getSingleField_typeSelect()
01769      * @param   array       See getSingleField_typeSelect()
01770      * @param   array       (Redundant) content of $PA['fieldConf']['config'] (for convenience)
01771      * @param   array       Items available for selection
01772      * @param   string      Label for no-matching-value
01773      * @return  string      The HTML code for the item
01774      * @see getSingleField_typeSelect()
01775      */
01776     function getSingleField_typeSelect_checkbox(
01777         $table, $field, $row, &$PA, $config, $selItems, $nMV_label) {
01778 
01779         if (empty($selItems)) {
01780             return '';
01781         }
01782 
01783             // Get values in an array (and make unique, which is fine because there can be no duplicates anyway):
01784         $itemArray = array_flip($this->extractValuesOnlyFromValueLabelList($PA['itemFormElValue']));
01785 
01786         $disabled = '';
01787         if ($this->renderReadonly || $config['readOnly']) {
01788             $disabled = ' disabled="disabled"';
01789         }
01790 
01791             // Traverse the Array of selector box items:
01792         $tRows = array();
01793         $c = 0;
01794         if (!$disabled) {
01795             $sOnChange = implode('', $PA['fieldChangeFunc']);
01796             $setAll = array(); // Used to accumulate the JS needed to restore the original selection.
01797             $unSetAll = array();
01798             foreach ($selItems as $p) {
01799                     // Non-selectable element:
01800                 if (!strcmp($p[1], '--div--')) {
01801                     $tRows[] = '
01802                         <tr class="c-header">
01803                             <td colspan="3">' . htmlspecialchars($p[0]) . '</td>
01804                         </tr>';
01805                 } else {
01806                         // Selected or not by default:
01807                     $sM = '';
01808                     if (isset($itemArray[$p[1]])) {
01809                         $sM = ' checked="checked"';
01810                         unset($itemArray[$p[1]]);
01811                     }
01812 
01813                         // Icon:
01814                     if ($p[2]) {
01815                         $selIcon = $p[2];
01816                     } else {
01817                         $selIcon = t3lib_iconWorks::getSpriteIcon('empty-empty');
01818                     }
01819 
01820                         // Compile row:
01821                     $rowId = uniqid('select_checkbox_row_');
01822                     $onClickCell = $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked=!' . $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked;';
01823                     $onClick = 'this.attributes.getNamedItem("class").nodeValue = ' . $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked ? "c-selectedItem" : "c-unselectedItem";';
01824                     $setAll[] = $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked=1;';
01825                     $setAll[] .= '$(\'' . $rowId . '\').removeClassName(\'c-unselectedItem\');$(\'' . $rowId . '\').addClassName(\'c-selectedItem\');';
01826                     $unSetAll[] = $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked=0;';
01827                     $unSetAll[] .= '$(\'' . $rowId . '\').removeClassName(\'c-selectedItem\');$(\'' . $rowId . '\').addClassName(\'c-unselectedItem\');';
01828                     $restoreCmd[] = $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked=' . ($sM ? 1 : 0) . ';' .
01829                                     '$(\'' . $rowId . '\').removeClassName(\'c-selectedItem\');$(\'' . $rowId . '\').removeClassName(\'c-unselectedItem\');' .
01830                                     '$(\'' . $rowId . '\').addClassName(\'c-' . ($sM ? '' : 'un') . 'selectedItem\');';
01831 
01832                         // Check if some help text is available
01833                         // Since TYPO3 4.5 help text is expected to be an associative array
01834                         // with two key, "title" and "description"
01835                         // For the sake of backwards compatibility, we test if the help text
01836                         // is a string and use it as a description (this could happen if items
01837                         // are modified with an itemProcFunc)
01838                     $hasHelp = FALSE;
01839                     $help = '';
01840                     $helpArray = array();
01841                     if ((is_array($p[3]) && count($p[3]) > 0) || !empty($p[3])) {
01842                         $hasHelp = TRUE;
01843                         if (is_array($p[3])) {
01844                             $helpArray = $p[3];
01845                         } else {
01846                             $helpArray['description'] = $p[3];
01847                         }
01848                     }
01849 
01850                     $label = t3lib_div::deHSCentities(htmlspecialchars($p[0]));
01851                     if ($hasHelp) {
01852                         $help = t3lib_BEfunc::wrapInHelp('', '', '', $helpArray);
01853                     }
01854 
01855                     $tRows[] = '
01856                         <tr id="' . $rowId . '" class="' . ($sM ? 'c-selectedItem' : 'c-unselectedItem') . '" onclick="' . htmlspecialchars($onClick) . '" style="cursor: pointer;">
01857                             <td class="c-checkbox"><input type="checkbox"' . $this->insertDefStyle('check') . ' name="' . htmlspecialchars($PA['itemFormElName'] . '[' . $c . ']') . '" value="' . htmlspecialchars($p[1]) . '"' . $sM . ' onclick="' . htmlspecialchars($sOnChange) . '"' . $PA['onFocus'] . ' /></td>
01858                             <td class="c-labelCell" onclick="' . htmlspecialchars($onClickCell) . '">' .
01859                                $this->getIconHtml($selIcon) .
01860                                $label .
01861                                '</td>
01862                                 <td class="c-descr" onclick="' . htmlspecialchars($onClickCell) . '">' . ((empty($help)) ? '' : $help) . '</td>
01863                         </tr>';
01864                     $c++;
01865                 }
01866             }
01867         }
01868 
01869             // Remaining values (invalid):
01870         if (count($itemArray) && !$PA['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
01871             foreach ($itemArray as $theNoMatchValue => $temp) {
01872                     // Compile <checkboxes> tag:
01873                 array_unshift($tRows, '
01874                         <tr class="c-invalidItem">
01875                             <td class="c-checkbox"><input type="checkbox"' . $this->insertDefStyle('check') . ' name="' . htmlspecialchars($PA['itemFormElName'] . '[' . $c . ']') . '" value="' . htmlspecialchars($theNoMatchValue) . '" checked="checked" onclick="' . htmlspecialchars($sOnChange) . '"' . $PA['onFocus'] . $disabled . ' /></td>
01876                             <td class="c-labelCell">' .
01877                                       t3lib_div::deHSCentities(htmlspecialchars(@sprintf($nMV_label, $theNoMatchValue))) .
01878                                       '</td><td>&nbsp;</td>
01879                         </tr>');
01880                 $c++;
01881             }
01882         }
01883 
01884             // Add an empty hidden field which will send a blank value if all items are unselected.
01885         $item .= '<input type="hidden" name="' . htmlspecialchars($PA['itemFormElName']) . '" value="" />';
01886 
01887             // Remaining checkboxes will get their set-all link:
01888         if (count($setAll)) {
01889             $tableHead = '<thead>
01890                     <tr class="c-header-checkbox-controls t3-row-header">
01891                         <td class="c-checkbox">
01892                         <input type="checkbox" class="checkbox" onclick="if (checked) {' . htmlspecialchars(implode('', $setAll) . '} else {' .  implode('', $unSetAll) . '}') . '">
01893                         </td>
01894                         <td colspan="2">
01895                         </td>
01896                     </tr></thead>';
01897         }
01898             // Implode rows in table:
01899         $item .= '
01900             <table border="0" cellpadding="0" cellspacing="0" class="typo3-TCEforms-select-checkbox">' .
01901                 $tableHead .
01902                 '<tbody>' . implode('', $tRows) . '</tbody>
01903             </table>
01904             ';
01905 
01906             // Add revert icon
01907         if (is_array($restoreCmd)) {
01908             $item .= '<a href="#" onclick="' . implode('', $restoreCmd) . ' return false;' . '">' .
01909                      t3lib_iconWorks::getSpriteIcon('actions-edit-undo', array('title' => htmlspecialchars($this->getLL('l_revertSelection')))) . '</a>';
01910         }
01911 
01912         return $item;
01913     }
01914 
01915     /**
01916      * Creates a selectorbox list (renderMode = "singlebox")
01917      * (Render function for getSingleField_typeSelect())
01918      *
01919      * @param   string      See getSingleField_typeSelect()
01920      * @param   string      See getSingleField_typeSelect()
01921      * @param   array       See getSingleField_typeSelect()
01922      * @param   array       See getSingleField_typeSelect()
01923      * @param   array       (Redundant) content of $PA['fieldConf']['config'] (for convenience)
01924      * @param   array       Items available for selection
01925      * @param   string      Label for no-matching-value
01926      * @return  string      The HTML code for the item
01927      * @see getSingleField_typeSelect()
01928      */
01929     function getSingleField_typeSelect_singlebox($table, $field, $row, &$PA, $config, $selItems, $nMV_label) {
01930 
01931             // Get values in an array (and make unique, which is fine because there can be no duplicates anyway):
01932         $itemArray = array_flip($this->extractValuesOnlyFromValueLabelList($PA['itemFormElValue']));
01933 
01934         $disabled = '';
01935         if ($this->renderReadonly || $config['readOnly']) {
01936             $disabled = ' disabled="disabled"';
01937         }
01938 
01939             // Traverse the Array of selector box items:
01940         $opt = array();
01941         $restoreCmd = array(); // Used to accumulate the JS needed to restore the original selection.
01942         $c = 0;
01943         foreach ($selItems as $p) {
01944                 // Selected or not by default:
01945             $sM = '';
01946             if (isset($itemArray[$p[1]])) {
01947                 $sM = ' selected="selected"';
01948                 $restoreCmd[] = $this->elName($PA['itemFormElName'] . '[]') . '.options[' . $c . '].selected=1;';
01949                 unset($itemArray[$p[1]]);
01950             }
01951 
01952                 // Non-selectable element:
01953             $nonSel = '';
01954             if (!strcmp($p[1], '--div--')) {
01955                 $nonSel = ' onclick="this.selected=0;" class="c-divider"';
01956             }
01957 
01958                 // Icon style for option tag:
01959             if ($config['iconsInOptionTags']) {
01960                 $styleAttrValue = $this->optionTagStyle($p[2]);
01961             }
01962 
01963                 // Compile <option> tag:
01964             $opt[] = '<option value="' . htmlspecialchars($p[1]) . '"' .
01965                      $sM .
01966                      $nonSel .
01967                      ($styleAttrValue ? ' style="' . htmlspecialchars($styleAttrValue) . '"' : '') .
01968                      '>' . t3lib_div::deHSCentities(htmlspecialchars($p[0])) . '</option>';
01969             $c++;
01970         }
01971 
01972             // Remaining values:
01973         if (count($itemArray) && !$PA['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
01974             foreach ($itemArray as $theNoMatchValue => $temp) {
01975                     // Compile <option> tag:
01976                 array_unshift($opt, '<option value="' . htmlspecialchars($theNoMatchValue) . '" selected="selected">' . t3lib_div::deHSCentities(htmlspecialchars(@sprintf($nMV_label, $theNoMatchValue))) . '</option>');
01977             }
01978         }
01979 
01980             // Compile selector box:
01981         $sOnChange = implode('', $PA['fieldChangeFunc']);
01982         $selector_itemListStyle = isset($config['itemListStyle']) ? ' style="' . htmlspecialchars($config['itemListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"';
01983         $size = intval($config['size']);
01984         $cssPrefix = ($size === 1) ? 'tceforms-select' : 'tceforms-multiselect';
01985         $size = $config['autoSizeMax'] ? t3lib_div::intInRange(count($selItems) + 1, t3lib_div::intInRange($size, 1), $config['autoSizeMax']) : $size;
01986         $selectBox = '<select id="' . uniqid($cssPrefix) . '" name="' . $PA['itemFormElName'] . '[]"' .
01987                      $this->insertDefStyle('select', $cssPrefix) .
01988                      ($size ? ' size="' . $size . '"' : '') .
01989                      ' multiple="multiple" onchange="' . htmlspecialchars($sOnChange) . '"' .
01990                      $PA['onFocus'] .
01991                      $selector_itemListStyle .
01992                      $disabled . '>
01993                         ' .
01994                      implode('
01995                         ', $opt) . '
01996                     </select>';
01997 
01998             // Add an empty hidden field which will send a blank value if all items are unselected.
01999         if (!$disabled) {
02000             $item .= '<input type="hidden" name="' . htmlspecialchars($PA['itemFormElName']) . '" value="" />';
02001         }
02002 
02003             // Put it all into a table:
02004         $item .= '
02005             <table border="0" cellspacing="0" cellpadding="0" width="1" class="typo3-TCEforms-select-singlebox">
02006                 <tr>
02007                     <td>
02008                     ' . $selectBox . '
02009                     <br/>
02010                     <em>' .
02011                  htmlspecialchars($this->getLL('l_holdDownCTRL')) .
02012                  '</em>
02013                     </td>
02014                     <td valign="top">
02015                       <a href="#" onclick="' . htmlspecialchars($this->elName($PA['itemFormElName'] . '[]') . '.selectedIndex=-1;' . implode('', $restoreCmd) . ' return false;') . '" title="' . htmlspecialchars($this->getLL('l_revertSelection')) . '">' .
02016                  t3lib_iconWorks::getSpriteIcon('actions-edit-undo') .
02017                  '</a>
02018                     </td>
02019                 </tr>
02020             </table>
02021                 ';
02022 
02023         return $item;
02024     }
02025 
02026     /**
02027      * Creates a multiple-selector box (two boxes, side-by-side)
02028      * (Render function for getSingleField_typeSelect())
02029      *
02030      * @param   string      See getSingleField_typeSelect()
02031      * @param   string      See getSingleField_typeSelect()
02032      * @param   array       See getSingleField_typeSelect()
02033      * @param   array       See getSingleField_typeSelect()
02034      * @param   array       (Redundant) content of $PA['fieldConf']['config'] (for convenience)
02035      * @param   array       Items available for selection
02036      * @param   string      Label for no-matching-value
02037      * @return  string      The HTML code for the item
02038      * @see getSingleField_typeSelect()
02039      */
02040     function getSingleField_typeSelect_multiple($table, $field, $row, &$PA, $config, $selItems, $nMV_label) {
02041 
02042         $disabled = '';
02043         if ($this->renderReadonly || $config['readOnly']) {
02044             $disabled = ' disabled="disabled"';
02045         }
02046 
02047             // Setting this hidden field (as a flag that JavaScript can read out)
02048         if (!$disabled) {
02049             $item .= '<input type="hidden" name="' . $PA['itemFormElName'] . '_mul" value="' . ($config['multiple'] ? 1 : 0) . '" />';
02050         }
02051 
02052             // Set max and min items:
02053         $maxitems = t3lib_div::intInRange($config['maxitems'], 0);
02054         if (!$maxitems) {
02055             $maxitems = 100000;
02056         }
02057         $minitems = t3lib_div::intInRange($config['minitems'], 0);
02058 
02059             // Register the required number of elements:
02060         $this->registerRequiredProperty('range', $PA['itemFormElName'], array($minitems, $maxitems, 'imgName' => $table . '_' . $row['uid'] . '_' . $field));
02061 
02062             // Get "removeItems":
02063         $removeItems = t3lib_div::trimExplode(',', $PA['fieldTSConfig']['removeItems'], 1);
02064 
02065             // Get the array with selected items:
02066         $itemArray = t3lib_div::trimExplode(',', $PA['itemFormElValue'], 1);
02067 
02068             // Possibly filter some items:
02069         $keepItemsFunc = create_function('$value', '$parts=explode(\'|\',$value,2); return rawurldecode($parts[0]);');
02070         $itemArray = t3lib_div::keepItemsInArray($itemArray, $PA['fieldTSConfig']['keepItems'], $keepItemsFunc);
02071 
02072             // Perform modification of the selected items array:
02073         foreach ($itemArray as $tk => $tv) {
02074             $tvP = explode('|', $tv, 2);
02075             $evalValue = $tvP[0];
02076             $isRemoved = in_array($evalValue, $removeItems) || ($config['form_type'] == 'select' && $config['authMode'] && !$GLOBALS['BE_USER']->checkAuthMode($table, $field, $evalValue, $config['authMode']));
02077             if ($isRemoved && !$PA['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
02078                 $tvP[1] = rawurlencode(@sprintf($nMV_label, $evalValue));
02079             } elseif (isset($PA['fieldTSConfig']['altLabels.'][$evalValue])) {
02080                 $tvP[1] = rawurlencode($this->sL($PA['fieldTSConfig']['altLabels.'][$evalValue]));
02081             }
02082             if ($tvP[1] == '') {
02083                     // Case: flexform, default values supplied, no label provided (bug #9795)
02084                 foreach ($selItems as $selItem) {
02085                     if ($selItem[1] == $tvP[0]) {
02086                         $tvP[1] = html_entity_decode($selItem[0]);
02087                         break;
02088                     }
02089                 }
02090             }
02091             $itemArray[$tk] = implode('|', $tvP);
02092         }
02093         $itemsToSelect = '';
02094 
02095         if (!$disabled) {
02096                 // Create option tags:
02097             $opt = array();
02098             $styleAttrValue = '';
02099             foreach ($selItems as $p) {
02100                 if ($config['iconsInOptionTags']) {
02101                     $styleAttrValue = $this->optionTagStyle($p[2]);
02102                 }
02103                 $opt[] = '<option value="' . htmlspecialchars($p[1]) . '"' .
02104                          ($styleAttrValue ? ' style="' . htmlspecialchars($styleAttrValue) . '"' : '') .
02105                          '>' . $p[0] . '</option>';
02106             }
02107 
02108                 // Put together the selector box:
02109             $selector_itemListStyle = isset($config['itemListStyle']) ? ' style="' . htmlspecialchars($config['itemListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"';
02110             $size = intval($config['size']);
02111             $size = $config['autoSizeMax'] ? t3lib_div::intInRange(count($itemArray) + 1, t3lib_div::intInRange($size, 1), $config['autoSizeMax']) : $size;
02112             if ($config['exclusiveKeys']) {
02113                 $sOnChange = 'setFormValueFromBrowseWin(\'' . $PA['itemFormElName'] . '\',this.options[this.selectedIndex].value,this.options[this.selectedIndex].text,\'' . $config['exclusiveKeys'] . '\'); ';
02114             } else {
02115                 $sOnChange = 'setFormValueFromBrowseWin(\'' . $PA['itemFormElName'] . '\',this.options[this.selectedIndex].value,this.options[this.selectedIndex].text); ';
02116             }
02117             $sOnChange .= implode('', $PA['fieldChangeFunc']);
02118             $itemsToSelect = '
02119                 <select id="' . uniqid('tceforms-multiselect-') . '" name="' . $PA['itemFormElName'] . '_sel"' .
02120                              $this->insertDefStyle('select', 'tceforms-multiselect tceforms-itemstoselect') .
02121                              ($size ? ' size="' . $size . '"' : '') .
02122                              ' onchange="' . htmlspecialchars($sOnChange) . '"' .
02123                              $PA['onFocus'] .
02124                              $selector_itemListStyle . '>
02125                     ' . implode('
02126                     ', $opt) . '
02127                 </select>';
02128         }
02129 
02130             // Pass to "dbFileIcons" function:
02131         $params = array(
02132             'size' => $size,
02133             'autoSizeMax' => t3lib_div::intInRange($config['autoSizeMax'], 0),
02134             'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"',
02135             'dontShowMoveIcons' => ($maxitems <= 1),
02136             'maxitems' => $maxitems,
02137             'info' => '',
02138             'headers' => array(
02139                 'selector' => $this->getLL('l_selected') . ':<br />',
02140                 'items' => $this->getLL('l_items') . ':<br />'
02141             ),
02142             'noBrowser' => 1,
02143             'thumbnails' => $itemsToSelect,
02144             'readOnly' => $disabled
02145         );
02146         $item .= $this->dbFileIcons($PA['itemFormElName'], '', '', $itemArray, '', $params, $PA['onFocus']);
02147 
02148         return $item;
02149     }
02150 
02151     /**
02152      * Generation of TCEform elements of the type "group"
02153      * This will render a selectorbox into which elements from either the file system or database can be inserted. Relations.
02154      *
02155      * @param   string      The table name of the record
02156      * @param   string      The field name which this element is supposed to edit
02157      * @param   array       The record data array where the value(s) for the field can be found
02158      * @param   array       An array with additional configuration options.
02159      * @return  string      The HTML code for the TCEform field
02160      */
02161     function getSingleField_typeGroup($table, $field, $row, &$PA) {
02162             // Init:
02163         $config = $PA['fieldConf']['config'];
02164         $internal_type = $config['internal_type'];
02165         $show_thumbs = $config['show_thumbs'];
02166         $size = intval($config['size']);
02167         $maxitems = t3lib_div::intInRange($config['maxitems'], 0);
02168         if (!$maxitems) {
02169             $maxitems = 100000;
02170         }
02171         $minitems = t3lib_div::intInRange($config['minitems'], 0);
02172         $allowed = trim($config['allowed']);
02173         $disallowed = trim($config['disallowed']);
02174 
02175         $disabled = '';
02176         if ($this->renderReadonly || $config['readOnly']) {
02177             $disabled = ' disabled="disabled"';
02178         }
02179 
02180         $item .= '<input type="hidden" name="' . $PA['itemFormElName'] . '_mul" value="' . ($config['multiple'] ? 1 : 0) . '"' . $disabled . ' />';
02181         $this->registerRequiredProperty('range', $PA['itemFormElName'], array($minitems, $maxitems, 'imgName' => $table . '_' . $row['uid'] . '_' . $field));
02182         $info = '';
02183 
02184             // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. See http://typo3.org/documentation/document-library/doc_core_api/Wizards_Configuratio/.
02185         $specConf = $this->getSpecConfFromString($PA['extra'], $PA['fieldConf']['defaultExtras']);
02186 
02187             // Acting according to either "file" or "db" type:
02188         switch ((string) $config['internal_type']) {
02189             case 'file_reference':
02190                 $config['uploadfolder'] = '';
02191                 // Fall through
02192             case 'file': // If the element is of the internal type "file":
02193 
02194                     // Creating string showing allowed types:
02195                 $tempFT = t3lib_div::trimExplode(',', $allowed, 1);
02196                 if (!count($tempFT)) {
02197                     $info .= '*';
02198                 }
02199                 foreach ($tempFT as $ext) {
02200                     if ($ext) {
02201                         $info .= strtoupper($ext) . ' ';
02202                     }
02203                 }
02204                     // Creating string, showing disallowed types:
02205                 $tempFT_dis = t3lib_div::trimExplode(',', $disallowed, 1);
02206                 if (count($tempFT_dis)) {
02207                     $info .= '<br />';
02208                 }
02209                 foreach ($tempFT_dis as $ext) {
02210                     if ($ext) {
02211                         $info .= '-' . strtoupper($ext) . ' ';
02212                     }
02213                 }
02214 
02215                     // Making the array of file items:
02216                 $itemArray = t3lib_div::trimExplode(',', $PA['itemFormElValue'], 1);
02217 
02218                     // Showing thumbnails:
02219                 $thumbsnail = '';
02220                 if ($show_thumbs) {
02221                     $imgs = array();
02222                     foreach ($itemArray as $imgRead) {
02223                         $imgP = explode('|', $imgRead);
02224                         $imgPath = rawurldecode($imgP[0]);
02225 
02226                         $rowCopy = array();
02227                         $rowCopy[$field] = $imgPath;
02228 
02229                         $imgs[] = '<span class="nobr">' . t3lib_BEfunc::thumbCode($rowCopy, $table, $field, $this->backPath, 'thumbs.php', $config['uploadfolder'], 0, ' align="middle"') .
02230                                   $imgPath .
02231                                   '</span>';
02232                     }
02233                     $thumbsnail = implode('<br />', $imgs);
02234                 }
02235 
02236                     // Creating the element:
02237                 $noList = isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'list');
02238                 $params = array(
02239                     'size' => $size,
02240                     'dontShowMoveIcons' => ($maxitems <= 1),
02241                     'autoSizeMax' => t3lib_div::intInRange($config['autoSizeMax'], 0),
02242                     'maxitems' => $maxitems,
02243                     'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"',
02244                     'info' => $info,
02245                     'thumbnails' => $thumbsnail,
02246                     'readOnly' => $disabled,
02247                     'noBrowser' => $noList || (isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'browser')),
02248                     'noList' => $noList,
02249                 );
02250                 $item .= $this->dbFileIcons($PA['itemFormElName'], 'file', implode(',', $tempFT), $itemArray, '', $params, $PA['onFocus']);
02251 
02252                 if (!$disabled && !(isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'upload'))) {
02253                         // Adding the upload field:
02254                     if ($this->edit_docModuleUpload && $config['uploadfolder']) {
02255                         $item .= '<input type="file" name="' . $PA['itemFormElName_file'] . '" size="35" onchange="' . implode('', $PA['fieldChangeFunc']) . '" />';
02256                     }
02257                 }
02258             break;
02259             case 'folder': // If the element is of the internal type "folder":
02260 
02261                     // array of folder items:
02262                 $itemArray = t3lib_div::trimExplode(',', $PA['itemFormElValue'], 1);
02263 
02264                     // Creating the element:
02265                 $noList = isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'list');
02266                 $params = array(
02267                     'size' => $size,
02268                     'dontShowMoveIcons' => ($maxitems <= 1),
02269                     'autoSizeMax' => t3lib_div::intInRange($config['autoSizeMax'], 0),
02270                     'maxitems' => $maxitems,
02271                     'style' => isset($config['selectedListStyle']) ?
02272                             ' style="' . htmlspecialchars($config['selectedListStyle']) . '"'
02273                             : ' style="' . $this->defaultMultipleSelectorStyle . '"',
02274                     'info' => $info,
02275                     'readOnly' => $disabled,
02276                     'noBrowser' => $noList || (isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'browser')),
02277                     'noList' => $noList,
02278                 );
02279 
02280                 $item .= $this->dbFileIcons(
02281                     $PA['itemFormElName'],
02282                     'folder',
02283                     '',
02284                     $itemArray,
02285                     '',
02286                     $params,
02287                     $PA['onFocus']
02288                 );
02289             break;
02290             case 'db': // If the element is of the internal type "db":
02291 
02292                     // Creating string showing allowed types:
02293                 $tempFT = t3lib_div::trimExplode(',', $allowed, TRUE);
02294                 if (!strcmp(trim($tempFT[0]), '*')) {
02295                     $onlySingleTableAllowed = false;
02296                     $info .= '<span class="nobr">' .
02297                              htmlspecialchars($this->getLL('l_allTables')) .
02298                              '</span><br />';
02299                 } elseif ($tempFT) {
02300                     $onlySingleTableAllowed = (count($tempFT) == 1);
02301                     foreach ($tempFT as $theT) {
02302                         $info .= '<span class="nobr">' .
02303                                  t3lib_iconWorks::getSpriteIconForRecord($theT, array()) .
02304                                  htmlspecialchars($this->sL($GLOBALS['TCA'][$theT]['ctrl']['title'])) .
02305                                  '</span><br />';
02306                     }
02307                 }
02308 
02309                 $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
02310                 $itemArray = array();
02311                 $imgs = array();
02312 
02313                     // Thumbnails:
02314                 $temp_itemArray = t3lib_div::trimExplode(',', $PA['itemFormElValue'], 1);
02315                 foreach ($temp_itemArray as $dbRead) {
02316                     $recordParts = explode('|', $dbRead);
02317                     list($this_table, $this_uid) = t3lib_BEfunc::splitTable_Uid($recordParts[0]);
02318                         // For the case that no table was found and only a single table is defined to be allowed, use that one:
02319                     if (!$this_table && $onlySingleTableAllowed) {
02320                         $this_table = $allowed;
02321                     }
02322                     $itemArray[] = array('table' => $this_table, 'id' => $this_uid);
02323                     if (!$disabled && $show_thumbs) {
02324                         $rr = t3lib_BEfunc::getRecordWSOL($this_table, $this_uid);
02325                         $imgs[] = '<span class="nobr">' .
02326                                   $this->getClickMenu(
02327                                       t3lib_iconWorks::getSpriteIconForRecord(
02328                                           $this_table,
02329                                           $rr,
02330                                           array(
02331                                                'style' => 'vertical-align:top',
02332                                                'title' => htmlspecialchars(t3lib_BEfunc::getRecordPath($rr['pid'], $perms_clause, 15) . ' [UID: ' . $rr['uid'] . ']')
02333                                           )
02334                                       ),
02335                                       $this_table,
02336                                       $this_uid
02337                                   ) .
02338                                   '&nbsp;' .
02339                                   t3lib_BEfunc::getRecordTitle($this_table, $rr, TRUE) . ' <span class="typo3-dimmed"><em>[' . $rr['uid'] . ']</em></span>' .
02340                                   '</span>';
02341                     }
02342                 }
02343                 $thumbsnail = '';
02344                 if (!$disabled && $show_thumbs) {
02345                     $thumbsnail = implode('<br />', $imgs);
02346                 }
02347 
02348                     // Creating the element:
02349                 $noList = isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'list');
02350                 $params = array(
02351                     'size' => $size,
02352                     'dontShowMoveIcons' => ($maxitems <= 1),
02353                     'autoSizeMax' => t3lib_div::intInRange($config['autoSizeMax'], 0),
02354                     'maxitems' => $maxitems,
02355                     'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"',
02356                     'info' => $info,
02357                     'thumbnails' => $thumbsnail,
02358                     'readOnly' => $disabled,
02359                     'noBrowser' => $noList || (isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'browser')),
02360                     'noList' => $noList,
02361                 );
02362                 $item .= $this->dbFileIcons($PA['itemFormElName'], 'db', implode(',', $tempFT), $itemArray, '', $params, $PA['onFocus'], $table, $field, $row['uid']);
02363 
02364             break;
02365         }
02366 
02367             // Wizards:
02368         $altItem = '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
02369         if (!$disabled) {
02370             $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'], $specConf);
02371         }
02372 
02373         return $item;
02374     }
02375 
02376     /**
02377      * Generation of TCEform elements of the type "none"
02378      * This will render a non-editable display of the content of the field.
02379      *
02380      * @param   string      The table name of the record
02381      * @param   string      The field name which this element is supposed to edit
02382      * @param   array       The record data array where the value(s) for the field can be found
02383      * @param   array       An array with additional configuration options.
02384      * @return  string      The HTML code for the TCEform field
02385      */
02386     function getSingleField_typeNone($table, $field, $row, &$PA) {
02387             // Init:
02388         $config = $PA['fieldConf']['config'];
02389         $itemValue = $PA['itemFormElValue'];
02390 
02391         return $this->getSingleField_typeNone_render($config, $itemValue);
02392     }
02393 
02394     /**
02395      * HTML rendering of a value which is not editable.
02396      *
02397      * @param   array       Configuration for the display
02398      * @param   string      The value to display
02399      * @return  string      The HTML code for the display
02400      * @see getSingleField_typeNone();
02401      */
02402     function getSingleField_typeNone_render($config, $itemValue) {
02403 
02404             // is colorScheme[0] the right value?
02405         $divStyle = 'border:solid 1px ' . t3lib_div::modifyHTMLColorAll($this->colorScheme[0], -30) . ';' . $this->defStyle . $this->formElStyle('none') . ' background-color: ' . $this->colorScheme[0] . '; padding-left:1px;color:#555;';
02406 
02407         if ($config['format']) {
02408             $itemValue = $this->formatValue($config, $itemValue);
02409         }
02410 
02411         $rows = intval($config['rows']);
02412         if ($rows > 1) {
02413             if (!$config['pass_content']) {
02414                 $itemValue = nl2br(htmlspecialchars($itemValue));
02415             }
02416                 // like textarea
02417             $cols = t3lib_div::intInRange($config['cols'] ? $config['cols'] : 30, 5, $this->maxTextareaWidth);
02418             if (!$config['fixedRows']) {
02419                 $origRows = $rows = t3lib_div::intInRange($rows, 1, 20);
02420                 if (strlen($itemValue) > $this->charsPerRow * 2) {
02421                     $cols = $this->maxTextareaWidth;
02422                     $rows = t3lib_div::intInRange(round(strlen($itemValue) / $this->charsPerRow), count(explode(LF, $itemValue)), 20);
02423                     if ($rows < $origRows) {
02424                         $rows = $origRows;
02425                     }
02426                 }
02427             }
02428 
02429             if ($this->docLarge) {
02430                 $cols = round($cols * $this->form_largeComp);
02431             }
02432             $width = ceil($cols * $this->form_rowsToStylewidth);
02433                 // hardcoded: 12 is the height of the font
02434             $height = $rows * 12;
02435 
02436             $item = '
02437                 <div style="' . htmlspecialchars($divStyle . ' overflow:auto; height:' . $height . 'px; width:' . $width . 'px;') . '" class="' . htmlspecialchars($this->formElClass('none')) . '">' .
02438                     $itemValue .
02439                     '</div>';
02440         } else {
02441             if (!$config['pass_content']) {
02442                 $itemValue = htmlspecialchars($itemValue);
02443             }
02444 
02445             $cols = $config['cols'] ? $config['cols'] : ($config['size'] ? $config['size'] : $this->maxInputWidth);
02446             if ($this->docLarge) {
02447                 $cols = round($cols * $this->form_largeComp);
02448             }
02449             $width = ceil($cols * $this->form_rowsToStylewidth);
02450 
02451                 // overflow:auto crashes mozilla here. Title tag is usefull when text is longer than the div box (overflow:hidden).
02452             $item = '
02453                 <div style="' . htmlspecialchars($divStyle . ' overflow:hidden; width:' . $width . 'px;') . '" class="' . htmlspecialchars($this->formElClass('none')) . '" title="' . $itemValue . '">' .
02454                     '<span class="nobr">' . (strcmp($itemValue, '') ? $itemValue : '&nbsp;') . '</span>' .
02455                     '</div>';
02456         }
02457 
02458         return $item;
02459     }
02460 
02461     /**
02462      * Handler for Flex Forms
02463      *
02464      * @param   string      The table name of the record
02465      * @param   string      The field name which this element is supposed to edit
02466      * @param   array       The record data array where the value(s) for the field can be found
02467      * @param   array       An array with additional configuration options.
02468      * @return  string      The HTML code for the TCEform field
02469      */
02470     function getSingleField_typeFlex($table, $field, $row, &$PA) {
02471 
02472             // Data Structure:
02473         $dataStructArray = t3lib_BEfunc::getFlexFormDS($PA['fieldConf']['config'], $row, $table);
02474 
02475             // Manipulate Flexform DS via TSConfig and group access lists
02476         if (is_array($dataStructArray)) {
02477             $flexFormHelper = t3lib_div::makeInstance('t3lib_TCEforms_Flexforms');
02478             $dataStructArray = $flexFormHelper->modifyFlexFormDS($dataStructArray, $table, $field, $row, $PA['fieldConf']['config']);
02479             unset($flexFormHelper);
02480         }
02481 
02482             // Get data structure:
02483         if (is_array($dataStructArray)) {
02484 
02485                 // Get data:
02486             $xmlData = $PA['itemFormElValue'];
02487             $xmlHeaderAttributes = t3lib_div::xmlGetHeaderAttribs($xmlData);
02488             $storeInCharset = strtolower($xmlHeaderAttributes['encoding']);
02489             if ($storeInCharset) {
02490                 $currentCharset = $GLOBALS['LANG']->charSet;
02491                 $xmlData = $GLOBALS['LANG']->csConvObj->conv($xmlData, $storeInCharset, $currentCharset, 1);
02492             }
02493             $editData = t3lib_div::xml2array($xmlData);
02494             if (!is_array($editData)) { // Must be XML parsing error...
02495                 $editData = array();
02496             } elseif (!isset($editData['meta']) || !is_array($editData['meta'])) {
02497                 $editData['meta'] = array();
02498             }
02499 
02500                 // Find the data structure if sheets are found:
02501             $sheet = $editData['meta']['currentSheetId'] ? $editData['meta']['currentSheetId'] : 'sDEF'; // Sheet to display
02502 
02503                 // Create sheet menu:
02504                 //TODO; Why is this commented out?
02505             //          if (is_array($dataStructArray['sheets']))   {
02506             //              #$item.=$this->getSingleField_typeFlex_sheetMenu($dataStructArray['sheets'], $PA['itemFormElName'].'[meta][currentSheetId]', $sheet).'<br />';
02507             //          }
02508 
02509                 // Create language menu:
02510             $langChildren = $dataStructArray['meta']['langChildren'] ? 1 : 0;
02511             $langDisabled = $dataStructArray['meta']['langDisable'] ? 1 : 0;
02512 
02513             $editData['meta']['currentLangId'] = array();
02514 
02515                 // Look up page overlays:
02516             $checkPageLanguageOverlay = $GLOBALS['BE_USER']->getTSConfigVal('options.checkPageLanguageOverlay') ? TRUE : FALSE;
02517             if ($checkPageLanguageOverlay) {
02518                 $pageOverlays = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
02519                     '*',
02520                     'pages_language_overlay',
02521                     'pid=' . intval($row['pid']) .
02522                     t3lib_BEfunc::deleteClause('pages_language_overlay') .
02523                     t3lib_BEfunc::versioningPlaceholderClause('pages_language_overlay'),
02524                     '',
02525                     '',
02526                     '',
02527                     'sys_language_uid'
02528                 );
02529             }
02530             $languages = $this->getAvailableLanguages();
02531 
02532             foreach ($languages as $lInfo) {
02533                 if ($GLOBALS['BE_USER']->checkLanguageAccess($lInfo['uid']) && (!$checkPageLanguageOverlay || $lInfo['uid'] <= 0 || is_array($pageOverlays[$lInfo['uid']]))) {
02534                     $editData['meta']['currentLangId'][] = $lInfo['ISOcode'];
02535                 }
02536             }
02537             if (!is_array($editData['meta']['currentLangId']) || !count($editData['meta']['currentLangId'])) {
02538                 $editData['meta']['currentLangId'] = array('DEF');
02539             }
02540 
02541             $editData['meta']['currentLangId'] = array_unique($editData['meta']['currentLangId']);
02542 
02543                 //TODO: Why is this commented out?
02544             //          if (!$langDisabled && count($languages) > 1)    {
02545             //              $item.=$this->getSingleField_typeFlex_langMenu($languages, $PA['itemFormElName'].'[meta][currentLangId]', $editData['meta']['currentLangId']).'<br />';
02546             //          }
02547 
02548             $PA['_noEditDEF'] = FALSE;
02549             if ($langChildren || $langDisabled) {
02550                 $rotateLang = array('DEF');
02551             } else {
02552                 if (!in_array('DEF', $editData['meta']['currentLangId'])) {
02553                     array_unshift($editData['meta']['currentLangId'], 'DEF');
02554                     $PA['_noEditDEF'] = TRUE;
02555                 }
02556                 $rotateLang = $editData['meta']['currentLangId'];
02557             }
02558 
02559                 // Tabs sheets
02560             if (is_array($dataStructArray['sheets'])) {
02561                 $tabsToTraverse = array_keys($dataStructArray['sheets']);
02562             } else {
02563                 $tabsToTraverse = array($sheet);
02564             }
02565 
02566             foreach ($rotateLang as $lKey) {
02567                 if (!$langChildren && !$langDisabled) {
02568                     $item .= '<strong>' . $this->getLanguageIcon($table, $row, 'v' . $lKey) . $lKey . ':</strong>';
02569                 }
02570 
02571                 $tabParts = array();
02572                 foreach ($tabsToTraverse as $sheet) {
02573                     list ($dataStruct, $sheet) = t3lib_div::resolveSheetDefInDS($dataStructArray, $sheet);
02574 
02575                         // Render sheet:
02576                     if (is_array($dataStruct['ROOT']) && is_array($dataStruct['ROOT']['el'])) {
02577                         $lang = 'l' . $lKey; // Default language, other options are "lUK" or whatever country code (independant of system!!!)
02578                         $PA['_valLang'] = $langChildren && !$langDisabled ? $editData['meta']['currentLangId'] : 'DEF'; // Default language, other options are "lUK" or whatever country code (independant of system!!!)
02579                         $PA['_lang'] = $lang;
02580                             // Assemble key for loading the correct CSH file
02581                         $dsPointerFields = t3lib_div::trimExplode(',', $GLOBALS['TCA'][$table]['columns'][$field]['config']['ds_pointerField'], TRUE);
02582                         $PA['_cshKey'] = $table . '.' . $field;
02583                         foreach ($dsPointerFields as $key) {
02584                             $PA['_cshKey'] .= '.' . $row[$key];
02585                         }
02586 
02587                             // Push the sheet level tab to DynNestedStack
02588                         if (is_array($dataStructArray['sheets'])) {
02589                             $tabIdentString = $GLOBALS['TBE_TEMPLATE']->getDynTabMenuId('TCEFORMS:flexform:' . $PA['itemFormElName'] . $PA['_lang']);
02590                             $this->pushToDynNestedStack('tab', $tabIdentString . '-' . (count($tabParts) + 1));
02591                         }
02592                             // Render flexform:
02593                         $tRows = $this->getSingleField_typeFlex_draw(
02594                             $dataStruct['ROOT']['el'],
02595                             $editData['data'][$sheet][$lang],
02596                             $table,
02597                             $field,
02598                             $row,
02599                             $PA,
02600                             '[data][' . $sheet . '][' . $lang . ']'
02601                         );
02602                         $sheetContent = '<div class="typo3-TCEforms-flexForm">' . $tRows . '</div>';
02603 
02604 
02605                             // Pop the sheet level tab from DynNestedStack
02606                         if (is_array($dataStructArray['sheets'])) {
02607                             $this->popFromDynNestedStack('tab', $tabIdentString . '-' . (count($tabParts) + 1));
02608                         }
02609                     } else {
02610                         $sheetContent = 'Data Structure ERROR: No ROOT element found for sheet "' . $sheet . '".';
02611                     }
02612 
02613                         // Add to tab:
02614                     $tabParts[] = array(
02615                         'label' => ($dataStruct['ROOT']['TCEforms']['sheetTitle'] ? $this->sL($dataStruct['ROOT']['TCEforms']['sheetTitle']) : $sheet),
02616                         'description' => ($dataStruct['ROOT']['TCEforms']['sheetDescription'] ? $this->sL($dataStruct['ROOT']['TCEforms']['sheetDescription']) : ''),
02617                         'linkTitle' => ($dataStruct['ROOT']['TCEforms']['sheetShortDescr'] ? $this->sL($dataStruct['ROOT']['TCEforms']['sheetShortDescr']) : ''),
02618                         'content' => $sheetContent
02619                     );
02620                 }
02621 
02622                 if (is_array($dataStructArray['sheets'])) {
02623                     $dividersToTabsBehaviour = (isset($GLOBALS['TCA'][$table]['ctrl']['dividers2tabs']) ? $GLOBALS['TCA'][$table]['ctrl']['dividers2tabs'] : 1);
02624                     $item .= $this->getDynTabMenu($tabParts, 'TCEFORMS:flexform:' . $PA['itemFormElName'] . $PA['_lang'], $dividersToTabsBehaviour);
02625                 } else {
02626                     $item .= $sheetContent;
02627                 }
02628             }
02629         } else {
02630             $item = 'Data Structure ERROR: ' . $dataStructArray;
02631         }
02632 
02633         return $item;
02634     }
02635 
02636     /**
02637      * Creates the language menu for FlexForms:
02638      *
02639      * @param   [type]      $languages: ...
02640      * @param   [type]      $elName: ...
02641      * @param   [type]      $selectedLanguage: ...
02642      * @param   [type]      $multi: ...
02643      * @return  string      HTML for menu
02644      */
02645     function getSingleField_typeFlex_langMenu($languages, $elName, $selectedLanguage, $multi = 1) {
02646         $opt = array();
02647         foreach ($languages as $lArr) {
02648             $opt[] = '<option value="' . htmlspecialchars($lArr['ISOcode']) . '"' . (in_array($lArr['ISOcode'], $selectedLanguage) ? ' selected="selected"' : '') . '>' . htmlspecialchars($lArr['title']) . '</option>';
02649         }
02650 
02651         $output = '<select id="' . uniqid('tceforms-multiselect-') . ' class="tceforms-select tceforms-multiselect tceforms-flexlangmenu" name="' . $elName . '[]"' . ($multi ? ' multiple="multiple" size="' . count($languages) . '"' : '') . '>' . implode('', $opt) . '</select>';
02652 
02653         return $output;
02654     }
02655 
02656     /**
02657      * Creates the menu for selection of the sheets:
02658      *
02659      * @param   array       Sheet array for which to render the menu
02660      * @param   string      Form element name of the field containing the sheet pointer
02661      * @param   string      Current sheet key
02662      * @return  string      HTML for menu
02663      */
02664     function getSingleField_typeFlex_sheetMenu($sArr, $elName, $sheetKey) {
02665 
02666         $tCells = array();
02667         $pct = round(100 / count($sArr));
02668         foreach ($sArr as $sKey => $sheetCfg) {
02669             if ($GLOBALS['BE_USER']->jsConfirmation(1)) {
02670                 $onClick = 'if (confirm(TBE_EDITOR.labels.onChangeAlert) && TBE_EDITOR.checkSubmit(-1)){' . $this->elName($elName) . ".value='" . $sKey . "'; TBE_EDITOR.submitForm()};";
02671             } else {
02672                 $onClick = 'if(TBE_EDITOR.checkSubmit(-1)){ ' . $this->elName($elName) . ".value='" . $sKey . "'; TBE_EDITOR.submitForm();}";
02673             }
02674 
02675 
02676             $tCells[] = '<td width="' . $pct . '%" style="' . ($sKey == $sheetKey ? 'background-color: #9999cc; font-weight: bold;' : 'background-color: #aaaaaa;') . ' cursor: hand;" onclick="' . htmlspecialchars($onClick) . '" align="center">' .
02677                         ($sheetCfg['ROOT']['TCEforms']['sheetTitle'] ? $this->sL($sheetCfg['ROOT']['TCEforms']['sheetTitle']) : $sKey) .
02678                         '</td>';
02679         }
02680 
02681         return '<table border="0" cellpadding="0" cellspacing="2" class="typo3-TCEforms-flexForm-sheetMenu"><tr>' . implode('', $tCells) . '</tr></table>';
02682     }
02683 
02684     /**
02685      * Recursive rendering of flexforms
02686      *
02687      * @param   array       (part of) Data Structure for which to render. Keys on first level is flex-form fields
02688      * @param   array       (part of) Data array of flexform corresponding to the input DS. Keys on first level is flex-form field names
02689      * @param   string      Table name, eg. tt_content
02690      * @param   string      Field name, eg. tx_templavoila_flex
02691      * @param   array       The particular record from $table in which the field $field is found
02692      * @param   array       Array of standard information for rendering of a form field in TCEforms, see other rendering functions too
02693      * @param   string      Form field prefix, eg. "[data][sDEF][lDEF][...][...]"
02694      * @param   integer     Indicates nesting level for the function call
02695      * @param   string      Prefix for ID-values
02696      * @param   boolean     Defines whether the next flexform level is open or closed. Comes from _TOGGLE pseudo field in FlexForm xml.
02697      * @return  string      HTMl code for form.
02698      */
02699     function getSingleField_typeFlex_draw($dataStruct, $editData, $table, $field, $row, &$PA, $formPrefix = '', $level = 0, $idPrefix = 'ID', $toggleClosed = FALSE) {
02700 
02701         $output = '';
02702         $mayRestructureFlexforms = $GLOBALS['BE_USER']->checkLanguageAccess(0);
02703 
02704             // Data Structure array must be ... and array of course...
02705         if (is_array($dataStruct)) {
02706             foreach ($dataStruct as $key => $value) { // Traversing fields in structure:
02707                 if (is_array($value)) { // The value of each entry must be an array.
02708 
02709                         // ********************
02710                         // Making the row:
02711                         // ********************
02712                         // Title of field:
02713                     $theTitle = htmlspecialchars(t3lib_div::fixed_lgd_cs($this->sL($value['tx_templavoila']['title']), 30));
02714 
02715                         // If it's a "section" or "container":
02716                     if ($value['type'] == 'array') {
02717 
02718                             // Creating IDs for form fields:
02719                             // It's important that the IDs "cascade" - otherwise we can't dynamically expand the flex form because this relies on simple string substitution of the first parts of the id values.
02720                         $thisId = t3lib_div::shortMd5(uniqid('id', TRUE)); // This is a suffix used for forms on this level
02721                         $idTagPrefix = $idPrefix . '-' . $thisId; // $idPrefix is the prefix for elements on lower levels in the hierarchy and we combine this with the thisId value to form a new ID on this level.
02722 
02723                             // If it's a "section" containing other elements:
02724                         if ($value['section']) {
02725 
02726                                 // Load script.aculo.us if flexform sections can be moved by drag'n'drop:
02727                             $GLOBALS['SOBE']->doc->getPageRenderer()->loadScriptaculous();
02728                                 // Render header of section:
02729                             $output .= '<div class="t3-form-field-label-flexsection"><strong>' . $theTitle . '</strong></div>';
02730 
02731                                 // Render elements in data array for section:
02732                             $tRows = array();
02733                             $cc = 0;
02734                             if (is_array($editData[$key]['el'])) {
02735                                 foreach ($editData[$key]['el'] as $k3 => $v3) {
02736                                     $cc = $k3;
02737                                     if (is_array($v3)) {
02738                                         $theType = key($v3);
02739                                         $theDat = $v3[$theType];
02740                                         $newSectionEl = $value['el'][$theType];
02741                                         if (is_array($newSectionEl)) {
02742                                             $tRows[] = $this->getSingleField_typeFlex_draw(
02743                                                 array($theType => $newSectionEl),
02744                                                 array($theType => $theDat),
02745                                                 $table,
02746                                                 $field,
02747                                                 $row,
02748                                                 $PA,
02749                                                 $formPrefix . '[' . $key . '][el][' . $cc . ']',
02750                                                 $level + 1,
02751                                                 $idTagPrefix,
02752                                                 $v3['_TOGGLE']
02753                                             );
02754                                         }
02755                                     }
02756                                 }
02757                             }
02758 
02759                                 // Now, we generate "templates" for new elements that could be added to this section by traversing all possible types of content inside the section:
02760                                 // We have to handle the fact that requiredElements and such may be set during this rendering process and therefore we save and reset the state of some internal variables - little crude, but works...
02761 
02762                                 // Preserving internal variables we don't want to change:
02763                             $TEMP_requiredElements = $this->requiredElements;
02764 
02765                                 // Traversing possible types of new content in the section:
02766                             $newElementsLinks = array();
02767                             foreach ($value['el'] as $nnKey => $nCfg) {
02768                                 $additionalJS_post_saved = $this->additionalJS_post;
02769                                 $this->additionalJS_post = array();
02770                                 $additionalJS_submit_saved = $this->additionalJS_submit;
02771                                 $this->additionalJS_submit = array();
02772                                 $newElementTemplate = $this->getSingleField_typeFlex_draw(
02773                                     array($nnKey => $nCfg),
02774                                     array(),
02775                                     $table,
02776                                     $field,
02777                                     $row,
02778                                     $PA,
02779                                     $formPrefix . '[' . $key . '][el][' . $idTagPrefix . '-form]',
02780                                     $level + 1,
02781                                     $idTagPrefix
02782                                 );
02783 
02784                                     // Makes a "Add new" link:
02785                                 $var = uniqid('idvar');
02786                                 $replace = 'replace(/' . $idTagPrefix . '-/g,"' . $idTagPrefix . '-"+' . $var . '+"-")';
02787                                 $onClickInsert = 'var ' . $var . ' = "' . 'idx"+(new Date()).getTime();';
02788                                     // Do not replace $isTagPrefix in setActionStatus() because it needs section id!
02789                                 $onClickInsert .= 'new Insertion.Bottom($("' . $idTagPrefix . '"), unescape("' . rawurlencode($newElementTemplate) . '").' . $replace . '); setActionStatus("' . $idTagPrefix . '");';
02790                                 $onClickInsert .= 'eval(unescape("' . rawurlencode(implode(';', $this->additionalJS_post)) . '").' . $replace . ');';
02791                                 $onClickInsert .= 'TBE_EDITOR.addActionChecks("submit", unescape("' . rawurlencode(implode(';', $this->additionalJS_submit)) . '").' . $replace . ');';
02792                                 $onClickInsert .= 'return false;';
02793                                     // Kasper's comment (kept for history): Maybe there is a better way to do this than store the HTML for the new element in rawurlencoded format - maybe it even breaks with certain charsets? But for now this works...
02794                                 $this->additionalJS_post = $additionalJS_post_saved;
02795                                 $this->additionalJS_submit = $additionalJS_submit_saved;
02796                                 $new = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:cm.new', 1);
02797                                 $newElementsLinks[] = '<a href="#" onclick="' . htmlspecialchars($onClickInsert) . '">' .
02798                                                       t3lib_iconWorks::getSpriteIcon('actions-document-new') .
02799                                                       htmlspecialchars(t3lib_div::fixed_lgd_cs($this->sL($nCfg['tx_templavoila']['title']), 30)) . '</a>';
02800                             }
02801 
02802                                 // Reverting internal variables we don't want to change:
02803                             $this->requiredElements = $TEMP_requiredElements;
02804 
02805                                 // Adding the sections:
02806                             $toggleAll = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.toggleall', 1);
02807                             $output .= '
02808                             <div class="t3-form-field-toggle-flexsection">
02809                                 <a href="#" onclick="' . htmlspecialchars('flexFormToggleSubs("' . $idTagPrefix . '"); return false;') . '">'
02810                                        . t3lib_iconWorks::getSpriteIcon('actions-move-right', array('title' => $toggleAll)) . $toggleAll . '
02811                                 </a>
02812                             </div>
02813 
02814                             <div id="' . $idTagPrefix . '" class="t3-form-field-container-flexsection">' . implode('', $tRows) . '</div>';
02815                             $output .= $mayRestructureFlexforms ? '<div class="t3-form-field-add-flexsection"><strong>' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.addnew', 1) . ':</strong> ' . implode(' | ', $newElementsLinks) . '</div>' : '';
02816                         } else {
02817                                 // It is a container
02818 
02819                             $toggleIcon_open = t3lib_iconWorks::getSpriteIcon('actions-move-down');
02820                             $toggleIcon_close = t3lib_iconWorks::getSpriteIcon('actions-move-right');
02821 
02822                                 // Create on-click actions.
02823                                 //$onClickCopy = 'new Insertion.After($("'.$idTagPrefix.'"), getOuterHTML("'.$idTagPrefix.'").replace(/'.$idTagPrefix.'-/g,"'.$idTagPrefix.'-copy"+Math.floor(Math.random()*100000+1)+"-")); return false;';    // Copied elements doesn't work (well) in Safari while they do in Firefox and MSIE! UPDATE: It turned out that copying doesn't work for any browser, simply because the data from the copied form never gets submitted to the server for some reason! So I decided to simply disable copying for now. If it's requested by customers we can look to enable it again and fix the issue. There is one un-fixable problem though; Copying an element like this will violate integrity if files are attached inside that element because the file reference doesn't get an absolute path prefixed to it which would be required to have TCEmain generate a new copy of the file.
02824                             $onClickRemove = 'if (confirm("Are you sure?")){/*###REMOVE###*/;$("' . $idTagPrefix . '").hide();setActionStatus("' . $idPrefix . '");} return false;';
02825                             $onClickToggle = 'flexFormToggle("' . $idTagPrefix . '"); return false;';
02826 
02827                             $onMove = 'flexFormSortable("' . $idPrefix . '")';
02828                                 // Notice: Creating "new" elements after others seemed to be too difficult to do and since moving new elements created in the bottom is now so easy with drag'n'drop I didn't see the need.
02829 
02830 
02831                                 // Putting together header of a section. Sections can be removed, copied, opened/closed, moved up and down:
02832                                 // I didn't know how to make something right-aligned without a table, so I put it in a table. can be made into <div>'s if someone like to.
02833                                 // Notice: The fact that I make a "Sortable.create" right onmousedown is that if we initialize this when rendering the form in PHP new and copied elements will not be possible to move as a sortable. But this way a new sortable is initialized everytime someone tries to move and it will always work.
02834                             $ctrlHeader = '
02835                                 <table class="t3-form-field-header-flexsection" onmousedown="' . ($mayRestructureFlexforms ? htmlspecialchars($onMove) : '') . '">
02836                                 <tr>
02837                                     <td>
02838                                         <a href="#" onclick="' . htmlspecialchars($onClickToggle) . '" id="' . $idTagPrefix . '-toggle">
02839                                             ' . ($toggleClosed ? $toggleIcon_close : $toggleIcon_open) . '
02840                                         </a>
02841                                         <strong>' . $theTitle . '</strong> <em><span id="' . $idTagPrefix . '-preview"></span></em>
02842                                     </td>
02843                                     <td align="right">' .
02844                                           ($mayRestructureFlexforms ? t3lib_iconWorks::getSpriteIcon('actions-move-move', array('title' => 'Drag to Move')) : '') .
02845                                           ($mayRestructureFlexforms ? '<a href="#" onclick="' . htmlspecialchars($onClickRemove) . '">' . t3lib_iconWorks::getSpriteIcon('actions-edit-delete', array('title' => 'Delete')) : '') .
02846                                           '</td>
02847                                     </tr>
02848                                 </table>';
02849 
02850                             $s = t3lib_div::revExplode('[]', $formPrefix, 2);
02851                             $actionFieldName = '_ACTION_FLEX_FORM' . $PA['itemFormElName'] . $s[0] . '][_ACTION][' . $s[1];
02852 
02853                                 // Push the container to DynNestedStack as it may be toggled
02854                             $this->pushToDynNestedStack('flex', $idTagPrefix);
02855 
02856                                 // Putting together the container:
02857                             $this->additionalJS_delete = array();
02858                             $output .= '
02859                                 <div id="' . $idTagPrefix . '" class="t3-form-field-container-flexsections">
02860                                     <input id="' . $idTagPrefix . '-action" type="hidden" name="' . htmlspecialchars($actionFieldName) . '" value=""/>
02861 
02862                                     ' . $ctrlHeader . '
02863                                     <div class="t3-form-field-record-flexsection" id="' . $idTagPrefix . '-content"' . ($toggleClosed ? ' style="display:none;"' : '') . '>' .
02864                                        $this->getSingleField_typeFlex_draw(
02865                                            $value['el'],
02866                                            $editData[$key]['el'],
02867                                            $table,
02868                                            $field,
02869                                            $row,
02870                                            $PA,
02871                                            $formPrefix . '[' . $key . '][el]',
02872                                            $level + 1,
02873                                            $idTagPrefix
02874                                        ) . '
02875                                     </div>
02876                                     <input id="' . $idTagPrefix . '-toggleClosed" type="hidden" name="' . htmlspecialchars('data[' . $table . '][' . $row['uid'] . '][' . $field . ']' . $formPrefix . '[_TOGGLE]') . '" value="' . ($toggleClosed ? 1 : 0) . '" />
02877                                 </div>';
02878                             $output = str_replace('/*###REMOVE###*/', t3lib_div::slashJS(htmlspecialchars(implode('', $this->additionalJS_delete))), $output);
02879                                 // NOTICE: We are saving the toggle-state directly in the flexForm XML and "unauthorized" according to the data structure. It means that flexform XML will report unclean and a cleaning operation will remove the recorded togglestates. This is not a fatal problem. Ideally we should save the toggle states in meta-data but it is much harder to do that. And this implementation was easy to make and with no really harmful impact.
02880 
02881                                 // Pop the container from DynNestedStack
02882                             $this->popFromDynNestedStack('flex', $idTagPrefix);
02883                         }
02884 
02885                             // If it's a "single form element":
02886                     } elseif (is_array($value['TCEforms']['config'])) { // Rendering a single form element:
02887 
02888                         if (is_array($PA['_valLang'])) {
02889                             $rotateLang = $PA['_valLang'];
02890                         } else {
02891                             $rotateLang = array($PA['_valLang']);
02892                         }
02893 
02894                         $conditionData = is_array($editData) ? $editData : array();
02895                             // add current $row to data processed by isDisplayCondition()
02896                         $conditionData['parentRec'] = $row;
02897 
02898                         $tRows = array();
02899                         foreach ($rotateLang as $vDEFkey) {
02900                             $vDEFkey = 'v' . $vDEFkey;
02901 
02902                             if (!$value['TCEforms']['displayCond'] || $this->isDisplayCondition($value['TCEforms']['displayCond'], $conditionData, $vDEFkey)) {
02903                                 $fakePA = array();
02904                                 $fakePA['fieldConf'] = array(
02905                                     'label' => $this->sL(trim($value['TCEforms']['label'])),
02906                                     'config' => $value['TCEforms']['config'],
02907                                     'defaultExtras' => $value['TCEforms']['defaultExtras'],
02908                                     'onChange' => $value['TCEforms']['onChange']
02909                                 );
02910                                 if ($PA['_noEditDEF'] && $PA['_lang'] === 'lDEF') {
02911                                     $fakePA['fieldConf']['config'] = array(
02912                                         'type' => 'none',
02913                                         'rows' => 2
02914                                     );
02915                                 }
02916 
02917                                 if (
02918                                     $fakePA['fieldConf']['onChange'] == 'reload' ||
02919                                     ($GLOBALS['TCA'][$table]['ctrl']['type'] && !strcmp($key, $GLOBALS['TCA'][$table]['ctrl']['type'])) ||
02920                                     ($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'] && t3lib_div::inList($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'], $key))) {
02921                                     if ($GLOBALS['BE_USER']->jsConfirmation(1)) {
02922                                         $alertMsgOnChange = 'if (confirm(TBE_EDITOR.labels.onChangeAlert) && TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };';
02923                                     } else {
02924                                         $alertMsgOnChange = 'if(TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm();}';
02925                                     }
02926                                 } else {
02927                                     $alertMsgOnChange = '';
02928                                 }
02929 
02930                                 $fakePA['fieldChangeFunc'] = $PA['fieldChangeFunc'];
02931                                 if (strlen($alertMsgOnChange)) {
02932                                     $fakePA['fieldChangeFunc']['alert'] = $alertMsgOnChange;
02933                                 }
02934                                 $fakePA['onFocus'] = $PA['onFocus'];
02935                                 $fakePA['label'] = $PA['label'];
02936 
02937                                 $fakePA['itemFormElName'] = $PA['itemFormElName'] . $formPrefix . '[' . $key . '][' . $vDEFkey . ']';
02938                                 $fakePA['itemFormElName_file'] = $PA['itemFormElName_file'] . $formPrefix . '[' . $key . '][' . $vDEFkey . ']';
02939                                 $fakePA['itemFormElID'] = $fakePA['itemFormElName'];
02940 
02941                                 if (isset($editData[$key][$vDEFkey])) {
02942                                     $fakePA['itemFormElValue'] = $editData[$key][$vDEFkey];
02943                                 } else {
02944                                     $fakePA['itemFormElValue'] = $fakePA['fieldConf']['config']['default'];
02945                                 }
02946 
02947                                 $theFormEl = $this->getSingleField_SW($table, $field, $row, $fakePA);
02948                                 $theTitle = htmlspecialchars($fakePA['fieldConf']['label']);
02949 
02950                                 if (!in_array('DEF', $rotateLang)) {
02951                                     $defInfo = '<div class="typo3-TCEforms-originalLanguageValue">' . $this->getLanguageIcon($table, $row, 0) .
02952                                                $this->previewFieldValue($editData[$key]['vDEF'], $fakePA['fieldConf'], $field) . '&nbsp;</div>';
02953                                 } else {
02954                                     $defInfo = '';
02955                                 }
02956 
02957                                 if (!$PA['_noEditDEF']) {
02958                                     $prLang = $this->getAdditionalPreviewLanguages();
02959                                     foreach ($prLang as $prL) {
02960                                         $defInfo .= '<div class="typo3-TCEforms-originalLanguageValue">' . $this->getLanguageIcon($table, $row, 'v' . $prL['ISOcode']) .
02961                                                     $this->previewFieldValue($editData[$key]['v' . $prL['ISOcode']], $fakePA['fieldConf'], $field) . '&nbsp;</div>';
02962                                     }
02963                                 }
02964 
02965                                 $languageIcon = '';
02966                                 if ($vDEFkey != 'vDEF') {
02967                                     $languageIcon = $this->getLanguageIcon($table, $row, $vDEFkey);
02968                                 }
02969                                     // Put row together
02970                                     // possible linebreaks in the label through xml: \n => <br/>, usage of nl2br() not possible, so it's done through str_replace
02971                                 $processedTitle = str_replace('\n', '<br />', $theTitle);
02972                                 $tRows[] = '<div class="t3-form-field-container t3-form-field-container-flex">' .
02973                                            '<div class="t3-form-field-label t3-form-field-label-flex">' .
02974                                            $languageIcon .
02975                                            t3lib_BEfunc::wrapInHelp($PA['_cshKey'], $key, $processedTitle) .
02976                                            '</div>
02977                                     <div class="t3-form-field t3-form-field-flex">' . $theFormEl . $defInfo . $this->renderVDEFDiff($editData[$key], $vDEFkey) . '</div>
02978                                 </div>';
02979                             }
02980                         }
02981                         if (count($tRows)) {
02982                             $output .= implode('', $tRows);
02983                         }
02984                     }
02985                 }
02986             }
02987         }
02988 
02989         return $output;
02990     }
02991 
02992     /**
02993      * Handler for unknown types.
02994      *
02995      * @param   string      The table name of the record
02996      * @param   string      The field name which this element is supposed to edit
02997      * @param   array       The record data array where the value(s) for the field can be found
02998      * @param   array       An array with additional configuration options.
02999      * @return  string      The HTML code for the TCEform field
03000      */
03001     function getSingleField_typeUnknown($table, $field, $row, &$PA) {
03002         $item = 'Unknown type: ' . $PA['fieldConf']['config']['form_type'] . '<br />';
03003 
03004         return $item;
03005     }
03006 
03007     /**
03008      * User defined field type
03009      *
03010      * @param   string      The table name of the record
03011      * @param   string      The field name which this element is supposed to edit
03012      * @param   array       The record data array where the value(s) for the field can be found
03013      * @param   array       An array with additional configuration options.
03014      * @return  string      The HTML code for the TCEform field
03015      */
03016     function getSingleField_typeUser($table, $field, $row, &$PA) {
03017         $PA['table'] = $table;
03018         $PA['field'] = $field;
03019         $PA['row'] = $row;
03020 
03021         $PA['pObj'] =& $this;
03022 
03023         return t3lib_div::callUserFunction($PA['fieldConf']['config']['userFunc'], $PA, $this);
03024     }
03025 
03026 
03027     /************************************************************
03028      *
03029      * Field content processing
03030      *
03031      ************************************************************/
03032 
03033     /**
03034      * Format field content of various types if $config['format'] is set to date, filesize, ..., user
03035      * This is primarily for the field type none but can be used for user field types for example
03036      *
03037      * @param   array       Configuration for the display
03038      * @param   string      The value to display
03039      * @return  string      Formatted Field content
03040      */
03041     function formatValue($config, $itemValue) {
03042         $format = trim($config['format']);
03043         switch ($format) {
03044             case 'date':
03045                 if ($itemValue) {
03046                     $option = trim($config['format.']['option']);
03047                     if ($option) {
03048                         if ($config['format.']['strftime']) {
03049                             $value = strftime($option, $itemValue);
03050                         } else {
03051                             $value = date($option, $itemValue);
03052                         }
03053                     } else {
03054                         $value = date('d-m-Y', $itemValue);
03055                     }
03056                 } else {
03057                     $value = '';
03058                 }
03059                 if ($config['format.']['appendAge']) {
03060                     $value .= ' (' .
03061                               t3lib_BEfunc::calcAge(($GLOBALS['EXEC_TIME'] - $itemValue), $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.minutesHoursDaysYears')) .
03062                               ')';
03063                 }
03064                 $itemValue = $value;
03065             break;
03066             case 'datetime': // compatibility with "eval" (type "input")
03067                 $itemValue = date('H:i d-m-Y', $itemValue);
03068             break;
03069             case 'time': // compatibility with "eval" (type "input")
03070                 $itemValue = date('H:i', $itemValue);
03071             break;
03072             case 'timesec': // compatibility with "eval" (type "input")
03073                 $itemValue = date('H:i:s', $itemValue);
03074             break;
03075             case 'year': // compatibility with "eval" (type "input")
03076                 $itemValue = date('Y', $itemValue);
03077             break;
03078             case 'int':
03079                 $baseArr = array('dec' => 'd', 'hex' => 'x', 'HEX' => 'X', 'oct' => 'o', 'bin' => 'b');
03080                 $base = trim($config['format.']['base']);
03081                 $format = $baseArr[$base] ? $baseArr[$base] : 'd';
03082                 $itemValue = sprintf('%' . $format, $itemValue);
03083             break;
03084             case 'float':
03085                 $precision = t3lib_div::intInRange($config['format.']['precision'], 1, 10, 2);
03086                 $itemValue = sprintf('%.' . $precision . 'f', $itemValue);
03087             break;
03088             case 'number':
03089                 $format = trim($config['format.']['option']);
03090                 $itemValue = sprintf('%' . $format, $itemValue);
03091             break;
03092             case 'md5':
03093                 $itemValue = md5($itemValue);
03094             break;
03095             case 'filesize':
03096                 $value = t3lib_div::formatSize(intval($itemValue));
03097                 if ($config['format.']['appendByteSize']) {
03098                     $value .= ' (' . $itemValue . ')';
03099                 }
03100                 $itemValue = $value;
03101             break;
03102             case 'user':
03103                 $func = trim($config['format.']['userFunc']);
03104                 if ($func) {
03105                     $params = array(
03106                         'value' => $itemValue,
03107                         'args' => $config['format.']['userFunc'],
03108                         'config' => $config,
03109                         'pObj' => &$this
03110                     );
03111                     $itemValue = t3lib_div::callUserFunction($func, $params, $this);
03112                 }
03113             break;
03114             default:
03115             break;
03116         }
03117 
03118         return $itemValue;
03119     }
03120 
03121 
03122     /************************************************************
03123      *
03124      * "Configuration" fetching/processing functions
03125      *
03126      ************************************************************/
03127 
03128     /**
03129      * Calculate and return the current "types" pointer value for a record
03130      *
03131      * @param   string      The table name. MUST be in $TCA
03132      * @param   array       The row from the table, should contain at least the "type" field, if applicable.
03133      * @return  string      Return the "type" value for this record, ready to pick a "types" configuration from the $TCA array.
03134      */
03135     function getRTypeNum($table, $row) {
03136         global $TCA;
03137             // If there is a "type" field configured...
03138         if ($TCA[$table]['ctrl']['type']) {
03139             $typeFieldName = $TCA[$table]['ctrl']['type'];
03140             $typeFieldConfig = $TCA[$table]['columns'][$typeFieldName];
03141             $typeNum = $this->getLanguageOverlayRawValue($table, $row, $typeFieldName, $typeFieldConfig);
03142             if (!strcmp($typeNum, '')) {
03143                 $typeNum = 0;
03144             } // If that value is an empty string, set it to "0" (zero)
03145         } else {
03146             $typeNum = 0; // If no "type" field, then set to "0" (zero)
03147         }
03148 
03149         $typeNum = (string) $typeNum; // Force to string. Necessary for eg '-1' to be recognized as a type value.
03150         if (!$TCA[$table]['types'][$typeNum]) { // However, if the type "0" is not found in the "types" array, then default to "1" (for historical reasons)
03151             $typeNum = 1;
03152         }
03153 
03154         return $typeNum;
03155     }
03156 
03157     /**
03158      * Used to adhoc-rearrange the field order normally set in the [types][showitem] list
03159      *
03160      * @param   array       A [types][showitem] list of fields, exploded by ","
03161      * @return  array       Returns rearranged version (keys are changed around as well.)
03162      * @see getMainFields()
03163      */
03164     function rearrange($fields) {
03165         $fO = array_flip(t3lib_div::trimExplode(',', $this->fieldOrder, 1));
03166         $newFields = array();
03167         foreach ($fields as $cc => $content) {
03168             $cP = t3lib_div::trimExplode(';', $content);
03169             if (isset($fO[$cP[0]])) {
03170                 $newFields[$fO[$cP[0]]] = $content;
03171                 unset($fields[$cc]);
03172             }
03173         }
03174         ksort($newFields);
03175         $fields = array_merge($newFields, $fields); // Candidate for t3lib_div::array_merge() if integer-keys will some day make trouble...
03176         return $fields;
03177     }
03178 
03179     /**
03180      * Producing an array of field names NOT to display in the form, based on settings from subtype_value_field, bitmask_excludelist_bits etc.
03181      * Notice, this list is in NO way related to the "excludeField" flag
03182      *
03183      * @param   string      Table name, MUST be in $TCA
03184      * @param   array       A record from table.
03185      * @param   string      A "type" pointer value, probably the one calculated based on the record array.
03186      * @return  array       Array with fieldnames as values. The fieldnames are those which should NOT be displayed "anyways"
03187      * @see getMainFields()
03188      */
03189     function getExcludeElements($table, $row, $typeNum) {
03190         global $TCA;
03191 
03192             // Init:
03193         $excludeElements = array();
03194 
03195             // If a subtype field is defined for the type
03196         if ($TCA[$table]['types'][$typeNum]['subtype_value_field']) {
03197             $sTfield = $TCA[$table]['types'][$typeNum]['subtype_value_field'];
03198             if (trim($TCA[$table]['types'][$typeNum]['subtypes_excludelist'][$row[$sTfield]])) {
03199                 $excludeElements = t3lib_div::trimExplode(',', $TCA[$table]['types'][$typeNum]['subtypes_excludelist'][$row[$sTfield]], 1);
03200             }
03201         }
03202 
03203             // If a bitmask-value field has been configured, then find possible fields to exclude based on that:
03204         if ($TCA[$table]['types'][$typeNum]['bitmask_value_field']) {
03205             $sTfield = $TCA[$table]['types'][$typeNum]['bitmask_value_field'];
03206             $sTValue = t3lib_div::intInRange($row[$sTfield], 0);
03207             if (is_array($TCA[$table]['types'][$typeNum]['bitmask_excludelist_bits'])) {
03208                 foreach ($TCA[$table]['types'][$typeNum]['bitmask_excludelist_bits'] as $bitKey => $eList) {
03209                     $bit = substr($bitKey, 1);
03210                     if (t3lib_div::testInt($bit)) {
03211                         $bit = t3lib_div::intInRange($bit, 0, 30);
03212                         if (
03213                             (substr($bitKey, 0, 1) == '-' && !($sTValue & pow(2, $bit))) ||
03214                             (substr($bitKey, 0, 1) == '+' && ($sTValue & pow(2, $bit)))
03215                         ) {
03216                             $excludeElements = array_merge($excludeElements, t3lib_div::trimExplode(',', $eList, 1));
03217                         }
03218                     }
03219                 }
03220             }
03221         }
03222 
03223             // Return the array of elements:
03224         return $excludeElements;
03225     }
03226 
03227     /**
03228      * Finds possible field to add to the form, based on subtype fields.
03229      *
03230      * @param   string      Table name, MUST be in $TCA
03231      * @param   array       A record from table.
03232      * @param   string      A "type" pointer value, probably the one calculated based on the record array.
03233      * @return  array       An array containing two values: 1) Another array containing fieldnames to add and 2) the subtype value field.
03234      * @see getMainFields()
03235      */
03236     function getFieldsToAdd($table, $row, $typeNum) {
03237         global $TCA;
03238 
03239             // Init:
03240         $addElements = array();
03241 
03242             // If a subtype field is defined for the type
03243         if ($TCA[$table]['types'][$typeNum]['subtype_value_field']) {
03244             $sTfield = $TCA[$table]['types'][$typeNum]['subtype_value_field'];
03245             if (trim($TCA[$table]['types'][$typeNum]['subtypes_addlist'][$row[$sTfield]])) {
03246                 $addElements = t3lib_div::trimExplode(',', $TCA[$table]['types'][$typeNum]['subtypes_addlist'][$row[$sTfield]], 1);
03247             }
03248         }
03249             // Return the return
03250         return array($addElements, $sTfield);
03251     }
03252 
03253     /**
03254      * Merges the current [types][showitem] array with the array of fields to add for the current subtype field of the "type" value.
03255      *
03256      * @param   array       A [types][showitem] list of fields, exploded by ","
03257      * @param   array       The output from getFieldsToAdd()
03258      * @return  array       Return the modified $fields array.
03259      * @see getMainFields(),getFieldsToAdd()
03260      */
03261     function mergeFieldsWithAddedFields($fields, $fieldsToAdd) {
03262         if (count($fieldsToAdd[0])) {
03263             $c = 0;
03264             foreach ($fields as $fieldInfo) {
03265                 $parts = explode(';', $fieldInfo);
03266                 if (!strcmp(trim($parts[0]), $fieldsToAdd[1])) {
03267                     array_splice(
03268                         $fields,
03269                         $c + 1,
03270                         0,
03271                         $fieldsToAdd[0]
03272                     );
03273                     break;
03274                 }
03275                 $c++;
03276             }
03277         }
03278         return $fields;
03279     }
03280 
03281 
03282     /**
03283      * Returns TSconfig for table/row
03284      * Multiple requests to this function will return cached content so there is no performance loss in calling this many times since the information is looked up only once.
03285      *
03286      * @param   string      The table name
03287      * @param   array       The table row (Should at least contain the "uid" value, even if "NEW..." string. The "pid" field is important as well, and negative values will be intepreted as pointing to a record from the same table.)
03288      * @param   string      Optionally you can specify the field name as well. In that case the TSconfig for the field is returned.
03289      * @return  mixed       The TSconfig values (probably in an array)
03290      * @see t3lib_BEfunc::getTCEFORM_TSconfig()
03291      */
03292     function setTSconfig($table, $row, $field = '') {
03293         $mainKey = $table . ':' . $row['uid'];
03294         if (!isset($this->cachedTSconfig[$mainKey])) {
03295             $this->cachedTSconfig[$mainKey] = t3lib_BEfunc::getTCEFORM_TSconfig($table, $row);
03296         }
03297         if ($field) {
03298             return $this->cachedTSconfig[$mainKey][$field];
03299         } else {
03300             return $this->cachedTSconfig[$mainKey];
03301         }
03302     }
03303 
03304     /**
03305      * Overrides the TCA field configuration by TSconfig settings.
03306      *
03307      * Example TSconfig: TCEform.<table>.<field>.config.appearance.useSortable = 1
03308      * This overrides the setting in $TCA[<table>]['columns'][<field>]['config']['appearance']['useSortable'].
03309      *
03310      * @param   array       $fieldConfig: TCA field configuration
03311      * @param   array       $TSconfig: TSconfig
03312      * @return  array       Changed TCA field configuration
03313      */
03314     function overrideFieldConf($fieldConfig, $TSconfig) {
03315         if (is_array($TSconfig)) {
03316             $TSconfig = t3lib_div::removeDotsFromTS($TSconfig);
03317             $type = $fieldConfig['type'];
03318             if (is_array($TSconfig['config']) && is_array($this->allowOverrideMatrix[$type])) {
03319                     // Check if the keys in TSconfig['config'] are allowed to override TCA field config:
03320                 foreach (array_keys($TSconfig['config']) as $key) {
03321                     if (!in_array($key, $this->allowOverrideMatrix[$type], TRUE)) {
03322                         unset($TSconfig['config'][$key]);
03323                     }
03324                 }
03325                     // Override TCA field config by remaining TSconfig['config']:
03326                 if (count($TSconfig['config'])) {
03327                     $fieldConfig = t3lib_div::array_merge_recursive_overrule($fieldConfig, $TSconfig['config']);
03328                 }
03329             }
03330         }
03331 
03332         return $fieldConfig;
03333     }
03334 
03335     /**
03336      * Returns the "special" configuration (from the "types" "showitem" list) for a fieldname based on input table/record
03337      * (Not used anywhere...?)
03338      *
03339      * @param   string      The table name
03340      * @param   array       The table row (Should at least contain the "uid" value, even if "NEW..." string. The "pid" field is important as well, and negative values will be intepreted as pointing to a record from the same table.)
03341      * @param   string      Specify the field name.
03342      * @return  array
03343      * @see getSpecConfFromString(), t3lib_BEfunc::getTCAtypes()
03344      */
03345     function getSpecConfForField($table, $row, $field) {
03346             // Finds the current "types" configuration for the table/row:
03347         $types_fieldConfig = t3lib_BEfunc::getTCAtypes($table, $row);
03348 
03349             // If this is an array, then traverse it:
03350         if (is_array($types_fieldConfig)) {
03351             foreach ($types_fieldConfig as $vconf) {
03352                     // If the input field name matches one found in the 'types' list, then return the 'special' configuration.
03353                 if ($vconf['field'] == $field) {
03354                     return $vconf['spec'];
03355                 }
03356             }
03357         }
03358     }
03359 
03360     /**
03361      * Returns the "special" configuration of an "extra" string (non-parsed)
03362      *
03363      * @param   string      The "Part 4" of the fields configuration in "types" "showitem" lists.
03364      * @param   string      The ['defaultExtras'] value from field configuration
03365      * @return  array       An array with the special options in.
03366      * @see getSpecConfForField(), t3lib_BEfunc::getSpecConfParts()
03367      */
03368     function getSpecConfFromString($extraString, $defaultExtras) {
03369         return t3lib_BEfunc::getSpecConfParts($extraString, $defaultExtras);
03370     }
03371 
03372 
03373     /**
03374      * Loads the elements of a palette (collection of secondary options) in an array.
03375      *
03376      * @param   string      The table name
03377      * @param   array       The row array
03378      * @param   string      The palette number/pointer
03379      * @param   string      Optional alternative list of fields for the palette
03380      * @return  array       The palette elements
03381      */
03382     public function loadPaletteElements($table, $row, $palette, $itemList = '') {
03383         global $TCA;
03384 
03385         t3lib_div::loadTCA($table);
03386         $parts = array();
03387 
03388             // Getting excludeElements, if any.
03389         if (!is_array($this->excludeElements)) {
03390             $this->excludeElements = $this->getExcludeElements($table, $row, $this->getRTypeNum($table, $row));
03391         }
03392 
03393             // Load the palette TCEform elements
03394         if ($TCA[$table] && (is_array($TCA[$table]['palettes'][$palette]) || $itemList)) {
03395             $itemList = ($itemList ? $itemList : $TCA[$table]['palettes'][$palette]['showitem']);
03396             if ($itemList) {
03397                 $fields = t3lib_div::trimExplode(',', $itemList, 1);
03398                 foreach ($fields as $info) {
03399                     $fieldParts = t3lib_div::trimExplode(';', $info);
03400                     $theField = $fieldParts[0];
03401                     if ($theField === '--linebreak--') {
03402                         $parts[]['NAME'] = '--linebreak--';
03403                     } elseif (!in_array($theField, $this->excludeElements) && $TCA[$table]['columns'][$theField]) {
03404                         $this->palFieldArr[$palette][] = $theField;
03405                         $elem = $this->getSingleField($table, $theField, $row, $fieldParts[1], 1, '', $fieldParts[2]);
03406                         if (is_array($elem)) {
03407                             $parts[] = $elem;
03408                         }
03409                     }
03410                 }
03411             }
03412         }
03413         return $parts;
03414     }
03415 
03416 
03417     /************************************************************
03418      *
03419      * Display of localized content etc.
03420      *
03421      ************************************************************/
03422 
03423     /**
03424      * Will register data from original language records if the current record is a translation of another.
03425      * The original data is shown with the edited record in the form. The information also includes possibly diff-views of what changed in the original record.
03426      * Function called from outside (see alt_doc.php + quick edit) before rendering a form for a record
03427      *
03428      * @param   string      Table name of the record being edited
03429      * @param   array       Record array of the record being edited
03430      * @return  void
03431      */
03432     function registerDefaultLanguageData($table, $rec) {
03433         global $TCA;
03434 
03435             // Add default language:
03436         if ($TCA[$table]['ctrl']['languageField']
03437             && $rec[$TCA[$table]['ctrl']['languageField']] > 0
03438             && $TCA[$table]['ctrl']['transOrigPointerField']
03439             && intval($rec[$TCA[$table]['ctrl']['transOrigPointerField']]) > 0) {
03440 
03441             $lookUpTable = $TCA[$table]['ctrl']['transOrigPointerTable'] ? $TCA[$table]['ctrl']['transOrigPointerTable'] : $table;
03442 
03443                 // Get data formatted:
03444             $this->defaultLanguageData[$table . ':' . $rec['uid']] = t3lib_BEfunc::getRecordWSOL($lookUpTable, intval($rec[$TCA[$table]['ctrl']['transOrigPointerField']]));
03445 
03446                 // Get data for diff:
03447             if ($TCA[$table]['ctrl']['transOrigDiffSourceField']) {
03448                 $this->defaultLanguageData_diff[$table . ':' . $rec['uid']] = unserialize($rec[$TCA[$table]['ctrl']['transOrigDiffSourceField']]);
03449             }
03450 
03451                 // If there are additional preview languages, load information for them also:
03452             $prLang = $this->getAdditionalPreviewLanguages();
03453             foreach ($prLang as $prL) {
03454                 $t8Tools = t3lib_div::makeInstance('t3lib_transl8tools');
03455                 $tInfo = $t8Tools->translationInfo($lookUpTable, intval($rec[$TCA[$table]['ctrl']['transOrigPointerField']]), $prL['uid']);
03456                 if (is_array($tInfo['translations'][$prL['uid']])) {
03457                     $this->additionalPreviewLanguageData[$table . ':' . $rec['uid']][$prL['uid']] = t3lib_BEfunc::getRecordWSOL($table, intval($tInfo['translations'][$prL['uid']]['uid']));
03458                 }
03459             }
03460         }
03461     }
03462 
03463     /**
03464      * Creates language-overlay for a field value
03465      * This means the requested field value will be overridden with the data from the default language.
03466      * Can be used to render read only fields for example.
03467      *
03468      * @param   string      Table name of the record being edited
03469      * @param   string      Field name represented by $item
03470      * @param   array       Record array of the record being edited in current language
03471      * @param   array       Content of $PA['fieldConf']
03472      * @return  string      Unprocessed field value merged with default language data if needed
03473      */
03474     function getLanguageOverlayRawValue($table, $row, $field, $fieldConf) {
03475         global $TCA;
03476 
03477         $value = $row[$field];
03478 
03479         if (is_array($this->defaultLanguageData[$table . ':' . $row['uid']])) {
03480 
03481             if ($fieldConf['l10n_mode'] == 'exclude'
03482                 || ($fieldConf['l10n_mode'] == 'mergeIfNotBlank' && strcmp(trim($this->defaultLanguageData[$table . ':' . $row['uid']][$field]), ''))) {
03483                 $value = $this->defaultLanguageData[$table . ':' . $row['uid']][$field];
03484             }
03485 
03486         }
03487 
03488         return $value;
03489     }
03490 
03491     /**
03492      * Renders the display of default language record content around current field.
03493      * Will render content if any is found in the internal array, $this->defaultLanguageData, depending on registerDefaultLanguageData() being called prior to this.
03494      *
03495      * @param   string      Table name of the record being edited
03496      * @param   string      Field name represented by $item
03497      * @param   array       Record array of the record being edited
03498      * @param   string      HTML of the form field. This is what we add the content to.
03499      * @return  string      Item string returned again, possibly with the original value added to.
03500      * @see getSingleField(), registerDefaultLanguageData()
03501      */
03502     function renderDefaultLanguageContent($table, $field, $row, $item) {
03503         if (is_array($this->defaultLanguageData[$table . ':' . $row['uid']])) {
03504             $dLVal = t3lib_BEfunc::getProcessedValue($table, $field, $this->defaultLanguageData[$table . ':' . $row['uid']][$field], 0, 1);
03505             $fCfg = $GLOBALS['TCA'][$table]['columns'][$field];
03506 
03507                 // Don't show content if it's for IRRE child records:
03508             if ($fCfg['config']['type'] != 'inline') {
03509                 if (strcmp($dLVal, '')) {
03510                     $item .= '<div class="typo3-TCEforms-originalLanguageValue">' . $this->getLanguageIcon($table, $row, 0) .
03511                              $this->previewFieldValue($dLVal, $fCfg, $field) . '&nbsp;</div>';
03512                 }
03513 
03514                 $prLang = $this->getAdditionalPreviewLanguages();
03515                 foreach ($prLang as $prL) {
03516                     $dlVal = t3lib_BEfunc::getProcessedValue($table, $field, $this->additionalPreviewLanguageData[$table . ':' . $row['uid']][$prL['uid']][$field], 0, 1);
03517 
03518                     if (strcmp($dlVal, '')) {
03519                         $item .= '<div class="typo3-TCEforms-originalLanguageValue">' . $this->getLanguageIcon($table, $row, 'v' . $prL['ISOcode']) .
03520                                  $this->previewFieldValue($dlVal, $fCfg, $field) . '&nbsp;</div>';
03521                     }
03522                 }
03523             }
03524         }
03525 
03526         return $item;
03527     }
03528 
03529     /**
03530      * Renders the diff-view of default language record content compared with what the record was originally translated from.
03531      * Will render content if any is found in the internal array, $this->defaultLanguageData, depending on registerDefaultLanguageData() being called prior to this.
03532      *
03533      * @param   string      Table name of the record being edited
03534      * @param   string      Field name represented by $item
03535      * @param   array       Record array of the record being edited
03536      * @param   string      HTML of the form field. This is what we add the content to.
03537      * @return  string      Item string returned again, possibly with the original value added to.
03538      * @see getSingleField(), registerDefaultLanguageData()
03539      */
03540     function renderDefaultLanguageDiff($table, $field, $row, $item) {
03541         if (is_array($this->defaultLanguageData_diff[$table . ':' . $row['uid']])) {
03542 
03543                 // Initialize:
03544             $dLVal = array(
03545                 'old' => $this->defaultLanguageData_diff[$table . ':' . $row['uid']],
03546                 'new' => $this->defaultLanguageData[$table . ':' . $row['uid']],
03547             );
03548 
03549             if (isset($dLVal['old'][$field])) { // There must be diff-data:
03550                 if (strcmp($dLVal['old'][$field], $dLVal['new'][$field])) {
03551 
03552                         // Create diff-result:
03553                     $t3lib_diff_Obj = t3lib_div::makeInstance('t3lib_diff');
03554                     $diffres = $t3lib_diff_Obj->makeDiffDisplay(
03555                         t3lib_BEfunc::getProcessedValue($table, $field, $dLVal['old'][$field], 0, 1),
03556                         t3lib_BEfunc::getProcessedValue($table, $field, $dLVal['new'][$field], 0, 1)
03557                     );
03558 
03559                     $item .= '<div class="typo3-TCEforms-diffBox">' .
03560                              '<div class="typo3-TCEforms-diffBox-header">' . htmlspecialchars($this->getLL('l_changeInOrig')) . ':</div>' .
03561                              $diffres .
03562                              '</div>';
03563                 }
03564             }
03565         }
03566 
03567         return $item;
03568     }
03569 
03570     /**
03571      * Renders the diff-view of vDEF fields in flexforms
03572      *
03573      * @param   string      Table name of the record being edited
03574      * @param   string      Field name represented by $item
03575      * @param   array       Record array of the record being edited
03576      * @param   string      HTML of the form field. This is what we add the content to.
03577      * @return  string      Item string returned again, possibly with the original value added to.
03578      * @see getSingleField(), registerDefaultLanguageData()
03579      */
03580     function renderVDEFDiff($vArray, $vDEFkey) {
03581         if ($GLOBALS['TYPO3_CONF_VARS']['BE']['flexFormXMLincludeDiffBase'] && isset($vArray[$vDEFkey . '.vDEFbase']) && strcmp($vArray[$vDEFkey . '.vDEFbase'], $vArray['vDEF'])) {
03582 
03583                 // Create diff-result:
03584             $t3lib_diff_Obj = t3lib_div::makeInstance('t3lib_diff');
03585             $diffres = $t3lib_diff_Obj->makeDiffDisplay($vArray[$vDEFkey . '.vDEFbase'], $vArray['vDEF']);
03586 
03587             $item .= '<div class="typo3-TCEforms-diffBox">' .
03588                      '<div class="typo3-TCEforms-diffBox-header">' . htmlspecialchars($this->getLL('l_changeInOrig')) . ':</div>' .
03589                      $diffres .
03590                      '</div>';
03591         }
03592 
03593         return $item;
03594     }
03595 
03596 
03597     /************************************************************
03598      *
03599      * Form element helper functions
03600      *
03601      ************************************************************/
03602 
03603     /**
03604      * Prints the selector box form-field for the db/file/select elements (multiple)
03605      *
03606      * @param   string      Form element name
03607      * @param   string      Mode "db", "file" (internal_type for the "group" type) OR blank (then for the "select" type)
03608      * @param   string      Commalist of "allowed"
03609      * @param   array       The array of items. For "select" and "group"/"file" this is just a set of value. For "db" its an array of arrays with table/uid pairs.
03610      * @param   string      Alternative selector box.
03611      * @param   array       An array of additional parameters, eg: "size", "info", "headers" (array with "selector" and "items"), "noBrowser", "thumbnails"
03612      * @param   string      On focus attribute string
03613      * @param   string      $table: (optional) Table name processing for
03614      * @param   string      $field: (optional) Field of table name processing for
03615      * @param   string      $uid:   (optional) uid of table record processing for
03616      * @return  string      The form fields for the selection.
03617      */
03618     function dbFileIcons($fName, $mode, $allowed, $itemArray, $selector = '', $params = array(), $onFocus = '', $table = '', $field = '', $uid = '') {
03619 
03620 
03621         $disabled = '';
03622         if ($this->renderReadonly || $params['readOnly']) {
03623             $disabled = ' disabled="disabled"';
03624         }
03625 
03626             // Sets a flag which means some JavaScript is included on the page to support this element.
03627         $this->printNeededJS['dbFileIcons'] = 1;
03628 
03629             // INIT
03630         $uidList = array();
03631         $opt = array();
03632         $itemArrayC = 0;
03633 
03634             // Creating <option> elements:
03635         if (is_array($itemArray)) {
03636             $itemArrayC = count($itemArray);
03637             switch ($mode) {
03638                 case 'db':
03639                     foreach ($itemArray as $pp) {
03640                         $pRec = t3lib_BEfunc::getRecordWSOL($pp['table'], $pp['id']);
03641                         if (is_array($pRec)) {
03642                             $pTitle = t3lib_BEfunc::getRecordTitle($pp['table'], $pRec, FALSE, TRUE);
03643                             $pUid = $pp['table'] . '_' . $pp['id'];
03644                             $uidList[] = $pUid;
03645                             $opt[] = '<option value="' . htmlspecialchars($pUid) . '">' . htmlspecialchars($pTitle) . '</option>';
03646                         }
03647                     }
03648                 break;
03649                 case 'file_reference':
03650                 case 'file':
03651                     foreach ($itemArray as $item) {
03652                         $itemParts = explode('|', $item);
03653                         $uidList[] = $pUid = $pTitle = $itemParts[0];
03654                         $opt[] = '<option value="' . htmlspecialchars(rawurldecode($itemParts[0])) . '">' . htmlspecialchars(basename(rawurldecode($itemParts[0]))) . '</option>';
03655                     }
03656                 break;
03657                 case 'folder':
03658                     foreach ($itemArray as $pp) {
03659                         $pParts = explode('|', $pp);
03660                         $uidList[] = $pUid = $pTitle = $pParts[0];
03661                         $opt[] = '<option value="' . htmlspecialchars(rawurldecode($pParts[0])) . '">' . htmlspecialchars(rawurldecode($pParts[0])) . '</option>';
03662                     }
03663                 break;
03664                 default:
03665                     foreach ($itemArray as $pp) {
03666                         $pParts = explode('|', $pp, 2);
03667                         $uidList[] = $pUid = $pParts[0];
03668                         $pTitle = $pParts[1];
03669                         $opt[] = '<option value="' . htmlspecialchars(rawurldecode($pUid)) . '">' . htmlspecialchars(rawurldecode($pTitle)) . '</option>';
03670                     }
03671                 break;
03672             }
03673         }
03674 
03675             // Create selector box of the options
03676         $sSize = $params['autoSizeMax'] ? t3lib_div::intInRange($itemArrayC + 1, t3lib_div::intInRange($params['size'], 1), $params['autoSizeMax']) : $params['size'];
03677         if (!$selector) {
03678             $selector = '<select id="' . uniqid('tceforms-multiselect-') . '" ' . ($params['noList'] ? 'style="display: none"' : 'size="' . $sSize . '"' . $this->insertDefStyle('group', 'tceforms-multiselect')) . ' multiple="multiple" name="' . $fName . '_list" ' . $onFocus . $params['style'] . $disabled . '>' . implode('', $opt) . '</select>';
03679         }
03680 
03681 
03682         $icons = array(
03683             'L' => array(),
03684             'R' => array(),
03685         );
03686         if (!$params['readOnly'] && !$params['noList']) {
03687             if (!$params['noBrowser']) {
03688                     // check against inline uniqueness
03689                 $inlineParent = $this->inline->getStructureLevel(-1);
03690                 if (is_array($inlineParent) && $inlineParent['uid']) {
03691                     if ($inlineParent['config']['foreign_table'] == $table && $inlineParent['config']['foreign_unique'] == $field) {
03692                         $objectPrefix = $this->inline->inlineNames['object'] . '[' . $table . ']';
03693                         $aOnClickInline = $objectPrefix . '|inline.checkUniqueElement|inline.setUniqueElement';
03694                         $rOnClickInline = 'inline.revertUnique(\'' . $objectPrefix . '\',null,\'' . $uid . '\');';
03695                     }
03696                 }
03697                 $aOnClick = 'setFormValueOpenBrowser(\'' . $mode . '\',\'' . ($fName . '|||' . $allowed . '|' . $aOnClickInline) . '\'); return false;';
03698                 $icons['R'][] = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">' .
03699                                 t3lib_iconWorks::getSpriteIcon('actions-insert-record', array('title' => htmlspecialchars($this->getLL('l_browse_' . ($mode == 'db' ? 'db' : 'file'))))) .
03700                                 '</a>';
03701             }
03702             if (!$params['dontShowMoveIcons']) {
03703                 if ($sSize >= 5) {
03704                     $icons['L'][] = '<a href="#" onclick="setFormValueManipulate(\'' . $fName . '\',\'Top\'); return false;">' .
03705                                     t3lib_iconWorks::getSpriteIcon('actions-move-to-top', array('title' => htmlspecialchars($this->getLL('l_move_to_top')))) .
03706                                     '</a>';
03707                 }
03708                 $icons['L'][] = '<a href="#" onclick="setFormValueManipulate(\'' . $fName . '\',\'Up\'); return false;">' .
03709                                 t3lib_iconWorks::getSpriteIcon('actions-move-up', array('title' => htmlspecialchars($this->getLL('l_move_up')))) .
03710                                 '</a>';
03711                 $icons['L'][] = '<a href="#" onclick="setFormValueManipulate(\'' . $fName . '\',\'Down\'); return false;">' .
03712                                 t3lib_iconWorks::getSpriteIcon('actions-move-down', array('title' => htmlspecialchars($this->getLL('l_move_down')))) .
03713                                 '</a>';
03714                 if ($sSize >= 5) {
03715                     $icons['L'][] = '<a href="#" onclick="setFormValueManipulate(\'' . $fName . '\',\'Bottom\'); return false;">' .
03716                                     t3lib_iconWorks::getSpriteIcon('actions-move-to-bottom', array('title' => htmlspecialchars($this->getLL('l_move_to_bottom')))) .
03717                                     '</a>';
03718                 }
03719             }
03720 
03721             $clipElements = $this->getClipboardElements($allowed, $mode);
03722             if (count($clipElements)) {
03723                 $aOnClick = '';
03724                 foreach ($clipElements as $elValue) {
03725                     if ($mode == 'db') {
03726                         list($itemTable, $itemUid) = explode('|', $elValue);
03727                         $itemTitle = $GLOBALS['LANG']->JScharCode(t3lib_BEfunc::getRecordTitle($itemTable, t3lib_BEfunc::getRecordWSOL($itemTable, $itemUid)));
03728                         $elValue = $itemTable . '_' . $itemUid;
03729                     } else {
03730                             // 'file', 'file_reference' and 'folder' mode
03731                         $itemTitle = 'unescape(\'' . rawurlencode(basename($elValue)) . '\')';
03732                     }
03733                     $aOnClick .= 'setFormValueFromBrowseWin(\'' . $fName . '\',unescape(\'' . rawurlencode(str_replace('%20', ' ', $elValue)) . '\'),' . $itemTitle . ');';
03734                 }
03735                 $aOnClick .= 'return false;';
03736                 $icons['R'][] = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">' .
03737                                 t3lib_iconWorks::getSpriteIcon('actions-document-paste-into', array('title' => htmlspecialchars(sprintf($this->getLL('l_clipInsert_' . ($mode == 'db' ? 'db' : 'file')), count($clipElements))))) .
03738                                 '</a>';
03739             }
03740             $rOnClick = $rOnClickInline . 'setFormValueManipulate(\'' . $fName . '\',\'Remove\'); return false';
03741             $icons['L'][] = '<a href="#" onclick="' . htmlspecialchars($rOnClick) . '">' .
03742                             t3lib_iconWorks::getSpriteIcon('actions-selection-delete', array('title' => htmlspecialchars($this->getLL('l_remove_selected')))) .
03743                             '</a>';
03744         }
03745         $imagesOnly = FALSE;
03746         if ($params['thumbnails'] && $params['info']) {
03747                 // In case we have thumbnails, check if only images are allowed.
03748                 // In this case, render them below the field, instead of to the right
03749             $allowedExtensionList = t3lib_div::trimExplode(' ', strtolower($params['info']), TRUE);
03750             $imageExtensionList = t3lib_div::trimExplode(',', strtolower($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']), TRUE);
03751             $imagesOnly = TRUE;
03752             foreach ($allowedExtensionList as $allowedExtension) {
03753                 if (!t3lib_div::inArray($imageExtensionList, $allowedExtension)) {
03754                     $imagesOnly = FALSE;
03755                     break;
03756                 }
03757             }
03758         }
03759         if ($imagesOnly) {
03760             $rightbox = '';
03761             $thumbnails = '<div class="imagethumbs">' . $this->wrapLabels($params['thumbnails']) . '</div>';
03762         } else {
03763             $rightbox = $this->wrapLabels($params['thumbnails']);
03764             $thumbnails = '';
03765         }
03766 
03767             // Hook: dbFileIcons_postProcess (requested by FAL-team for use with the "fal" extension)
03768         if (is_array ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['dbFileIcons'])) {
03769             foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['dbFileIcons'] as $classRef) {
03770                 $hookObject = t3lib_div::getUserObj($classRef);
03771 
03772                 if (!($hookObject instanceof t3lib_TCEforms_dbFileIconsHook)) {
03773                     throw new UnexpectedValueException(
03774                         '$hookObject must implement interface t3lib_TCEforms_dbFileIconsHook',
03775                         1290167704
03776                     );
03777                 }
03778 
03779                 $additionalParams = array(
03780                     'mode' => $mode,
03781                     'allowed' => $allowed,
03782                     'itemArray' => $itemArray,
03783                     'onFocus' => $onFocus,
03784                     'table' => $table,
03785                     'field' => $field,
03786                     'uid' => $uid
03787                 );
03788                 $hookObject->dbFileIcons_postProcess($params, $selector, $thumbnails, $icons, $rightbox, $fName, $uidList, $additionalParams, $this);
03789             }
03790         }
03791 
03792         $str = '<table border="0" cellpadding="0" cellspacing="0" width="1">
03793             ' . ($params['headers'] ? '
03794                 <tr>
03795                     <td>' . $this->wrapLabels($params['headers']['selector']) . '</td>
03796                     <td></td>
03797                     <td></td>
03798                     <td>' . ($params['thumbnails'] ? $this->wrapLabels($params['headers']['items']) : '') . '</td>
03799                 </tr>' : '') .
03800                '
03801             <tr>
03802                 <td valign="top">' .
03803                $selector .
03804                $thumbnails .
03805                ($params['noList'] ? '' : '<span class="filetypes">' . $this->wrapLabels($params['info'])) .
03806                '</span></td>
03807                 <td valign="top" class="icons">' .
03808                implode('<br />', $icons['L']) . '</td>
03809                 <td valign="top" class="icons">' .
03810                implode('<br />', $icons['R']) . '</td>
03811                 <td valign="top" class="thumbnails">' .
03812                $rightbox .
03813                '</td>
03814             </tr>
03815         </table>';
03816 
03817             // Creating the hidden field which contains the actual value as a comma list.
03818         $str .= '<input type="hidden" name="' . $fName . '" value="' . htmlspecialchars(implode(',', $uidList)) . '" />';
03819 
03820         return $str;
03821     }
03822 
03823     /**
03824      * Returns array of elements from clipboard to insert into GROUP element box.
03825      *
03826      * @param   string      Allowed elements, Eg "pages,tt_content", "gif,jpg,jpeg,png"
03827      * @param   string      Mode of relations: "db" or "file"
03828      * @return  array       Array of elements in values (keys are insignificant), if none found, empty array.
03829      */
03830     function getClipboardElements($allowed, $mode) {
03831 
03832         $output = array();
03833 
03834         if (is_object($this->clipObj)) {
03835             switch ($mode) {
03836                 case 'file_reference':
03837                 case 'file':
03838                     $elFromTable = $this->clipObj->elFromTable('_FILE');
03839                     $allowedExts = t3lib_div::trimExplode(',', $allowed, 1);
03840 
03841                     if ($allowedExts) { // If there are a set of allowed extensions, filter the content:
03842                         foreach ($elFromTable as $elValue) {
03843                             $pI = pathinfo($elValue);
03844                             $ext = strtolower($pI['extension']);
03845                             if (in_array($ext, $allowedExts)) {
03846                                 $output[] = $elValue;
03847                             }
03848                         }
03849                     } else { // If all is allowed, insert all: (This does NOT respect any disallowed extensions, but those will be filtered away by the backend TCEmain)
03850                         $output = $elFromTable;
03851                     }
03852                 break;
03853                 case 'db':
03854                     $allowedTables = t3lib_div::trimExplode(',', $allowed, 1);
03855                     if (!strcmp(trim($allowedTables[0]), '*')) { // All tables allowed for relation:
03856                         $output = $this->clipObj->elFromTable('');
03857                     } else { // Only some tables, filter them:
03858                         foreach ($allowedTables as $tablename) {
03859                             $elFromTable = $this->clipObj->elFromTable($tablename);
03860                             $output = array_merge($output, $elFromTable);
03861                         }
03862                     }
03863                     $output = array_keys($output);
03864                 break;
03865             }
03866         }
03867 
03868         return $output;
03869     }
03870 
03871     /**
03872      * Wraps the icon of a relation item (database record or file) in a link opening the context menu for the item.
03873      * Icons will be wrapped only if $this->enableClickMenu is set. This must be done only if a global SOBE object exists and if the necessary JavaScript for displaying the context menus has been added to the page properties.
03874      *
03875      * @param   string      The icon HTML to wrap
03876      * @param   string      Table name (eg. "pages" or "tt_content") OR the absolute path to the file
03877      * @param   integer     The uid of the record OR if file, just blank value.
03878      * @return  string      HTML
03879      */
03880     function getClickMenu($str, $table, $uid = '') {
03881         if ($this->enableClickMenu) {
03882             $onClick = $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($str, $table, $uid, 1, '', '+copy,info,edit,view', TRUE);
03883             return '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $str . '</a>';
03884         }
03885     }
03886 
03887     /**
03888      * Rendering wizards for form fields.
03889      *
03890      * @param   array       Array with the real item in the first value, and an alternative item in the second value.
03891      * @param   array       The "wizard" key from the config array for the field (from TCA)
03892      * @param   string      Table name
03893      * @param   array       The record array
03894      * @param   string      The field name
03895      * @param   array       Additional configuration array. (passed by reference!)
03896      * @param   string      The field name
03897      * @param   array       Special configuration if available.
03898      * @param   boolean     Whether the RTE could have been loaded.
03899      * @return  string      The new item value.
03900      */
03901     function renderWizards($itemKinds, $wizConf, $table, $row, $field, &$PA, $itemName, $specConf, $RTE = 0) {
03902 
03903             // Init:
03904         $fieldChangeFunc = $PA['fieldChangeFunc'];
03905         $item = $itemKinds[0];
03906         $outArr = array();
03907         $colorBoxLinks = array();
03908         $fName = '[' . $table . '][' . $row['uid'] . '][' . $field . ']';
03909         $md5ID = 'ID' . t3lib_div::shortmd5($itemName);
03910         $listFlag = '_list';
03911 
03912         $prefixOfFormElName = 'data[' . $table . '][' . $row['uid'] . '][' . $field . ']';
03913         if (t3lib_div::isFirstPartOfStr($PA['itemFormElName'], $prefixOfFormElName)) {
03914             $flexFormPath = str_replace('][', '/', substr($PA['itemFormElName'], strlen($prefixOfFormElName) + 1, -1));
03915         }
03916 
03917             // Manipulate the field name (to be the true form field name) and remove a suffix-value if the item is a selector box with renderMode "singlebox":
03918         if ($PA['fieldConf']['config']['form_type'] == 'select') {
03919             if ($PA['fieldConf']['config']['maxitems'] <= 1) { // Single select situation:
03920                 $listFlag = '';
03921             } elseif ($PA['fieldConf']['config']['renderMode'] == 'singlebox') {
03922                 $itemName .= '[]';
03923                 $listFlag = '';
03924             }
03925         }
03926 
03927             // traverse wizards:
03928         if (is_array($wizConf) && !$this->disableWizards) {
03929             $parametersOfWizards =& $specConf['wizards']['parameters'];
03930 
03931             foreach ($wizConf as $wid => $wConf) {
03932                 if (substr($wid, 0, 1) != '_'
03933                     && (!$wConf['enableByTypeConfig'] || is_array($parametersOfWizards) && in_array($wid, $parametersOfWizards))
03934                     && ($RTE || !$wConf['RTEonly'])
03935                 ) {
03936 
03937                         // Title / icon:
03938                     $iTitle = htmlspecialchars($this->sL($wConf['title']));
03939                     if ($wConf['icon']) {
03940                         $icon = $this->getIconHtml($wConf['icon'], $iTitle, $iTitle);
03941                     } else {
03942                         $icon = $iTitle;
03943                     }
03944 
03945                         //
03946                     switch ((string) $wConf['type']) {
03947                         case 'userFunc':
03948                         case 'script':
03949                         case 'popup':
03950                         case 'colorbox':
03951                             if (!$wConf['notNewRecords'] || t3lib_div::testInt($row['uid'])) {
03952 
03953                                     // Setting &P array contents:
03954                                 $params = array();
03955                                 $params['params'] = $wConf['params'];
03956                                 $params['exampleImg'] = $wConf['exampleImg'];
03957                                 $params['table'] = $table;
03958                                 $params['uid'] = $row['uid'];
03959                                 $params['pid'] = $row['pid'];
03960                                 $params['field'] = $field;
03961                                 $params['flexFormPath'] = $flexFormPath;
03962                                 $params['md5ID'] = $md5ID;
03963                                 $params['returnUrl'] = $this->thisReturnUrl();
03964 
03965                                     // Resolving script filename and setting URL.
03966                                 if (!strcmp(substr($wConf['script'], 0, 4), 'EXT:')) {
03967                                     $wScript = t3lib_div::getFileAbsFileName($wConf['script']);
03968                                     if ($wScript) {
03969                                         $wScript = '../' . substr($wScript, strlen(PATH_site));
03970                                     } else {
03971                                         break;
03972                                     }
03973                                 } else {
03974                                     $wScript = $wConf['script'];
03975                                 }
03976                                 $url = $this->backPath . $wScript . (strstr($wScript, '?') ? '' : '?');
03977 
03978                                     // If there is no script and the type is "colorbox", break right away:
03979                                 if ((string) $wConf['type'] == 'colorbox' && !$wConf['script']) {
03980                                     break;
03981                                 }
03982 
03983                                     // If "script" type, create the links around the icon:
03984                                 if ((string) $wConf['type'] == 'script') {
03985                                     $aUrl = $url . t3lib_div::implodeArrayForUrl('', array('P' => $params));
03986                                     $outArr[] = '<a href="' . htmlspecialchars($aUrl) . '" onclick="' . $this->blur() . 'return !TBE_EDITOR.isFormChanged();">' .
03987                                                 $icon .
03988                                                 '</a>';
03989                                 } else {
03990 
03991                                         // ... else types "popup", "colorbox" and "userFunc" will need additional parameters:
03992                                     $params['formName'] = $this->formName;
03993                                     $params['itemName'] = $itemName;
03994                                     $params['fieldChangeFunc'] = $fieldChangeFunc;
03995                                     $params['fieldChangeFuncHash'] = t3lib_div::hmac(serialize($fieldChangeFunc));
03996 
03997                                     switch ((string) $wConf['type']) {
03998                                         case 'popup':
03999                                         case 'colorbox':
04000                                                 // Current form value is passed as P[currentValue]!
04001                                             $addJS = $wConf['popup_onlyOpenIfSelected'] ? 'if (!TBE_EDITOR.curSelected(\'' . $itemName . $listFlag . '\')){alert(' . $GLOBALS['LANG']->JScharCode($this->getLL('m_noSelItemForEdit')) . '); return false;}' : '';
04002                                             $curSelectedValues = '+\'&P[currentSelectedValues]=\'+TBE_EDITOR.curSelected(\'' . $itemName . $listFlag . '\')';
04003                                             $aOnClick = $this->blur() .
04004                                                         $addJS .
04005                                                         'vHWin=window.open(\'' . $url . t3lib_div::implodeArrayForUrl('', array('P' => $params)) . '\'+\'&P[currentValue]=\'+TBE_EDITOR.rawurlencode(' . $this->elName($itemName) . '.value,200)' . $curSelectedValues . ',\'popUp' . $md5ID . '\',\'' . $wConf['JSopenParams'] . '\');' .
04006                                                         'vHWin.focus();return false;';
04007                                                 // Setting "colorBoxLinks" - user LATER to wrap around the color box as well:
04008                                             $colorBoxLinks = Array('<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">', '</a>');
04009                                             if ((string) $wConf['type'] == 'popup') {
04010                                                 $outArr[] = $colorBoxLinks[0] . $icon . $colorBoxLinks[1];
04011                                             }
04012                                         break;
04013                                         case 'userFunc':
04014                                             $params['item'] = &$item; // Reference set!
04015                                             $params['icon'] = $icon;
04016                                             $params['iTitle'] = $iTitle;
04017                                             $params['wConf'] = $wConf;
04018                                             $params['row'] = $row;
04019                                             $outArr[] = t3lib_div::callUserFunction($wConf['userFunc'], $params, $this);
04020                                         break;
04021                                     }
04022                                 }
04023 
04024                                     // Hide the real form element?
04025                                 if (is_array($wConf['hideParent']) || $wConf['hideParent']) {
04026                                     $item = $itemKinds[1]; // Setting the item to a hidden-field.
04027                                     if (is_array($wConf['hideParent'])) {
04028                                         $item .= $this->getSingleField_typeNone_render($wConf['hideParent'], $PA['itemFormElValue']);
04029                                     }
04030                                 }
04031                             }
04032                         break;
04033                         case 'select':
04034                             $fieldValue = array('config' => $wConf);
04035                             $TSconfig = $this->setTSconfig($table, $row);
04036                             $TSconfig[$field] = $TSconfig[$field]['wizards.'][$wid . '.'];
04037                             $selItems = $this->addSelectOptionsToItemArray($this->initItemArray($fieldValue), $fieldValue, $TSconfig, $field);
04038 
04039                             $opt = array();
04040                             $opt[] = '<option>' . $iTitle . '</option>';
04041                             foreach ($selItems as $p) {
04042                                 $opt[] = '<option value="' . htmlspecialchars($p[1]) . '">' . htmlspecialchars($p[0]) . '</option>';
04043                             }
04044                             if ($wConf['mode'] == 'append') {
04045                                 $assignValue = $this->elName($itemName) . '.value=\'\'+this.options[this.selectedIndex].value+' . $this->elName($itemName) . '.value';
04046                             } elseif ($wConf['mode'] == 'prepend') {
04047                                 $assignValue = $this->elName($itemName) . '.value+=\'\'+this.options[this.selectedIndex].value';
04048                             } else {
04049                                 $assignValue = $this->elName($itemName) . '.value=this.options[this.selectedIndex].value';
04050                             }
04051                             $sOnChange = $assignValue . ';this.blur();this.selectedIndex=0;' . implode('', $fieldChangeFunc);
04052                             $outArr[] = '<select id="' . uniqid('tceforms-select-') . '" class="tceforms-select tceforms-wizardselect" name="_WIZARD' . $fName . '" onchange="' . htmlspecialchars($sOnChange) . '">' . implode('', $opt) . '</select>';
04053                         break;
04054                         case 'suggest':
04055                             if (isset($PA['fieldTSConfig']['suggest.']['default.']['hide']) &&
04056                                 ((bool) $PA['fieldTSConfig']['suggest.']['default.']['hide'] == TRUE)) {
04057                                 break;
04058                             }
04059                             $outArr[] = $this->suggest->renderSuggestSelector($PA['itemFormElName'], $table, $field, $row, $PA);
04060                         break;
04061                     }
04062 
04063                         // Color wizard colorbox:
04064                     if ((string) $wConf['type'] == 'colorbox') {
04065                         $dim = t3lib_div::intExplode('x', $wConf['dim']);
04066                         $dX = t3lib_div::intInRange($dim[0], 1, 200, 20);
04067                         $dY = t3lib_div::intInRange($dim[1], 1, 200, 20);
04068                         $color = $PA['itemFormElValue'] ? ' bgcolor="' . htmlspecialchars($PA['itemFormElValue']) . '"' : '';
04069                         $outArr[] = '<table border="0" cellpadding="0" cellspacing="0" id="' . $md5ID . '"' . $color . ' style="' . htmlspecialchars($wConf['tableStyle']) . '">
04070                                     <tr>
04071                                         <td>' .
04072                                     $colorBoxLinks[0] . '<img ' .
04073                                     t3lib_iconWorks::skinImg($this->backPath,
04074                                                              (strlen(trim($color)) == 0 || strcmp(trim($color), '0') == 0) ? 'gfx/colorpicker_empty.png' : 'gfx/colorpicker.png',
04075                                                              'width="' . $dX . '" height="' . $dY . '"' . t3lib_BEfunc::titleAltAttrib(trim($iTitle . ' ' . $PA['itemFormElValue'])) . ' border="0"') .
04076                                     '>' . $colorBoxLinks[1] .
04077                                     '</td>
04078                                     </tr>
04079                                 </table>';
04080                     }
04081                 }
04082             }
04083 
04084                 // For each rendered wizard, put them together around the item.
04085             if (count($outArr)) {
04086                 if ($wizConf['_HIDDENFIELD']) {
04087                     $item = $itemKinds[1];
04088                 }
04089 
04090                 $outStr = '';
04091                 $vAlign = $wizConf['_VALIGN'] ? ' style="vertical-align:' . $wizConf['_VALIGN'] . '"' : '';
04092                 if (count($outArr) > 1 || $wizConf['_PADDING']) {
04093                     $dist = intval($wizConf['_DISTANCE']);
04094                     if ($wizConf['_VERTICAL']) {
04095                         $dist = $dist ? '<tr><td><img src="clear.gif" width="1" height="' . $dist . '" alt="" /></td></tr>' : '';
04096                         $outStr = '<tr><td>' . implode('</td></tr>' . $dist . '<tr><td>', $outArr) . '</td></tr>';
04097                     } else {
04098                         $dist = $dist ? '<td><img src="clear.gif" height="1" width="' . $dist . '" alt="" /></td>' : '';
04099                         $outStr = '<tr><td' . $vAlign . '>' . implode('</td>' . $dist . '<td' . $vAlign . '>', $outArr) . '</td></tr>';
04100                     }
04101                     $outStr = '<table border="0" cellpadding="' . intval($wizConf['_PADDING']) . '" cellspacing="' . intval($wizConf['_PADDING']) . '">' . $outStr . '</table>';
04102                 } else {
04103                     $outStr = implode('', $outArr);
04104                 }
04105 
04106                 if (!strcmp($wizConf['_POSITION'], 'left')) {
04107                     $outStr = '<tr><td' . $vAlign . '>' . $outStr . '</td><td' . $vAlign . '>' . $item . '</td></tr>';
04108                 } elseif (!strcmp($wizConf['_POSITION'], 'top')) {
04109                     $outStr = '<tr><td>' . $outStr . '</td></tr><tr><td>' . $item . '</td></tr>';
04110                 } elseif (!strcmp($wizConf['_POSITION'], 'bottom')) {
04111                     $outStr = '<tr><td>' . $item . '</td></tr><tr><td>' . $outStr . '</td></tr>';
04112                 } else {
04113                     $outStr = '<tr><td' . $vAlign . '>' . $item . '</td><td' . $vAlign . '>' . $outStr . '</td></tr>';
04114                 }
04115 
04116                 $item = '<table border="0" cellpadding="0" cellspacing="0">' . $outStr . '</table>';
04117             }
04118         }
04119         return $item;
04120     }
04121 
04122     /**
04123      * Get icon (for example for selector boxes)
04124      *
04125      * @param   string      Icon reference
04126      * @return  array       Array with two values; the icon file reference (relative to PATH_typo3 minus backPath), the icon file information array (getimagesize())
04127      */
04128     function getIcon($icon) {
04129         if (substr($icon, 0, 4) == 'EXT:') {
04130             $file = t3lib_div::getFileAbsFileName($icon);
04131             if ($file) {
04132                 $file = substr($file, strlen(PATH_site));
04133                 $selIconFile = $this->backPath . '../' . $file;
04134                 $selIconInfo = @getimagesize(PATH_site . $file);
04135             }
04136         } elseif (substr($icon, 0, 3) == '../') {
04137             $selIconFile = $this->backPath . t3lib_div::resolveBackPath($icon);
04138             $selIconInfo = @getimagesize(PATH_site . t3lib_div::resolveBackPath(substr($icon, 3)));
04139         } elseif (substr($icon, 0, 4) == 'ext/' || substr($icon, 0, 7) == 'sysext/') {
04140             $selIconFile = $this->backPath . $icon;
04141             $selIconInfo = @getimagesize(PATH_typo3 . $icon);
04142         } else {
04143             $selIconFile = t3lib_iconWorks::skinImg($this->backPath, 'gfx/' . $icon, '', 1);
04144             $iconPath = substr($selIconFile, strlen($this->backPath));
04145             $selIconInfo = @getimagesize(PATH_typo3 . $iconPath);
04146         }
04147         return array($selIconFile, $selIconInfo);
04148     }
04149 
04150     /**
04151      * Renders the $icon, supports a filename for skinImg or sprite-icon-name
04152      * @param $icon the icon passed, could be a file-reference or a sprite Icon name
04153      * @param string $alt alt attribute of the icon returned
04154      * @param string $title title attribute of the icon return
04155      * @return an tag representing to show the asked icon
04156      */
04157     protected function getIconHtml($icon, $alt = '', $title = '') {
04158         $iconArray = $this->getIcon($icon);
04159         if (is_file(t3lib_div::resolveBackPath(PATH_typo3 . PATH_typo3_mod . $iconArray[0]))) {
04160             return '<img src="' . $iconArray[0] . '" alt="' . $alt . '" ' . ($title ? 'title="' . $title . '"' : '') . ' />';
04161         } else {
04162             return t3lib_iconWorks::getSpriteIcon($icon, array('alt'=> $alt, 'title'=> $title));
04163         }
04164     }
04165 
04166     /**
04167      * Creates style attribute content for option tags in a selector box, primarily setting it up to show the icon of an element as background image (works in mozilla)
04168      *
04169      * @param   string      Icon string for option item
04170      * @return  string      Style attribute content, if any
04171      */
04172     function optionTagStyle($iconString) {
04173         if ($iconString) {
04174             list($selIconFile, $selIconInfo) = $this->getIcon($iconString);
04175 
04176             $padLeft = $selIconInfo[0] + 4;
04177 
04178             if ($padLeft >= 18 && $padLeft <= 24) {
04179                 $padLeft = 22; // In order to get the same padding for all option tags even if icon sizes differ a little, set it to 22 if it was between 18 and 24 pixels
04180             }
04181 
04182             $padTop = t3lib_div::intInRange(($selIconInfo[1] - 12) / 2, 0);
04183             $styleAttr = 'background: #fff url(' . $selIconFile . ') 0% 50% no-repeat; height: ' . t3lib_div::intInRange(($selIconInfo[1] + 2) - $padTop, 0) . 'px; padding-top: ' . $padTop . 'px; padding-left: ' . $padLeft . 'px;';
04184             return $styleAttr;
04185         }
04186     }
04187 
04188     /**
04189      * Creates style attribute content for optgroup tags in a selector box, primarily setting it up to show the icon of an element as background image (works in mozilla).
04190      *
04191      * @param   string      Icon string for option item
04192      * @return  string      Style attribute content, if any
04193      */
04194     function optgroupTagStyle($iconString) {
04195         if ($iconString) {
04196             list($selIconFile, $selIconInfo) = $this->getIcon($iconString);
04197 
04198             $padLeft = $selIconInfo[0] + 4;
04199 
04200             if($padLeft >= 18 && $padLeft <= 24) {
04201                     // In order to get the same padding for all option tags even if icon sizes differ a little,
04202                     // set it to 22, if it was between 18 and 24 pixels.
04203                 $padLeft = 22;
04204             }
04205             $padTop = t3lib_div::intInRange(($selIconInfo[1] - 12) / 2, 0);
04206 
04207             return 'background: #ffffff url(' . $selIconFile . ') 0 0 no-repeat; padding-top: ' . $padTop . 'px; padding-left: ' . $padLeft . 'px;';
04208         }
04209     }
04210 
04211     /**
04212      * Extracting values from a value/label list (as made by transferData class)
04213      *
04214      * @param   string      Value string where values are comma separated, intermixed with labels and rawurlencoded (this is what is delivered to TCEforms normally!)
04215      * @param   array       Values in an array
04216      * @return  array       Input string exploded with comma and for each value only the label part is set in the array. Keys are numeric
04217      */
04218     function extractValuesOnlyFromValueLabelList($itemFormElValue) {
04219             // Get values of selected items:
04220         $itemArray = t3lib_div::trimExplode(',', $itemFormElValue, 1);
04221         foreach ($itemArray as $tk => $tv) {
04222             $tvP = explode('|', $tv, 2);
04223             $tvP[0] = rawurldecode($tvP[0]);
04224 
04225             $itemArray[$tk] = $tvP[0];
04226         }
04227         return $itemArray;
04228     }
04229 
04230     /**
04231      * Wraps a string with a link to the palette.
04232      *
04233      * @param   string      The string to wrap in an A-tag
04234      * @param   string      The table name for which to open the palette.
04235      * @param   array       The palette pointer.
04236      * @param   integer     The record array
04237      */
04238     function wrapOpenPalette($header, $table, $row, $palette, $retFunc) {
04239         $id = 'TCEFORMS_' . $table . '_' . $palette . '_' . $row['uid'];
04240         $res = '<a href="#" onclick="TBE_EDITOR.toggle_display_states(\'' . $id . '\',\'block\',\'none\'); return false;" >' . $header . '</a>';
04241         return array($res, '');
04242     }
04243 
04244     /**
04245      * Add the id and the style property to the field palette
04246      *
04247      * @param   string      Palette Code
04248      * @param   string      The table name for which to open the palette.
04249      * @param   string      Palette ID
04250      * @param   string      The record array
04251      * @return  boolean     is collapsed
04252      */
04253     function wrapPaletteField($code, $table, $row, $palette, $collapsed) {
04254         $display = $collapsed ? 'none' : 'block';
04255         $id = 'TCEFORMS_' . $table . '_' . $palette . '_' . $row['uid'];
04256         $code = '<div id="' . $id . '" style="display:' . $display . ';" >' . $code . '</div>';
04257         return $code;
04258     }
04259 
04260     /**
04261      * Creates checkbox parameters
04262      *
04263      * @param   string      Form element name
04264      * @param   integer     The value of the checkbox (representing checkboxes with the bits)
04265      * @param   integer     Checkbox # (0-9?)
04266      * @param   integer     Total number of checkboxes in the array.
04267      * @param   string      Additional JavaScript for the onclick handler.
04268      * @return  string      The onclick attribute + possibly the checked-option set.
04269      */
04270     function checkBoxParams($itemName, $thisValue, $c, $iCount, $addFunc = '') {
04271         $onClick = $this->elName($itemName) . '.value=this.checked?(' . $this->elName($itemName) . '.value|' . pow(2, $c) . '):(' . $this->elName($itemName) . '.value&' . (pow(2, $iCount) - 1 - pow(2, $c)) . ');' .
04272                    $addFunc;
04273         $str = ' onclick="' . htmlspecialchars($onClick) . '"' .
04274                (($thisValue & pow(2, $c)) ? ' checked="checked"' : '');
04275         return $str;
04276     }
04277 
04278     /**
04279      * Returns element reference for form element name
04280      *
04281      * @param   string      Form element name
04282      * @return  string      Form element reference (JS)
04283      */
04284     function elName($itemName) {
04285         return 'document.' . $this->formName . "['" . $itemName . "']";
04286     }
04287 
04288     /**
04289      * Returns 'this.blur();' string, if supported.
04290      *
04291      * @return  string      If the current browser supports styles, the string 'this.blur();' is returned.
04292      */
04293     function blur() {
04294         return $GLOBALS['CLIENT']['FORMSTYLE'] ? 'this.blur();' : '';
04295     }
04296 
04297     /**
04298      * Returns the "returnUrl" of the form. Can be set externally or will be taken from "t3lib_div::linkThisScript()"
04299      *
04300      * @return  string      Return URL of current script
04301      */
04302     function thisReturnUrl() {
04303         return $this->returnUrl ? $this->returnUrl : t3lib_div::linkThisScript();
04304     }
04305 
04306     /**
04307      * Returns the form field for a single HIDDEN field.
04308      * (Not used anywhere...?)
04309      *
04310      * @param   string      Table name
04311      * @param   string      Field name
04312      * @param   array       The row
04313      * @return  string      The hidden-field <input> tag.
04314      */
04315     function getSingleHiddenField($table, $field, $row) {
04316         global $TCA;
04317         $out = '';
04318         t3lib_div::loadTCA($table);
04319         if ($TCA[$table]['columns'][$field]) {
04320 
04321             $uid = $row['uid'];
04322             $itemName = $this->prependFormFieldNames . '[' . $table . '][' . $uid . '][' . $field . ']';
04323             $itemValue = $row[$field];
04324             $item .= '<input type="hidden" name="' . $itemName . '" value="' . htmlspecialchars($itemValue) . '" />';
04325             $out = $item;
04326         }
04327         return $out;
04328     }
04329 
04330     /**
04331      * Returns parameters to set the width for a <input>/<textarea>-element
04332      *
04333      * @param   integer     The abstract size value (1-48)
04334      * @param   boolean     If this is for a text area.
04335      * @return  string      Either a "style" attribute string or "cols"/"size" attribute string.
04336      */
04337     function formWidth($size = 48, $textarea = 0) {
04338         $widthAndStyleAttributes = '';
04339         $fieldWidthAndStyle = $this->formWidthAsArray($size, $textarea);
04340 
04341         if (!$GLOBALS['CLIENT']['FORMSTYLE']) {
04342                 // If not setting the width by style-attribute
04343             $widthAndStyleAttributes = ' ' . $fieldWidthAndStyle['width'];
04344         } else {
04345                 // Setting width by style-attribute. 'cols' MUST be avoided with NN6+
04346             $widthAndStyleAttributes = ' style="' . htmlspecialchars($fieldWidthAndStyle['style']) . '"';
04347 
04348             if ($fieldWidthAndStyle['class']) {
04349                 $widthAndStyleAttributes .= ' class="' . htmlspecialchars($fieldWidthAndStyle['class']) . '"';
04350             }
04351         }
04352 
04353         return $widthAndStyleAttributes;
04354     }
04355 
04356     /**
04357      * Returns parameters to set the width for a <input>/<textarea>-element
04358      *
04359      * @param   integer     The abstract size value (1-48)
04360      * @param   boolean     If set, calculates sizes for a text area.
04361      * @return  array       An array containing style, class, and width attributes.
04362      */
04363     protected function formWidthAsArray($size = 48, $textarea = FALSE) {
04364         $fieldWidthAndStyle = array('style' => '', 'class' => '', 'width' => '');
04365 
04366         if ($this->docLarge) {
04367             $size = round($size * $this->form_largeComp);
04368         }
04369 
04370         $widthAttribute = $textarea ? 'cols' : 'size';
04371         if (!$GLOBALS['CLIENT']['FORMSTYLE']) {
04372                 // If not setting the width by style-attribute
04373             $fieldWidthAndStyle['width'] = $widthAttribute . '="' . $size . '"';
04374         } else {
04375                 // Setting width by style-attribute. 'cols' MUST be avoided with NN6+
04376             $widthInPixels = ceil($size * $this->form_rowsToStylewidth);
04377             $fieldWidthAndStyle['style'] = 'width: ' . $widthInPixels . 'px; '
04378                                            . $this->defStyle
04379                                            . $this->formElStyle($textarea ? 'text' : 'input');
04380 
04381             $fieldWidthAndStyle['class'] = $this->formElClass($textarea ? 'text' : 'input');
04382         }
04383 
04384         return $fieldWidthAndStyle;
04385     }
04386 
04387     /**
04388      * Returns parameters to set with for a textarea field
04389      *
04390      * @param   integer     The abstract width (1-48)
04391      * @param   string      Empty or "off" (text wrapping in the field or not)
04392      * @return  string      The "cols" attribute string (or style from formWidth())
04393      * @see formWidth()
04394      */
04395     function formWidthText($size = 48, $wrap = '') {
04396         $wTags = $this->formWidth($size, 1);
04397             // Netscape 6+ seems to have this ODD problem where there WILL ALWAYS be wrapping with the cols-attribute set and NEVER without the col-attribute...
04398         if (strtolower(trim($wrap)) != 'off' && $GLOBALS['CLIENT']['BROWSER'] == 'net' && $GLOBALS['CLIENT']['VERSION'] >= 5) {
04399             $wTags .= ' cols="' . $size . '"';
04400         }
04401         return $wTags;
04402     }
04403 
04404     /**
04405      * Get style CSS values for the current field type.
04406      *
04407      * @param   string      Field type (eg. "check", "radio", "select")
04408      * @return  string      CSS attributes
04409      * @see formElStyleClassValue()
04410      */
04411     function formElStyle($type) {
04412         return $this->formElStyleClassValue($type);
04413     }
04414 
04415     /**
04416      * Get class attribute value for the current field type.
04417      *
04418      * @param   string      Field type (eg. "check", "radio", "select")
04419      * @return  string      CSS attributes
04420      * @see formElStyleClassValue()
04421      */
04422     function formElClass($type) {
04423         return $this->formElStyleClassValue($type, TRUE);
04424     }
04425 
04426     /**
04427      * Get style CSS values for the current field type.
04428      *
04429      * @param   string      Field type (eg. "check", "radio", "select")
04430      * @param   boolean     If set, will return value only if prefixed with CLASS, otherwise must not be prefixed "CLASS"
04431      * @return  string      CSS attributes
04432      */
04433     function formElStyleClassValue($type, $class = FALSE) {
04434             // Get value according to field:
04435         if (isset($this->fieldStyle[$type])) {
04436             $style = trim($this->fieldStyle[$type]);
04437         } else {
04438             $style = trim($this->fieldStyle['all']);
04439         }
04440 
04441             // Check class prefixed:
04442         if (substr($style, 0, 6) == 'CLASS:') {
04443             $out = $class ? trim(substr($style, 6)) : '';
04444         } else {
04445             $out = !$class ? $style : '';
04446         }
04447 
04448         return $out;
04449     }
04450 
04451     /**
04452      * Return default "style" / "class" attribute line.
04453      *
04454      * @param   string      Field type (eg. "check", "radio", "select")
04455      * @param   string      Additional class(es) to be added
04456      * @return  string      CSS attributes
04457      */
04458     function insertDefStyle($type, $additionalClass = '') {
04459         $out = '';
04460 
04461         $style = trim($this->defStyle . $this->formElStyle($type));
04462         $out .= $style ? ' style="' . htmlspecialchars($style) . '"' : '';
04463 
04464         $class = $this->formElClass($type);
04465         $classAttributeValue = join(' ', array_filter(array($class, $additionalClass)));
04466         $out .= $classAttributeValue ? ' class="' . htmlspecialchars($classAttributeValue) . '"' : '';
04467 
04468         return $out;
04469     }
04470 
04471     /**
04472      * Create dynamic tab menu
04473      *
04474      * @param   array       Parts for the tab menu, fed to template::getDynTabMenu()
04475      * @param   string      ID string for the tab menu
04476      * @param   integer     If set to '1' empty tabs will be removed, If set to '2' empty tabs will be disabled
04477      * @return  string      HTML for the menu
04478      */
04479     function getDynTabMenu($parts, $idString, $dividersToTabsBehaviour = 1) {
04480         if (is_object($GLOBALS['TBE_TEMPLATE'])) {
04481             $GLOBALS['TBE_TEMPLATE']->backPath = $this->backPath;
04482             return $GLOBALS['TBE_TEMPLATE']->getDynTabMenu($parts, $idString, 0, FALSE, 0, 1, FALSE, 1, $dividersToTabsBehaviour);
04483         } else {
04484             $output = '';
04485             foreach ($parts as $singlePad) {
04486                 $output .= '
04487                 <h3>' . htmlspecialchars($singlePad['label']) . '</h3>
04488                 ' . ($singlePad['description'] ? '<p class="c-descr">' . nl2br(htmlspecialchars($singlePad['description'])) . '</p>' : '') . '
04489                 ' . $singlePad['content'];
04490             }
04491 
04492             return '<div class="typo3-dyntabmenu-divs">' . $output . '</div>';
04493         }
04494     }
04495 
04496 
04497     /************************************************************
04498      *
04499      * Item-array manipulation functions (check/select/radio)
04500      *
04501      ************************************************************/
04502 
04503     /**
04504      * Initialize item array (for checkbox, selectorbox, radio buttons)
04505      * Will resolve the label value.
04506      *
04507      * @param   array       The "columns" array for the field (from TCA)
04508      * @return  array       An array of arrays with three elements; label, value, icon
04509      */
04510     function initItemArray($fieldValue) {
04511         $items = array();
04512         if (is_array($fieldValue['config']['items'])) {
04513             foreach ($fieldValue['config']['items'] as $itemValue) {
04514                 $items[] = array($this->sL($itemValue[0]), $itemValue[1], $itemValue[2]);
04515             }
04516         }
04517         return $items;
04518     }
04519 
04520     /**
04521      * Merges items into an item-array
04522      *
04523      * @param   array       The existing item array
04524      * @param   array       An array of items to add. NOTICE: The keys are mapped to values, and the values and mapped to be labels. No possibility of adding an icon.
04525      * @return  array       The updated $item array
04526      */
04527     function addItems($items, $iArray) {
04528         global $TCA;
04529         if (is_array($iArray)) {
04530             foreach ($iArray as $value => $label) {
04531                 $items[] = array($this->sl($label), $value);
04532             }
04533         }
04534         return $items;
04535     }
04536 
04537     /**
04538      * Perform user processing of the items arrays of checkboxes, selectorboxes and radio buttons.
04539      *
04540      * @param   array       The array of items (label,value,icon)
04541      * @param   array       The "itemsProcFunc." from fieldTSconfig of the field.
04542      * @param   array       The config array for the field.
04543      * @param   string      Table name
04544      * @param   array       Record row
04545      * @param   string      Field name
04546      * @return  array       The modified $items array
04547      */
04548     function procItems($items, $iArray, $config, $table, $row, $field) {
04549         global $TCA;
04550 
04551         $params = array();
04552         $params['items'] = &$items;
04553         $params['config'] = $config;
04554         $params['TSconfig'] = $iArray;
04555         $params['table'] = $table;
04556         $params['row'] = $row;
04557         $params['field'] = $field;
04558 
04559         t3lib_div::callUserFunction($config['itemsProcFunc'], $params, $this);
04560         return $items;
04561     }
04562 
04563     /**
04564      * Add selector box items of more exotic kinds.
04565      *
04566      * @param   array       The array of items (label,value,icon)
04567      * @param   array       The "columns" array for the field (from TCA)
04568      * @param   array       TSconfig for the table/row
04569      * @param   string      The fieldname
04570      * @return  array       The $items array modified.
04571      */
04572     function addSelectOptionsToItemArray($items, $fieldValue, $TSconfig, $field) {
04573         global $TCA;
04574 
04575             // Values from foreign tables:
04576         if ($fieldValue['config']['foreign_table']) {
04577             $items = $this->foreignTable($items, $fieldValue, $TSconfig, $field);
04578             if ($fieldValue['config']['neg_foreign_table']) {
04579                 $items = $this->foreignTable($items, $fieldValue, $TSconfig, $field, 1);
04580             }
04581         }
04582 
04583             // Values from a file folder:
04584         if ($fieldValue['config']['fileFolder']) {
04585             $fileFolder = t3lib_div::getFileAbsFileName($fieldValue['config']['fileFolder']);
04586             if (@is_dir($fileFolder)) {
04587 
04588                     // Configurations:
04589                 $extList = $fieldValue['config']['fileFolder_extList'];
04590                 $recursivityLevels = isset($fieldValue['config']['fileFolder_recursions']) ? t3lib_div::intInRange($fieldValue['config']['fileFolder_recursions'], 0, 99) : 99;
04591 
04592                     // Get files:
04593                 $fileFolder = rtrim($fileFolder, '/') . '/';
04594                 $fileArr = t3lib_div::getAllFilesAndFoldersInPath(array(), $fileFolder, $extList, 0, $recursivityLevels);
04595                 $fileArr = t3lib_div::removePrefixPathFromList($fileArr, $fileFolder);
04596 
04597                 foreach ($fileArr as $fileRef) {
04598                     $fI = pathinfo($fileRef);
04599                     $icon = t3lib_div::inList('gif,png,jpeg,jpg', strtolower($fI['extension'])) ? '../' . substr($fileFolder, strlen(PATH_site)) . $fileRef : '';
04600                     $items[] = array(
04601                         $fileRef,
04602                         $fileRef,
04603                         $icon
04604                     );
04605                 }
04606             }
04607         }
04608 
04609             // If 'special' is configured:
04610         if ($fieldValue['config']['special']) {
04611             switch ($fieldValue['config']['special']) {
04612                 case 'tables':
04613                     $temp_tc = array_keys($TCA);
04614                     $descr = '';
04615 
04616                     foreach ($temp_tc as $theTableNames) {
04617                         if (!$TCA[$theTableNames]['ctrl']['adminOnly']) {
04618 
04619                                 // Icon:
04620                             $icon = t3lib_iconWorks::mapRecordTypeToSpriteIconName($theTableNames, array());
04621 
04622                                 // Add help text
04623                             $helpText = array();
04624                             $GLOBALS['LANG']->loadSingleTableDescription($theTableNames);
04625                             $helpTextArray = $GLOBALS['TCA_DESCR'][$theTableNames]['columns'][''];
04626                             if (!empty($helpTextArray['description'])) {
04627                                 $helpText['description'] = $helpTextArray['description'];
04628                             }
04629 
04630                                 // Item configuration:
04631                             $items[] = array(
04632                                 $this->sL($TCA[$theTableNames]['ctrl']['title']),
04633                                 $theTableNames,
04634                                 $icon,
04635                                 $helpText
04636                             );
04637                         }
04638                     }
04639                 break;
04640                 case 'pagetypes':
04641                     $theTypes = $TCA['pages']['columns']['doktype']['config']['items'];
04642 
04643                     foreach ($theTypes as $theTypeArrays) {
04644                             // Icon:
04645                         $icon = t3lib_iconWorks::mapRecordTypeToSpriteIconName('pages', array('doktype' => $theTypeArrays[1]));
04646 
04647                             // Item configuration:
04648                         $items[] = array(
04649                             $this->sL($theTypeArrays[0]),
04650                             $theTypeArrays[1],
04651                             $icon
04652                         );
04653                     }
04654                 break;
04655                 case 'exclude':
04656                     $theTypes = t3lib_BEfunc::getExcludeFields();
04657                     $descr = '';
04658 
04659                     foreach ($theTypes as $theTypeArrays) {
04660                         list($theTable, $theField) = explode(':', $theTypeArrays[1]);
04661 
04662                             // Add help text
04663                         $helpText = array();
04664                         $GLOBALS['LANG']->loadSingleTableDescription($theTable);
04665                         $helpTextArray = $GLOBALS['TCA_DESCR'][$theTable]['columns'][$theField];
04666                         if (!empty($helpTextArray['description'])) {
04667                             $helpText['description'] = $helpTextArray['description'];
04668                         }
04669 
04670                             // Item configuration:
04671                         $items[] = array(
04672                             rtrim($theTypeArrays[0], ':'),
04673                             $theTypeArrays[1],
04674                             'empty-empty',
04675                             $helpText
04676                         );
04677                     }
04678                 break;
04679                 case 'explicitValues':
04680                     $theTypes = t3lib_BEfunc::getExplicitAuthFieldValues();
04681 
04682                         // Icons:
04683                     $icons = array(
04684                         'ALLOW' => 'status-status-permission-granted',
04685                         'DENY' => 'status-status-permission-denied',
04686                     );
04687 
04688                         // Traverse types:
04689                     foreach ($theTypes as $tableFieldKey => $theTypeArrays) {
04690 
04691                         if (is_array($theTypeArrays['items'])) {
04692                                 // Add header:
04693                             $items[] = array(
04694                                 $theTypeArrays['tableFieldLabel'],
04695                                 '--div--',
04696                             );
04697 
04698                                 // Traverse options for this field:
04699                             foreach ($theTypeArrays['items'] as $itemValue => $itemContent) {
04700                                     // Add item to be selected:
04701                                 $items[] = array(
04702                                     '[' . $itemContent[2] . '] ' . $itemContent[1],
04703                                     $tableFieldKey . ':' . preg_replace('/[:|,]/', '', $itemValue) . ':' . $itemContent[0],
04704                                     $icons[$itemContent[0]]
04705                                 );
04706                             }
04707                         }
04708                     }
04709                 break;
04710                 case 'languages':
04711                     $items = array_merge($items, t3lib_BEfunc::getSystemLanguages());
04712                 break;
04713                 case 'custom':
04714                         // Initialize:
04715                     $customOptions = $GLOBALS['TYPO3_CONF_VARS']['BE']['customPermOptions'];
04716                     if (is_array($customOptions)) {
04717                         foreach ($customOptions as $coKey => $coValue) {
04718                             if (is_array($coValue['items'])) {
04719                                     // Add header:
04720                                 $items[] = array(
04721                                     $GLOBALS['LANG']->sl($coValue['header']),
04722                                     '--div--',
04723                                 );
04724 
04725                                     // Traverse items:
04726                                 foreach ($coValue['items'] as $itemKey => $itemCfg) {
04727                                         // Icon:
04728                                     if ($itemCfg[1]) {
04729                                         list($icon) = $this->getIcon($itemCfg[1]);
04730                                     } else {
04731                                         $icon = 'empty-empty';
04732                                     }
04733 
04734                                         // Add help text
04735                                     $helpText = array();
04736                                     if (!empty($itemCfg[2])) {
04737                                         $helpText['description'] = $GLOBALS['LANG']->sl($itemCfg[2]);
04738                                     }
04739 
04740                                         // Add item to be selected:
04741                                     $items[] = array(
04742                                         $GLOBALS['LANG']->sl($itemCfg[0]),
04743                                         $coKey . ':' . preg_replace('/[:|,]/', '', $itemKey),
04744                                         $icon,
04745                                         $helpText,
04746                                     );
04747                                 }
04748                             }
04749                         }
04750                     }
04751                 break;
04752                 case 'modListGroup':
04753                 case 'modListUser':
04754                     $loadModules = t3lib_div::makeInstance('t3lib_loadModules');
04755                     $loadModules->load($GLOBALS['TBE_MODULES']);
04756 
04757                     $modList = $fieldValue['config']['special'] == 'modListUser' ? $loadModules->modListUser : $loadModules->modListGroup;
04758                     if (is_array($modList)) {
04759                         $descr = '';
04760 
04761                         foreach ($modList as $theMod) {
04762 
04763                                 // Icon:
04764                             $icon = $GLOBALS['LANG']->moduleLabels['tabs_images'][$theMod . '_tab'];
04765                             if ($icon) {
04766                                 $icon = '../' . substr($icon, strlen(PATH_site));
04767                             }
04768 
04769                                 // Add help text
04770                             $helpText = array(
04771                                 'title' => $GLOBALS['LANG']->moduleLabels['labels'][$theMod . '_tablabel'],
04772                                 'description' => $GLOBALS['LANG']->moduleLabels['labels'][$theMod . '_tabdescr']
04773                             );
04774 
04775                                 // Item configuration:
04776                             $items[] = array(
04777                                 $this->addSelectOptionsToItemArray_makeModuleData($theMod),
04778                                 $theMod,
04779                                 $icon,
04780                                 $helpText
04781                             );
04782                         }
04783                     }
04784                 break;
04785             }
04786         }
04787 
04788             // Return the items:
04789         return $items;
04790     }
04791 
04792     /**
04793      * Creates value/label pair for a backend module (main and sub)
04794      *
04795      * @param   string      The module key
04796      * @return  string      The rawurlencoded 2-part string to transfer to interface
04797      * @access private
04798      * @see addSelectOptionsToItemArray()
04799      */
04800     function addSelectOptionsToItemArray_makeModuleData($value) {
04801         $label = '';
04802             // Add label for main module:
04803         $pp = explode('_', $value);
04804         if (count($pp) > 1) {
04805             $label .= $GLOBALS['LANG']->moduleLabels['tabs'][$pp[0] . '_tab'] . '>';
04806         }
04807             // Add modules own label now:
04808         $label .= $GLOBALS['LANG']->moduleLabels['tabs'][$value . '_tab'];
04809 
04810         return $label;
04811     }
04812 
04813     /**
04814      * Adds records from a foreign table (for selector boxes)
04815      *
04816      * @param   array       The array of items (label,value,icon)
04817      * @param   array       The 'columns' array for the field (from TCA)
04818      * @param   array       TSconfig for the table/row
04819      * @param   string      The fieldname
04820      * @param   boolean     If set, then we are fetching the 'neg_' foreign tables.
04821      * @return  array       The $items array modified.
04822      * @see addSelectOptionsToItemArray(), t3lib_BEfunc::exec_foreign_table_where_query()
04823      */
04824     function foreignTable($items, $fieldValue, $TSconfig, $field, $pFFlag = 0) {
04825         global $TCA;
04826 
04827             // Init:
04828         $pF = $pFFlag ? 'neg_' : '';
04829         $f_table = $fieldValue['config'][$pF . 'foreign_table'];
04830         $uidPre = $pFFlag ? '-' : '';
04831 
04832             // Get query:
04833         $res = t3lib_BEfunc::exec_foreign_table_where_query($fieldValue, $field, $TSconfig, $pF);
04834 
04835             // Perform lookup
04836         if ($GLOBALS['TYPO3_DB']->sql_error()) {
04837             echo($GLOBALS['TYPO3_DB']->sql_error() . "\n\nThis may indicate a table defined in tables.php is not existing in the database!");
04838             return array();
04839         }
04840 
04841             // Get label prefix.
04842         $lPrefix = $this->sL($fieldValue['config'][$pF . 'foreign_table_prefix']);
04843 
04844             // Get icon field + path if any:
04845         $iField = $TCA[$f_table]['ctrl']['selicon_field'];
04846         $iPath = trim($TCA[$f_table]['ctrl']['selicon_field_path']);
04847 
04848             // Traverse the selected rows to add them:
04849         while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
04850             t3lib_BEfunc::workspaceOL($f_table, $row);
04851 
04852             if (is_array($row)) {
04853                     // Prepare the icon if available:
04854                 if ($iField && $iPath && $row[$iField]) {
04855                     $iParts = t3lib_div::trimExplode(',', $row[$iField], 1);
04856                     $icon = '../' . $iPath . '/' . trim($iParts[0]);
04857                 } elseif (t3lib_div::inList('singlebox,checkbox', $fieldValue['config']['renderMode'])) {
04858                     $icon = t3lib_iconWorks::mapRecordTypeToSpriteIconName($f_table, $row);
04859                 } else {
04860                     $icon = 'empty-empty';
04861                 }
04862 
04863                     // Add the item:
04864                 $items[] = array(
04865                     $lPrefix . htmlspecialchars(t3lib_BEfunc::getRecordTitle($f_table, $row)),
04866                     $uidPre . $row['uid'],
04867                     $icon
04868                 );
04869             }
04870         }
04871         return $items;
04872     }
04873 
04874 
04875     /********************************************
04876      *
04877      * Template functions
04878      *
04879      ********************************************/
04880 
04881     /**
04882      * Sets the design to the backend design.
04883      * Backend
04884      *
04885      * @return  void
04886      */
04887     function setNewBEDesign() {
04888         $template = t3lib_div::getURL(PATH_typo3 . $this->templateFile);
04889 
04890             // Wrapping all table rows for a particular record being edited:
04891         $this->totalWrap = t3lib_parsehtml::getSubpart($template, '###TOTALWRAP###');
04892 
04893             // Wrapping a single field:
04894         $this->fieldTemplate = t3lib_parsehtml::getSubpart($template, '###FIELDTEMPLATE###');
04895 
04896         $this->palFieldTemplate = t3lib_parsehtml::getSubpart($template, '###PALETTE_FIELDTEMPLATE###');
04897         $this->palFieldTemplateHeader = t3lib_parsehtml::getSubpart($template, '###PALETTE_FIELDTEMPLATE_HEADER###');
04898 
04899         $this->sectionWrap = t3lib_parsehtml::getSubpart($template, '###SECTION_WRAP###');
04900     }
04901 
04902     /**
04903      * This inserts the content of $inArr into the field-template
04904      *
04905      * @param   array       Array with key/value pairs to insert in the template.
04906      * @param   string      Alternative template to use instead of the default.
04907      * @return  string
04908      */
04909     function intoTemplate($inArr, $altTemplate = '') {
04910             // Put into template_
04911         $fieldTemplateParts = explode('###FIELD_', $this->rplColorScheme($altTemplate ? $altTemplate : $this->fieldTemplate));
04912         $out = current($fieldTemplateParts);
04913         foreach ($fieldTemplateParts as $part) {
04914             list($key, $val) = explode('###', $part, 2);
04915             $out .= $inArr[$key];
04916             $out .= $val;
04917         }
04918         return $out;
04919     }
04920 
04921     /**
04922      * Overwrite this function in own extended class to add own markers for output
04923      *
04924      * @param   array       Array with key/value pairs to insert in the template.
04925      * @param   string      The table name of the record
04926      * @param   string      The field name which this element is supposed to edit
04927      * @param   array       The record data array where the value(s) for the field can be found
04928      * @param   array       An array with additional configuration options.
04929      * @return  array       marker array for template output
04930      * @see function intoTemplate()
04931      */
04932     function addUserTemplateMarkers($marker, $table, $field, $row, &$PA) {
04933         return $marker;
04934     }
04935 
04936     /**
04937      * Wrapping labels
04938      * Currently not implemented - just returns input value.
04939      *
04940      * @param   string      Input string.
04941      * @return  string      Output string.
04942      */
04943     function wrapLabels($str) {
04944         return $str;
04945     }
04946 
04947     /**
04948      * Wraps all the table rows into a single table.
04949      * Used externally from scripts like alt_doc.php and db_layout.php (which uses TCEforms...)
04950      *
04951      * @param   string      Code to output between table-parts; table rows
04952      * @param   array       The record
04953      * @param   string      The table name
04954      * @return  string
04955      */
04956     function wrapTotal($c, $rec, $table) {
04957         $parts = $this->replaceTableWrap(explode('|', $this->totalWrap, 2), $rec, $table);
04958         return $parts[0] . $c . $parts[1] . implode('', $this->hiddenFieldAccum);
04959     }
04960 
04961     /**
04962      * Generates a token and returns an input field with it
04963      *
04964      * @param string $formName Context of the token
04965      * @param string $tokenName The name of the token GET/POST variable
04966      * @return string a complete input field
04967      */
04968     public static function getHiddenTokenField($formName = 'securityToken', $tokenName = 'formToken') {
04969         $formprotection = t3lib_formprotection_Factory::get();
04970         return '<input type="hidden" name="' .$tokenName . '" value="' . $formprotection->generateToken($formName) . '-' . $formName . '" />';
04971     }
04972 
04973     /**
04974      * This replaces markers in the total wrap
04975      *
04976      * @param   array       An array of template parts containing some markers.
04977      * @param   array       The record
04978      * @param   string      The table name
04979      * @return  string
04980      */
04981     function replaceTableWrap($arr, $rec, $table) {
04982         global $TCA;
04983 
04984             // Make "new"-label
04985         if (strstr($rec['uid'], 'NEW')) {
04986             $newLabel = ' <span class="typo3-TCEforms-newToken">' .
04987                         $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.new', 1) .
04988                         '</span>';
04989 
04990                 // Kasper: Should not be used here because NEW records are not offline workspace versions...
04991             #t3lib_BEfunc::fixVersioningPid($table,$rec);
04992             $truePid = t3lib_BEfunc::getTSconfig_pidValue($table, $rec['uid'], $rec['pid']);
04993             $prec = t3lib_BEfunc::getRecordWSOL('pages', $truePid, 'title');
04994             $pageTitle = t3lib_BEfunc::getRecordTitle('pages', $prec, TRUE, FALSE);
04995             $rLabel = '<em>[PID: ' . $truePid . '] ' . $pageTitle . '</em>';
04996 
04997                 // Fetch translated title of the table
04998             $tableTitle = $GLOBALS['LANG']->sL($GLOBALS['TCA'][$table]['ctrl']['title']);
04999             if ($table === 'pages') {
05000                 $label = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.createNewPage', TRUE);
05001                 $pageTitle = sprintf($label, $tableTitle);
05002             } else {
05003                 $label = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.createNewRecord', TRUE);
05004 
05005                 if ($rec['pid'] == 0) {
05006                     $label = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.createNewRecordRootLevel', TRUE);
05007                 }
05008                 $pageTitle = sprintf($label, $tableTitle, $pageTitle);
05009             }
05010         } else {
05011             $newLabel = ' <span class="typo3-TCEforms-recUid">[' . $rec['uid'] . ']</span>';
05012             $rLabel = t3lib_BEfunc::getRecordTitle($table, $rec, TRUE, FALSE);
05013             $prec = t3lib_BEfunc::getRecordWSOL('pages', $rec['pid'], 'uid,title');
05014 
05015                 // Fetch translated title of the table
05016             $tableTitle = $GLOBALS['LANG']->sL($GLOBALS['TCA'][$table]['ctrl']['title']);
05017             if ($table === 'pages') {
05018                 $label = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.editPage', TRUE);
05019 
05020                     // Just take the record title and prepend an edit label.
05021                 $pageTitle = sprintf($label, $tableTitle, $rLabel);
05022             } else {
05023                 $label = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.editRecord', TRUE);
05024 
05025                 $pageTitle = t3lib_BEfunc::getRecordTitle('pages', $prec, TRUE, FALSE);
05026                 if ($rLabel === t3lib_BEfunc::getNoRecordTitle(TRUE)) {
05027                     $label = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.editRecordNoTitle', TRUE);
05028                 }
05029                 if ($rec['pid'] == 0) {
05030                     $label = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.editRecordRootLevel', TRUE);
05031                 }
05032 
05033                 if ($rLabel !== t3lib_BEfunc::getNoRecordTitle(TRUE)) {
05034 
05035                         // Just take the record title and prepend an edit label.
05036                     $pageTitle = sprintf($label, $tableTitle, $rLabel, $pageTitle);
05037                 } else {
05038 
05039                         // Leave out the record title since it is not set.
05040                     $pageTitle = sprintf($label, $tableTitle, $pageTitle);
05041                 }
05042             }
05043         }
05044 
05045         foreach ($arr as $k => $v) {
05046                 // Make substitutions:
05047             $arr[$k] = str_replace('###PAGE_TITLE###', $pageTitle, $arr[$k]);
05048             $arr[$k] = str_replace('###ID_NEW_INDICATOR###', $newLabel, $arr[$k]);
05049             $arr[$k] = str_replace('###RECORD_LABEL###', $rLabel, $arr[$k]);
05050             $arr[$k] = str_replace('###TABLE_TITLE###', htmlspecialchars($this->sL($TCA[$table]['ctrl']['title'])), $arr[$k]);
05051 
05052             $arr[$k] = str_replace('###RECORD_ICON###', t3lib_iconWorks::getSpriteIconForRecord($table, $rec, array('title' => $this->getRecordPath($table, $rec))), $arr[$k]);
05053 
05054         }
05055         return $arr;
05056     }
05057 
05058     /**
05059      * Wraps an element in the $out_array with the template row for a "section" ($this->sectionWrap)
05060      *
05061      * @param   array       The array with form elements stored in (passed by reference and changed!)
05062      * @param   integer     The pointer to the entry in the $out_array  (passed by reference and incremented!)
05063      * @return  void
05064      */
05065     function wrapBorder(&$out_array, &$out_pointer) {
05066         if ($this->sectionWrap && $out_array[$out_pointer]) {
05067             $tableAttribs = '';
05068             $tableAttribs .= $this->borderStyle[0] ? ' style="' . htmlspecialchars($this->borderStyle[0]) . '"' : '';
05069             $tableAttribs .= $this->borderStyle[2] ? ' background="' . htmlspecialchars($this->backPath . $this->borderStyle[2]) . '"' : '';
05070             $tableAttribs .= $this->borderStyle[3] ? ' class="' . htmlspecialchars($this->borderStyle[3]) . '"' : '';
05071             if ($tableAttribs) {
05072                 $tableAttribs = 'border="0" cellspacing="0" cellpadding="0" width="100%"' . $tableAttribs;
05073                 $out_array[$out_pointer] = str_replace('###CONTENT###', $out_array[$out_pointer],
05074                                                        str_replace('###TABLE_ATTRIBS###', $tableAttribs, $this->sectionWrap));
05075             }
05076             $out_pointer++;
05077         }
05078     }
05079 
05080     /**
05081      * Replaces colorscheme markers in the template string
05082      *
05083      * @param   string      Template string with markers to be substituted.
05084      * @return  string
05085      */
05086     function rplColorScheme($inTemplate) {
05087             // Colors:
05088         $inTemplate = str_replace('###BGCOLOR###', $this->colorScheme[0] ? ' bgcolor="' . $this->colorScheme[0] . '"' : '', $inTemplate);
05089         $inTemplate = str_replace('###BGCOLOR_HEAD###', $this->colorScheme[1] ? ' bgcolor="' . $this->colorScheme[1] . '"' : '', $inTemplate);
05090         $inTemplate = str_replace('###FONTCOLOR_HEAD###', $this->colorScheme[3], $inTemplate);
05091 
05092             // Classes:
05093         $inTemplate = str_replace('###CLASSATTR_1###', $this->classScheme[0] ? ' class="' . $this->classScheme[0] . '"' : '', $inTemplate);
05094         $inTemplate = str_replace('###CLASSATTR_2###', $this->classScheme[1] ? ' class="' . $this->classScheme[1] . '"' : '', $inTemplate);
05095         $inTemplate = str_replace('###CLASSATTR_4###', $this->classScheme[3] ? ' class="' . $this->classScheme[3] . '"' : '', $inTemplate);
05096 
05097         return $inTemplate;
05098     }
05099 
05100     /**
05101      * Returns divider.
05102      * Currently not implemented and returns only blank value.
05103      *
05104      * @return  string      Empty string
05105      */
05106     function getDivider() {
05107         return '';
05108     }
05109 
05110     /**
05111      * Creates HTML output for a palette
05112      *
05113      * @param   array       The palette array to print
05114      * @return  string      HTML output
05115      */
05116     function printPalette($palArr) {
05117         $fieldAttributes = $labelAttributes = '';
05118 
05119             // Init color/class attributes:
05120         if ($this->colorScheme[2]) {
05121             $labelAttributes .= ' bgcolor="' . $this->colorScheme[2] . '"';
05122         }
05123 
05124         if ($this->classScheme[2]) {
05125             $labelAttributes .= ' class="t3-form-palette-field-label ' . $this->classScheme[2] . '"';
05126         } else {
05127             $labelAttributes .= ' class="t3-form-palette-field-label"';
05128         }
05129 
05130         if ($this->colorScheme[4]) {
05131             $fieldAttributes .= ' style="color: ' . $this->colorScheme[4] . '"';
05132         }
05133 
05134         if ($this->classScheme[4]) {
05135             $fieldAttributes .= ' class="t3-form-palette-field ' . $this->classScheme[4] . '"';
05136         }
05137 
05138         $row = 0;
05139         $hRow = $iRow = array();
05140         $lastLineWasLinebreak = FALSE;
05141 
05142             // Traverse palette fields and render them into containers:
05143         foreach ($palArr as $content) {
05144             if ($content['NAME'] === '--linebreak--') {
05145                 if (!$lastLineWasLinebreak) {
05146                     $row++;
05147                     $lastLineWasLinebreak = TRUE;
05148                 }
05149             } else {
05150                 $lastLineWasLinebreak = FALSE;
05151                 $fieldIdentifierForJs = $content['TABLE'] . '_' . $content['ID'] . '_' . $content['FIELD'];
05152                 $iRow[$row][] = '<span class="t3-form-palette-field-container">' .
05153                                 '<label' . $labelAttributes . '>' .
05154                                 $content['NAME'] .
05155                                 '</label>' .
05156                                 '<span' . $fieldAttributes . '>' .
05157                                     '<img name="cm_' . $fieldIdentifierForJs . '" src="clear.gif" class="t3-form-palette-icon-contentchanged" alt="" />' .
05158                                     '<img name="req_' . $fieldIdentifierForJs . '" src="clear.gif" class="t3-form-palette-icon-required" alt="" />' .
05159                                     $content['ITEM'] .
05160                                 '</span>' .
05161                                 '</span>';
05162             }
05163         }
05164 
05165             // Final wrapping into the fieldset:
05166         $out = '<fieldset class="t3-form-palette-fieldset">';
05167         for ($i = 0; $i <= $row; $i++) {
05168             if (isset($iRow[$i])) {
05169                 $out .= implode('', $iRow[$i]);
05170                 $out .= ($i < $row ? '<br />' : '');
05171             }
05172 
05173         }
05174         $out .= '</fieldset>';
05175         return $out;
05176     }
05177 
05178 
05179     /**
05180      * Returns help-text ICON if configured for.
05181      *
05182      * @param   string      The table name
05183      * @param   string      The field name
05184      * @param   boolean     Force the return of the help-text icon.
05185      * @return  string      HTML, <a>-tag with
05186      * @deprecated since TYPO3 4.5, will be removed in TYPO3 4.7
05187      */
05188     function helpTextIcon($table, $field, $force = 0) {
05189         t3lib_div::logDeprecatedFunction();
05190         if ($this->globalShowHelp && $GLOBALS['TCA_DESCR'][$table]['columns'][$field] && (($this->edit_showFieldHelp == 'icon' && !$this->doLoadTableDescr($table)) || $force)) {
05191             return t3lib_BEfunc::helpTextIcon($table, $field, $this->backPath, $force);
05192         } else {
05193                 // Detects fields with no CSH and outputs dummy line to insert into CSH locallang file:
05194             return '<span class="nbsp">&nbsp;</span>';
05195         }
05196     }
05197 
05198     /**
05199      * Returns help text DESCRIPTION, if configured for.
05200      *
05201      * @param   string      The table name
05202      * @param   string      The field name
05203      * @return  string
05204      * @deprecated since TYPO3 4.5, will be removed in TYPO3 4.7
05205      */
05206     function helpText($table, $field) {
05207         t3lib_div::logDeprecatedFunction();
05208         if ($this->globalShowHelp && $GLOBALS['TCA_DESCR'][$table]['columns'][$field] && ($this->edit_showFieldHelp == 'text' || $this->doLoadTableDescr($table))) {
05209             $fDat = $GLOBALS['TCA_DESCR'][$table]['columns'][$field];
05210             return '<table border="0" cellpadding="2" cellspacing="0" width="90%"><tr><td valign="top" width="14">' .
05211                    $this->helpTextIcon(
05212                        $table,
05213                        $field,
05214                        $fDat['details'] || $fDat['syntax'] || $fDat['image_descr'] || $fDat['image'] || $fDat['seeAlso']
05215                    ) .
05216                    '</td><td valign="top"><span class="typo3-TCEforms-helpText">' .
05217                    $GLOBALS['LANG']->hscAndCharConv(strip_tags($fDat['description']), 1) .
05218                    '</span></td></tr></table>';
05219         }
05220     }
05221 
05222     /**
05223      * Returns help-text ICON if configured for.
05224      *
05225      * @param   string      Field name
05226      * @param   string      Field title
05227      * @param   string      File name with CSH labels
05228      * @return  string      HTML, <a>-tag with
05229      * @deprecated since TYPO3 4.5, this function will be removed in TYPO3 4.7. Use t3lib_BEfunc::wrapInHelp() instead.
05230      */
05231     function helpTextIcon_typeFlex($field, $fieldTitle, $cshFile) {
05232         t3lib_div::logDeprecatedFunction();
05233         if ($this->globalShowHelp && $cshFile) {
05234             $value = $GLOBALS['LANG']->sL($cshFile . ':' . $field . '.description');
05235             if (trim($value)) {
05236                 if (substr($fieldTitle, -1, 1) == ':') {
05237                     $fieldTitle = substr($fieldTitle, 0, strlen($fieldTitle) - 1);
05238                 }
05239 
05240                     // Hover popup textbox with alttitle and description
05241                 if ($this->edit_showFieldHelp == 'icon') {
05242                     $arrow = t3lib_iconWorks::getSpriteIcon('actions-view-go-forward');
05243                         // add description text
05244                     $hoverText = '<span class="paragraph">' . nl2br(htmlspecialchars($value)) . $arrow . '</span>';
05245                         // put header before the rest of the text
05246                     $alttitle = $GLOBALS['LANG']->sL($cshFile . ':' . $field . '.alttitle');
05247                     if ($alttitle) {
05248                         $hoverText = '<span class="header">' . $alttitle . '</span><br />' . $hoverText;
05249                     }
05250                     $hoverText = '<span class="typo3-csh-inline">' . $GLOBALS['LANG']->hscAndCharConv($hoverText, FALSE) . '</span>';
05251                 }
05252 
05253                     // CSH exists
05254                 $params = base64_encode(serialize(array(
05255                                                        'cshFile' => $cshFile,
05256                                                        'field' => $field,
05257                                                        'title' => $fieldTitle
05258                                                   )));
05259                 $aOnClick = 'vHWin=window.open(\'' . $this->backPath . 'view_help.php?ffID=' . $params . '\',\'viewFieldHelp\',\'height=400,width=600,status=0,menubar=0,scrollbars=1\');vHWin.focus();return false;';
05260                 return '<a href="#" class="typo3-csh-link" onclick="' . htmlspecialchars($aOnClick) . '">' .
05261                        t3lib_iconWorks::getSpriteIcon('actions-system-help-open') . $hoverText .
05262                        '</a>';
05263             }
05264         }
05265         return '';
05266     }
05267 
05268     /**
05269      * Returns help text DESCRIPTION, if configured for.
05270      *
05271      * @param   string      Field name
05272      * @param   string      CSH file name
05273      * @return  string      Description for the field with cion or empty string
05274      * @deprecated since TYPO3 4.5, this function will be removed in TYPO3 4.7. Use t3lib_BEfunc::wrapInHelp() instead.
05275      */
05276     function helpText_typeFlex($field, $fieldTitle, $cshFile) {
05277         t3lib_div::logDeprecatedFunction();
05278         if ($this->globalShowHelp && $cshFile && $this->edit_showFieldHelp == 'text') {
05279             $value = $GLOBALS['LANG']->sL($cshFile . ':' . $field . '.description');
05280             if (trim($value)) {
05281                 return '<table border="0" cellpadding="2" cellspacing="0" width="90%"><tr><td valign="top" width="14">' .
05282                        $this->helpTextIcon_typeFlex(
05283                            $field,
05284                            $fieldTitle,
05285                            $cshFile
05286                        ) .
05287                        '</td><td valign="top"><span class="typo3-TCEforms-helpText-flexform">' .
05288                        $GLOBALS['LANG']->hscAndCharConv(strip_tags($value), 1) .
05289                        '</span></td></tr></table>';
05290             }
05291         }
05292         return '';
05293     }
05294 
05295 
05296     /**
05297      * Setting the current color scheme ($this->colorScheme) based on $this->defColorScheme plus input string.
05298      *
05299      * @param   string      A color scheme string.
05300      * @return  void
05301      */
05302     function setColorScheme($scheme) {
05303         $this->colorScheme = $this->defColorScheme;
05304         $this->classScheme = $this->defClassScheme;
05305 
05306         $parts = t3lib_div::trimExplode(',', $scheme);
05307         foreach ($parts as $key => $col) {
05308                 // Split for color|class:
05309             list($color, $class) = t3lib_div::trimExplode('|', $col);
05310 
05311                 // Handle color values:
05312             if ($color) {
05313                 $this->colorScheme[$key] = $color;
05314             }
05315             if ($color == '-') {
05316                 $this->colorScheme[$key] = '';
05317             }
05318 
05319                 // Handle class values:
05320             if ($class) {
05321                 $this->classScheme[$key] = $class;
05322             }
05323             if ($class == '-') {
05324                 $this->classScheme[$key] = '';
05325             }
05326         }
05327     }
05328 
05329     /**
05330      * Reset color schemes.
05331      *
05332      * @return  void
05333      */
05334     function resetSchemes() {
05335         $this->setColorScheme($GLOBALS['TBE_STYLES']['colorschemes'][0]);
05336         $this->fieldStyle = $GLOBALS['TBE_STYLES']['styleschemes'][0];
05337         $this->borderStyle = $GLOBALS['TBE_STYLES']['borderschemes'][0];
05338     }
05339 
05340     /**
05341      * Store current color scheme
05342      *
05343      * @return  void
05344      */
05345     function storeSchemes() {
05346         $this->savedSchemes['classScheme'] = $this->classScheme;
05347         $this->savedSchemes['colorScheme'] = $this->colorScheme;
05348         $this->savedSchemes['fieldStyle'] = $this->fieldStyle;
05349         $this->savedSchemes['borderStyle'] = $this->borderStyle;
05350     }
05351 
05352     /**
05353      * Restore the saved color scheme
05354      *
05355      * @return  void
05356      */
05357     function restoreSchemes() {
05358         $this->classScheme = $this->savedSchemes['classScheme'];
05359         $this->colorScheme = $this->savedSchemes['colorScheme'];
05360         $this->fieldStyle = $this->savedSchemes['fieldStyle'];
05361         $this->borderStyle = $this->savedSchemes['borderStyle'];
05362     }
05363 
05364 
05365     /********************************************
05366      *
05367      * JavaScript related functions
05368      *
05369      ********************************************/
05370 
05371     /**
05372      * JavaScript code added BEFORE the form is drawn:
05373      *
05374      * @return  string      A <script></script> section with JavaScript.
05375      */
05376     function JStop() {
05377 
05378         $out = '';
05379 
05380             // Additional top HTML:
05381         if (count($this->additionalCode_pre)) {
05382             $out .= implode('
05383 
05384                 <!-- NEXT: -->
05385             ', $this->additionalCode_pre);
05386         }
05387 
05388             // Additional top JavaScript
05389         if (count($this->additionalJS_pre)) {
05390             $out .= '
05391 
05392 
05393         <!--
05394             JavaScript in top of page (before form):
05395         -->
05396 
05397         <script type="text/javascript">
05398             /*<![CDATA[*/
05399 
05400             ' . implode('
05401 
05402                     // NEXT:
05403             ', $this->additionalJS_pre) . '
05404 
05405             /*]]>*/
05406         </script>
05407             ';
05408         }
05409 
05410             // Return result:
05411         return $out;
05412     }
05413 
05414     /**
05415      * JavaScript code used for input-field evaluation.
05416      *
05417      *       Example use:
05418      *
05419      *       $msg .= 'Distribution time (hh:mm dd-mm-yy):<br /><input type="text" name="send_mail_datetime_hr" onchange="typo3form.fieldGet(\'send_mail_datetime\', \'datetime\', \'\', 0,0);"' . $GLOBALS['TBE_TEMPLATE']->formWidth(20) . ' /><input type="hidden" value="' . $GLOBALS['EXEC_TIME'] . '" name="send_mail_datetime" /><br />';
05420      *       $this->extJSCODE.='typo3form.fieldSet("send_mail_datetime", "datetime", "", 0,0);';
05421      *
05422      *       ... and then include the result of this function after the form
05423      *
05424      * @param   string      $formname: The identification of the form on the page.
05425      * @param   boolean     $update: Just extend/update existing settings, e.g. for AJAX call
05426      * @return  string      A section with JavaScript - if $update is false, embedded in <script></script>
05427      */
05428     function JSbottom($formname = 'forms[0]', $update = FALSE) {
05429         $jsFile = array();
05430         $elements = array();
05431 
05432             // required:
05433         foreach ($this->requiredFields as $itemImgName => $itemName) {
05434             $match = array();
05435             if (preg_match('/^(.+)\[((\w|\d|_)+)\]$/', $itemName, $match)) {
05436                 $record = $match[1];
05437                 $field = $match[2];
05438                 $elements[$record][$field]['required'] = 1;
05439                 $elements[$record][$field]['requiredImg'] = $itemImgName;
05440                 if (isset($this->requiredAdditional[$itemName]) && is_array($this->requiredAdditional[$itemName])) {
05441                     $elements[$record][$field]['additional'] = $this->requiredAdditional[$itemName];
05442                 }
05443             }
05444         }
05445             // range:
05446         foreach ($this->requiredElements as $itemName => $range) {
05447             if (preg_match('/^(.+)\[((\w|\d|_)+)\]$/', $itemName, $match)) {
05448                 $record = $match[1];
05449                 $field = $match[2];
05450                 $elements[$record][$field]['range'] = array($range[0], $range[1]);
05451                 $elements[$record][$field]['rangeImg'] = $range['imgName'];
05452             }
05453         }
05454 
05455         $this->TBE_EDITOR_fieldChanged_func = 'TBE_EDITOR.fieldChanged_fName(fName,formObj[fName+"_list"]);';
05456 
05457         if (!$update) {
05458             if ($this->loadMD5_JS) {
05459                 $this->loadJavascriptLib('md5.js');
05460             }
05461 
05462             /** @var $pageRenderer t3lib_PageRenderer */
05463             $pageRenderer = $GLOBALS['SOBE']->doc->getPageRenderer();
05464             $pageRenderer->loadPrototype();
05465             $pageRenderer->loadExtJS();
05466 
05467                 // make textareas resizable and flexible
05468             if (!($GLOBALS['BE_USER']->uc['resizeTextareas'] == '0' && $GLOBALS['BE_USER']->uc['resizeTextareas_Flexible'] == '0')) {
05469                 $pageRenderer->addCssFile($this->backPath . '../t3lib/js/extjs/ux/resize.css');
05470                 $this->loadJavascriptLib('../t3lib/js/extjs/ux/ext.resizable.js');
05471             }
05472             $resizableSettings = array(
05473                 'textareaMaxHeight' => $GLOBALS['BE_USER']->uc['resizeTextareas_MaxHeight'] > 0 ? $GLOBALS['BE_USER']->uc['resizeTextareas_MaxHeight'] : '600',
05474                 'textareaFlexible' => (!$GLOBALS['BE_USER']->uc['resizeTextareas_Flexible'] == '0'),
05475                 'textareaResize' => (!$GLOBALS['BE_USER']->uc['resizeTextareas'] == '0'),
05476             );
05477             $pageRenderer->addInlineSettingArray('', $resizableSettings);
05478 
05479             $this->loadJavascriptLib('../t3lib/jsfunc.evalfield.js');
05480             $this->loadJavascriptLib('jsfunc.tbe_editor.js');
05481 
05482                 // needed for tceform manipulation (date picker)
05483             $typo3Settings = array(
05484                 'datePickerUSmode' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? 1 : 0,
05485                 'dateFormat' => array('j-n-Y', 'G:i j-n-Y'),
05486                 'dateFormatUS' => array('n-j-Y', 'G:i n-j-Y'),
05487             );
05488             $pageRenderer->addInlineSettingArray('', $typo3Settings);
05489 
05490             $this->loadJavascriptLib('../t3lib/js/extjs/tceforms.js');
05491 
05492                 // if IRRE fields were processed, add the JavaScript functions:
05493             if ($this->inline->inlineCount) {
05494                 $GLOBALS['SOBE']->doc->getPageRenderer()->loadScriptaculous();
05495                 $this->loadJavascriptLib('../t3lib/jsfunc.inline.js');
05496                 $out .= '
05497                 inline.setPrependFormFieldNames("' . $this->inline->prependNaming . '");
05498                 inline.setNoTitleString("' . addslashes(t3lib_BEfunc::getNoRecordTitle(TRUE)) . '");
05499                 ';
05500             }
05501 
05502                 // if Suggest fields were processed, add the JS functions
05503             if ($this->suggest->suggestCount > 0) {
05504                 $pageRenderer->loadScriptaculous();
05505                 $this->loadJavascriptLib('../t3lib/js/jsfunc.tceforms_suggest.js');
05506             }
05507 
05508                 // Toggle icons:
05509             $toggleIcon_open = t3lib_iconWorks::getSpriteIcon('actions-move-down', array('title' => 'Open'));
05510             $toggleIcon_close = t3lib_iconWorks::getSpriteIcon('actions-move-right', array('title' => 'Close'));
05511 
05512             $out .= '
05513             function getOuterHTML(idTagPrefix)  {   // Function getting the outerHTML of an element with id
05514                 var str=($(idTagPrefix).inspect()+$(idTagPrefix).innerHTML+"</"+$(idTagPrefix).tagName.toLowerCase()+">");
05515                 return str;
05516             }
05517             function flexFormToggle(id) {   // Toggling flexform elements on/off:
05518                 Element.toggle(""+id+"-content");
05519 
05520                 if (Element.visible(id+"-content")) {
05521                     $(id+"-toggle").update(\'' . $toggleIcon_open . '\');
05522                     $(id+"-toggleClosed").value = 0;
05523                 } else {
05524                     $(id+"-toggle").update(\'' . $toggleIcon_close . '\');
05525                     $(id+"-toggleClosed").value = 1;
05526                 }
05527 
05528                 var previewContent = "";
05529                 var children = $(id+"-content").getElementsByTagName("input");
05530                 for (var i = 0, length = children.length; i < length; i++) {
05531                     if (children[i].type=="text" && children[i].value)  previewContent+= (previewContent?" / ":"")+children[i].value;
05532                 }
05533                 if (previewContent.length>80)   {
05534                     previewContent = previewContent.substring(0,67)+"...";
05535                 }
05536                 $(id+"-preview").update(previewContent);
05537             }
05538             function flexFormToggleSubs(id) {   // Toggling sub flexform elements on/off:
05539                 var descendants = $(id).immediateDescendants();
05540                 var isOpen=0;
05541                 var isClosed=0;
05542                     // Traverse and find how many are open or closed:
05543                 for (var i = 0, length = descendants.length; i < length; i++) {
05544                     if (descendants[i].id)  {
05545                         if (Element.visible(descendants[i].id+"-content"))  {isOpen++;} else {isClosed++;}
05546                     }
05547                 }
05548 
05549                     // Traverse and toggle
05550                 for (var i = 0, length = descendants.length; i < length; i++) {
05551                     if (descendants[i].id)  {
05552                         if (isOpen!=0 && isClosed!=0)   {
05553                             if (Element.visible(descendants[i].id+"-content"))  {flexFormToggle(descendants[i].id);}
05554                         } else {
05555                             flexFormToggle(descendants[i].id);
05556                         }
05557                     }
05558                 }
05559             }
05560             function flexFormSortable(id)   {   // Create sortables for flexform sections
05561                 Position.includeScrollOffsets = true;
05562                 Sortable.create(id, {tag:\'div\',constraint: false, onChange:function(){
05563                     setActionStatus(id);
05564                 } });
05565             }
05566             function setActionStatus(id)    {   // Updates the "action"-status for a section. This is used to move and delete elements.
05567                 var descendants = $(id).immediateDescendants();
05568 
05569                     // Traverse and find how many are open or closed:
05570                 for (var i = 0, length = descendants.length; i < length; i++) {
05571                     if (descendants[i].id)  {
05572                         $(descendants[i].id+"-action").value = descendants[i].visible() ? i : "DELETE";
05573                     }
05574                 }
05575             }
05576 
05577             TBE_EDITOR.images.req.src = "' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/required_h.gif', '', 1) . '";
05578             TBE_EDITOR.images.cm.src = "' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/content_client.gif', '', 1) . '";
05579             TBE_EDITOR.images.sel.src = "' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/content_selected.gif', '', 1) . '";
05580             TBE_EDITOR.images.clear.src = "' . $this->backPath . 'clear.gif";
05581 
05582             TBE_EDITOR.auth_timeout_field = ' . intval($GLOBALS['BE_USER']->auth_timeout_field) . ';
05583             TBE_EDITOR.formname = "' . $formname . '";
05584             TBE_EDITOR.formnameUENC = "' . rawurlencode($formname) . '";
05585             TBE_EDITOR.backPath = "' . addslashes($this->backPath) . '";
05586             TBE_EDITOR.prependFormFieldNames = "' . $this->prependFormFieldNames . '";
05587             TBE_EDITOR.prependFormFieldNamesUENC = "' . rawurlencode($this->prependFormFieldNames) . '";
05588             TBE_EDITOR.prependFormFieldNamesCnt = ' . substr_count($this->prependFormFieldNames, '[') . ';
05589             TBE_EDITOR.isPalettedoc = ' . ($this->isPalettedoc ? addslashes($this->isPalettedoc) : 'null') . ';
05590             TBE_EDITOR.doSaveFieldName = "' . ($this->doSaveFieldName ? addslashes($this->doSaveFieldName) : '') . '";
05591             TBE_EDITOR.labels.fieldsChanged = ' . $GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.fieldsChanged')) . ';
05592             TBE_EDITOR.labels.fieldsMissing = ' . $GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.fieldsMissing')) . ';
05593             TBE_EDITOR.labels.refresh_login = ' . $GLOBALS['LANG']->JScharCode($this->getLL('m_refresh_login')) . ';
05594             TBE_EDITOR.labels.onChangeAlert = ' . $GLOBALS['LANG']->JScharCode($this->getLL('m_onChangeAlert')) . ';
05595             evalFunc.USmode = ' . ($GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? '1' : '0') . ';
05596             TBE_EDITOR.backend_interface = "' . $GLOBALS['BE_USER']->uc['interfaceSetup'] . '";
05597             ';
05598         }
05599 
05600             // add JS required for inline fields
05601         if (count($this->inline->inlineData)) {
05602             $out .= '
05603             inline.addToDataArray(' . json_encode($this->inline->inlineData) . ');
05604             ';
05605         }
05606             // Registered nested elements for tabs or inline levels:
05607         if (count($this->requiredNested)) {
05608             $out .= '
05609             TBE_EDITOR.addNested(' . json_encode($this->requiredNested) . ');
05610             ';
05611         }
05612             // elements which are required or have a range definition:
05613         if (count($elements)) {
05614             $out .= '
05615             TBE_EDITOR.addElements(' . json_encode($elements) . ');
05616             TBE_EDITOR.initRequired();
05617             ';
05618         }
05619             // $this->additionalJS_submit:
05620         if ($this->additionalJS_submit) {
05621             $additionalJS_submit = implode('', $this->additionalJS_submit);
05622             $additionalJS_submit = str_replace(CR, '', $additionalJS_submit);
05623             $additionalJS_submit = str_replace(LF, '', $additionalJS_submit);
05624             $out .= '
05625             TBE_EDITOR.addActionChecks("submit", "' . addslashes($additionalJS_submit) . '");
05626             ';
05627         }
05628 
05629         $out .= LF . implode(LF, $this->additionalJS_post) . LF . $this->extJSCODE;
05630         $out .= '
05631             TBE_EDITOR.loginRefreshed();
05632         ';
05633 
05634             // Regular direct output:
05635         if (!$update) {
05636             $spacer = LF . TAB;
05637             $out = $spacer . implode($spacer, $jsFile) . t3lib_div::wrapJS($out);
05638         }
05639 
05640         return $out;
05641     }
05642 
05643     /**
05644      * Used to connect the db/file browser with this document and the formfields on it!
05645      *
05646      * @param   string      Form object reference (including "document.")
05647      * @return  string      JavaScript functions/code (NOT contained in a <script>-element)
05648      */
05649     function dbFileCon($formObj = 'document.forms[0]') {
05650             // @TODO: Export this to an own file, it is more static than dynamic JavaScript -- olly
05651         $str = '
05652 
05653             // ***************
05654             // Used to connect the db/file browser with this document and the formfields on it!
05655             // ***************
05656 
05657             var browserWin="";
05658 
05659             function setFormValueOpenBrowser(mode,params) { //
05660                 var url = "' . $this->backPath . 'browser.php?mode="+mode+"&bparams="+params;
05661 
05662                 browserWin = window.open(url,"Typo3WinBrowser","height=650,width="+(mode=="db"?650:600)+",status=0,menubar=0,resizable=1,scrollbars=1");
05663                 browserWin.focus();
05664             }
05665             function setFormValueFromBrowseWin(fName,value,label,exclusiveValues) {
05666                 var formObj = setFormValue_getFObj(fName);
05667                 if (formObj && value !== "--div--") {
05668                         // Check if the form object has a "_list" element or not
05669                         // The "_list" element exists for multiple selection select types
05670                     var isMultiple = true;
05671                     if (formObj[fName + "_list"]) {
05672                         fObj = formObj[fName + "_list"];
05673                     } else {
05674                         fObj = formObj[fName];
05675                         var isMultiple = false;
05676                     }
05677                     var len = fObj.length;
05678 
05679                     if (isMultiple) {
05680                             // Clear elements if exclusive values are found
05681                         if (exclusiveValues) {
05682                             var m = new RegExp("(^|,)" + value + "($|,)");
05683                             if (exclusiveValues.match(m))   {
05684                                     // the new value is exclusive
05685                                 for (a = len - 1; a >= 0; a--) {
05686                                     fObj[a] = null;
05687                                 }
05688                                 len = 0;
05689                             } else if (len == 1)    {
05690                                 m = new RegExp("(^|,)" + fObj.options[0].value + "($|,)");
05691                                 if (exclusiveValues.match(m)) {
05692                                         // the old value is exclusive
05693                                     fObj[0] = null;
05694                                     len = 0;
05695                                 }
05696                             }
05697                         }
05698                             // Inserting element
05699                         var setOK = 1;
05700                         if (!formObj[fName + "_mul"] || formObj[fName + "_mul"].value == 0) {
05701                             for (a = 0; a < len; a++) {
05702                                 if (fObj.options[a].value == value) {
05703                                     setOK = 0;
05704                                 }
05705                             }
05706                         }
05707                         if (setOK) {
05708                             fObj.length++;
05709                             fObj.options[len].value = value;
05710                             fObj.options[len].text = unescape(label);
05711 
05712                                 // Traversing list and set the hidden-field
05713                             setHiddenFromList(fObj,formObj[fName]);
05714                             ' . $this->TBE_EDITOR_fieldChanged_func . '
05715                         }
05716                     } else {
05717                             // The incoming value consists of the table name, an underscore and the uid
05718                             // For a single selection field we need only the uid, so we extract it
05719                         var uidValue = value;
05720                         var pattern = /_(\d+)$/;
05721                         var result = value.match(pattern);
05722                         if (result != null) {
05723                             uidValue = result[1];
05724                         }
05725                             // Change the selected value
05726                         fObj.value = uidValue;
05727                     }
05728                 }
05729             }
05730             function setHiddenFromList(fObjSel,fObjHid) {   //
05731                 l=fObjSel.length;
05732                 fObjHid.value="";
05733                 for (a=0;a<l;a++)   {
05734                     fObjHid.value+=fObjSel.options[a].value+",";
05735                 }
05736             }
05737             function setFormValueManipulate(fName,type) {   //
05738                 var formObj = setFormValue_getFObj(fName);
05739                 if (formObj)    {
05740                     var localArray_V = new Array();
05741                     var localArray_L = new Array();
05742                     var localArray_S = new Array();
05743                     var fObjSel = formObj[fName+"_list"];
05744                     var l=fObjSel.length;
05745                     var c=0;
05746                     if ((type=="Remove" && fObjSel.size > 1) || type=="Top" || type=="Bottom")  {
05747                         if (type=="Top")    {
05748                             for (a=0;a<l;a++)   {
05749                                 if (fObjSel.options[a].selected==1) {
05750                                     localArray_V[c]=fObjSel.options[a].value;
05751                                     localArray_L[c]=fObjSel.options[a].text;
05752                                     localArray_S[c]=1;
05753                                     c++;
05754                                 }
05755                             }
05756                         }
05757                         for (a=0;a<l;a++)   {
05758                             if (fObjSel.options[a].selected!=1) {
05759                                 localArray_V[c]=fObjSel.options[a].value;
05760                                 localArray_L[c]=fObjSel.options[a].text;
05761                                 localArray_S[c]=0;
05762                                 c++;
05763                             }
05764                         }
05765                         if (type=="Bottom") {
05766                             for (a=0;a<l;a++)   {
05767                                 if (fObjSel.options[a].selected==1) {
05768                                     localArray_V[c]=fObjSel.options[a].value;
05769                                     localArray_L[c]=fObjSel.options[a].text;
05770                                     localArray_S[c]=1;
05771                                     c++;
05772                                 }
05773                             }
05774                         }
05775                     }
05776                     if (type=="Down")   {
05777                         var tC = 0;
05778                         var tA = new Array();
05779 
05780                         for (a=0;a<l;a++)   {
05781                             if (fObjSel.options[a].selected!=1) {
05782                                     // Add non-selected element:
05783                                 localArray_V[c]=fObjSel.options[a].value;
05784                                 localArray_L[c]=fObjSel.options[a].text;
05785                                 localArray_S[c]=0;
05786                                 c++;
05787 
05788                                     // Transfer any accumulated and reset:
05789                                 if (tA.length > 0)  {
05790                                     for (aa=0;aa<tA.length;aa++)    {
05791                                         localArray_V[c]=fObjSel.options[tA[aa]].value;
05792                                         localArray_L[c]=fObjSel.options[tA[aa]].text;
05793                                         localArray_S[c]=1;
05794                                         c++;
05795                                     }
05796 
05797                                     var tC = 0;
05798                                     var tA = new Array();
05799                                 }
05800                             } else {
05801                                 tA[tC] = a;
05802                                 tC++;
05803                             }
05804                         }
05805                             // Transfer any remaining:
05806                         if (tA.length > 0)  {
05807                             for (aa=0;aa<tA.length;aa++)    {
05808                                 localArray_V[c]=fObjSel.options[tA[aa]].value;
05809                                 localArray_L[c]=fObjSel.options[tA[aa]].text;
05810                                 localArray_S[c]=1;
05811                                 c++;
05812                             }
05813                         }
05814                     }
05815                     if (type=="Up") {
05816                         var tC = 0;
05817                         var tA = new Array();
05818                         var c = l-1;
05819 
05820                         for (a=l-1;a>=0;a--)    {
05821                             if (fObjSel.options[a].selected!=1) {
05822 
05823                                     // Add non-selected element:
05824                                 localArray_V[c]=fObjSel.options[a].value;
05825                                 localArray_L[c]=fObjSel.options[a].text;
05826                                 localArray_S[c]=0;
05827                                 c--;
05828 
05829                                     // Transfer any accumulated and reset:
05830                                 if (tA.length > 0)  {
05831                                     for (aa=0;aa<tA.length;aa++)    {
05832                                         localArray_V[c]=fObjSel.options[tA[aa]].value;
05833                                         localArray_L[c]=fObjSel.options[tA[aa]].text;
05834                                         localArray_S[c]=1;
05835                                         c--;
05836                                     }
05837 
05838                                     var tC = 0;
05839                                     var tA = new Array();
05840                                 }
05841                             } else {
05842                                 tA[tC] = a;
05843                                 tC++;
05844                             }
05845                         }
05846                             // Transfer any remaining:
05847                         if (tA.length > 0)  {
05848                             for (aa=0;aa<tA.length;aa++)    {
05849                                 localArray_V[c]=fObjSel.options[tA[aa]].value;
05850                                 localArray_L[c]=fObjSel.options[tA[aa]].text;
05851                                 localArray_S[c]=1;
05852                                 c--;
05853                             }
05854                         }
05855                         c=l;    // Restore length value in "c"
05856                     }
05857 
05858                         // Transfer items in temporary storage to list object:
05859                     fObjSel.length = c;
05860                     for (a=0;a<c;a++)   {
05861                         fObjSel.options[a].value = localArray_V[a];
05862                         fObjSel.options[a].text = localArray_L[a];
05863                         fObjSel.options[a].selected = localArray_S[a];
05864                     }
05865                     setHiddenFromList(fObjSel,formObj[fName]);
05866 
05867                     ' . $this->TBE_EDITOR_fieldChanged_func . '
05868                 }
05869             }
05870             function setFormValue_getFObj(fName)    {   //
05871                 var formObj = ' . $formObj . ';
05872                 if (formObj) {
05873                         // Take the form object if it is either of type select-one or of type-multiple and it has a "_list" element
05874                     if (formObj[fName] && ((formObj[fName].type == "select-one") || (formObj[fName + "_list"] && formObj[fName + "_list"].type == "select-multiple"))) {
05875                         return formObj;
05876                     } else {
05877                         alert("Formfields missing:\n fName: " + formObj[fName] + "\n fName_list:" + formObj[fName + "_list"] + "\n type:" + formObj[fName + "_list"].type + "\n fName:" + fName);
05878                     }
05879                 }
05880                 return "";
05881             }
05882 
05883             // END: dbFileCon parts.
05884         ';
05885         return $str;
05886     }
05887 
05888     /**
05889      * Prints necessary JavaScript for TCEforms (after the form HTML).
05890      *
05891      * @return  void
05892      */
05893     function printNeededJSFunctions() {
05894             // JS evaluation:
05895         $out = $this->JSbottom($this->formName);
05896 
05897 
05898             // Integrate JS functions for the element browser if such fields or IRRE fields were processed:
05899         if ($this->printNeededJS['dbFileIcons'] || $this->inline->inlineCount) {
05900             $out .= '
05901 
05902 
05903 
05904             <!--
05905                 JavaScript after the form has been drawn:
05906             -->
05907 
05908             <script type="text/javascript">
05909                 /*<![CDATA[*/
05910             ' . $this->dbFileCon('document.' . $this->formName) . '
05911                 /*]]>*/
05912             </script>';
05913         }
05914         return $out;
05915     }
05916 
05917     /**
05918      * Returns necessary JavaScript for the top
05919      *
05920      * @return  void
05921      */
05922     function printNeededJSFunctions_top() {
05923             // JS evaluation:
05924         $out = $this->JStop($this->formName);
05925         return $out;
05926     }
05927 
05928     /**
05929      * Includes a javascript library that exists in the core /typo3/ directory. The
05930      * backpath is automatically applied.
05931      * This method acts as wrapper for $GLOBALS['SOBE']->doc->loadJavascriptLib($lib).
05932      *
05933      * @param   string      $lib: Library name. Call it with the full path like "contrib/prototype/prototype.js" to load it
05934      * @return  void
05935      */
05936     public function loadJavascriptLib($lib) {
05937         $GLOBALS['SOBE']->doc->loadJavascriptLib($lib);
05938     }
05939 
05940 
05941     /********************************************
05942      *
05943      * Various helper functions
05944      *
05945      ********************************************/
05946 
05947 
05948     /**
05949      * Gets default record. Maybe not used anymore. FE-editor?
05950      *
05951      * @param   string      Database Tablename
05952      * @param   integer     PID value (positive / negative)
05953      * @return  array       "default" row.
05954      */
05955     function getDefaultRecord($table, $pid = 0) {
05956         global $TCA;
05957         if ($TCA[$table]) {
05958             t3lib_div::loadTCA($table);
05959             $row = array();
05960 
05961             if ($pid < 0 && $TCA[$table]['ctrl']['useColumnsForDefaultValues']) {
05962                     // Fetches the previous record:
05963                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, 'uid=' . abs($pid) . t3lib_BEfunc::deleteClause($table));
05964                 if ($drow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
05965                         // Gets the list of fields to copy from the previous record.
05966                     $fArr = explode(',', $TCA[$table]['ctrl']['useColumnsForDefaultValues']);
05967                     foreach ($fArr as $theF) {
05968                         if ($TCA[$table]['columns'][$theF]) {
05969                             $row[$theF] = $drow[$theF];
05970                         }
05971                     }
05972                 }
05973                 $GLOBALS['TYPO3_DB']->sql_free_result($res);
05974             }
05975 
05976             foreach ($TCA[$table]['columns'] as $field => $info) {
05977                 if (isset($info['config']['default'])) {
05978                     $row[$field] = $info['config']['default'];
05979                 }
05980             }
05981 
05982             return $row;
05983         }
05984     }
05985 
05986     /**
05987      * Return record path (visually formatted, using t3lib_BEfunc::getRecordPath() )
05988      *
05989      * @param   string      Table name
05990      * @param   array       Record array
05991      * @return  string      The record path.
05992      * @see t3lib_BEfunc::getRecordPath()
05993      */
05994     function getRecordPath($table, $rec) {
05995         t3lib_BEfunc::fixVersioningPid($table, $rec);
05996         list($tscPID, $thePidValue) = $this->getTSCpid($table, $rec['uid'], $rec['pid']);
05997         if ($thePidValue >= 0) {
05998             return t3lib_BEfunc::getRecordPath($tscPID, $this->readPerms(), 15);
05999         }
06000     }
06001 
06002     /**
06003      * Returns the select-page read-access SQL clause.
06004      * Returns cached string, so you can call this function as much as you like without performance loss.
06005      *
06006      * @return  string
06007      */
06008     function readPerms() {
06009         if (!$this->perms_clause_set) {
06010             $this->perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
06011             $this->perms_clause_set = 1;
06012         }
06013         return $this->perms_clause;
06014     }
06015 
06016     /**
06017      * Fetches language label for key
06018      *
06019      * @param   string      Language label reference, eg. 'LLL:EXT:lang/locallang_core.php:labels.blablabla'
06020      * @return  string      The value of the label, fetched for the current backend language.
06021      */
06022     function sL($str) {
06023         return $GLOBALS['LANG']->sL($str);
06024     }
06025 
06026     /**
06027      * Returns language label from locallang_core.php
06028      * Labels must be prefixed with either "l_" or "m_".
06029      * The prefix "l_" maps to the prefix "labels." inside locallang_core.php
06030      * The prefix "m_" maps to the prefix "mess." inside locallang_core.php
06031      *
06032      * @param   string      The label key
06033      * @return  string      The value of the label, fetched for the current backend language.
06034      */
06035     function getLL($str) {
06036         $content = '';
06037 
06038         switch (substr($str, 0, 2)) {
06039             case 'l_':
06040                 $content = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.' . substr($str, 2));
06041             break;
06042             case 'm_':
06043                 $content = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:mess.' . substr($str, 2));
06044             break;
06045         }
06046         return $content;
06047     }
06048 
06049     /**
06050      * Returns true, if the palette, $palette, is collapsed (not shown, but found in top-frame) for the table.
06051      *
06052      * @param   string      The table name
06053      * @param   integer     The palette pointer/number
06054      * @return  boolean
06055      */
06056     function isPalettesCollapsed($table, $palette) {
06057         global $TCA;
06058 
06059         if ($TCA[$table]['ctrl']['canNotCollapse']) {
06060             return 0;
06061         }
06062         if (is_array($TCA[$table]['palettes'][$palette]) && $TCA[$table]['palettes'][$palette]['canNotCollapse']) {
06063             return 0;
06064         }
06065         return $this->palettesCollapsed;
06066     }
06067 
06068     /**
06069      * Returns true, if the evaluation of the required-field code is OK.
06070      *
06071      * @param   string      The required-field code
06072      * @param   array       The record to evaluate
06073      * @param   string      FlexForm value key, eg. vDEF
06074      * @return  boolean
06075      */
06076     function isDisplayCondition($displayCond, $row, $ffValueKey = '') {
06077         $output = FALSE;
06078 
06079         $parts = explode(':', $displayCond);
06080         switch ((string) $parts[0]) { // Type of condition:
06081             case 'FIELD':
06082                 if ($ffValueKey) {
06083                     if (strpos($parts[1], 'parentRec.') !== FALSE) {
06084                         $fParts = explode('.', $parts[1]);
06085                         $theFieldValue = $row['parentRec'][$fParts[1]];
06086                     } else {
06087                         $theFieldValue = $row[$parts[1]][$ffValueKey];
06088                     }
06089                 } else {
06090                     $theFieldValue = $row[$parts[1]];
06091                 }
06092 
06093                 switch ((string) $parts[2]) {
06094                     case 'REQ':
06095                         if (strtolower($parts[3]) == 'true') {
06096                             $output = $theFieldValue ? TRUE : FALSE;
06097                         } elseif (strtolower($parts[3]) == 'false') {
06098                             $output = !$theFieldValue ? TRUE : FALSE;
06099                         }
06100                     break;
06101                     case '>':
06102                         $output = $theFieldValue > $parts[3];
06103                     break;
06104                     case '<':
06105                         $output = $theFieldValue < $parts[3];
06106                     break;
06107                     case '>=':
06108                         $output = $theFieldValue >= $parts[3];
06109                     break;
06110                     case '<=':
06111                         $output = $theFieldValue <= $parts[3];
06112                     break;
06113                     case '-':
06114                     case '!-':
06115                         $cmpParts = explode('-', $parts[3]);
06116                         $output = $theFieldValue >= $cmpParts[0] && $theFieldValue <= $cmpParts[1];
06117                         if ($parts[2]{0} == '!') {
06118                             $output = !$output;
06119                         }
06120                     break;
06121                     case 'IN':
06122                     case '!IN':
06123                         $output = t3lib_div::inList($parts[3], $theFieldValue);
06124                         if ($parts[2]{0} == '!') {
06125                             $output = !$output;
06126                         }
06127                     break;
06128                     case '=':
06129                     case '!=':
06130                         $output = t3lib_div::inList($parts[3], $theFieldValue);
06131                         if ($parts[2]{0} == '!') {
06132                             $output = !$output;
06133                         }
06134                     break;
06135                 }
06136             break;
06137             case 'EXT':
06138                 switch ((string) $parts[2]) {
06139                     case 'LOADED':
06140                         if (strtolower($parts[3]) == 'true') {
06141                             $output = t3lib_extMgm::isLoaded($parts[1]) ? TRUE : FALSE;
06142                         } elseif (strtolower($parts[3]) == 'false') {
06143                             $output = !t3lib_extMgm::isLoaded($parts[1]) ? TRUE : FALSE;
06144                         }
06145                     break;
06146                 }
06147             break;
06148             case 'REC':
06149                 switch ((string) $parts[1]) {
06150                     case 'NEW':
06151                         if (strtolower($parts[2]) == 'true') {
06152                             $output = !(intval($row['uid']) > 0) ? TRUE : FALSE;
06153                         } elseif (strtolower($parts[2]) == 'false') {
06154                             $output = (intval($row['uid']) > 0) ? TRUE : FALSE;
06155                         }
06156                     break;
06157                 }
06158             break;
06159             case 'HIDE_L10N_SIBLINGS':
06160                 if ($ffValueKey === 'vDEF') {
06161                     $output = TRUE;
06162                 } elseif ($parts[1] === 'except_admin' && $GLOBALS['BE_USER']->isAdmin()) {
06163                     $output = TRUE;
06164                 }
06165             break;
06166             case 'HIDE_FOR_NON_ADMINS':
06167                 $output = $GLOBALS['BE_USER']->isAdmin() ? TRUE : FALSE;
06168             break;
06169             case 'VERSION':
06170                 switch ((string) $parts[1]) {
06171                     case 'IS':
06172                         $isNewRecord = (intval($row['uid']) > 0 ? FALSE : TRUE);
06173 
06174                             // detection of version can be done be detecting the workspace of the user
06175                         $isUserInWorkspace = ($GLOBALS['BE_USER']->workspace > 0 ? TRUE : FALSE);
06176                         if (intval($row['pid']) == -1 || intval($row['_ORIG_pid']) == -1) {
06177                             $isRecordDetectedAsVersion = TRUE;
06178                         } else {
06179                             $isRecordDetectedAsVersion = FALSE;
06180                         }
06181 
06182                             // New records in a workspace are not handled as a version record
06183                             // if it's no new version, we detect versions like this:
06184                             // -- if user is in workspace: always true
06185                             // -- if editor is in live ws: only true if pid == -1
06186                         $isVersion = ($isUserInWorkspace || $isRecordDetectedAsVersion) && !$isNewRecord;
06187 
06188                         if (strtolower($parts[2]) == 'true') {
06189                             $output = $isVersion;
06190                         } else {
06191                             if (strtolower($parts[2]) == 'false') {
06192                                 $output = !$isVersion;
06193                             }
06194                         }
06195                     break;
06196                 }
06197             break;
06198         }
06199 
06200         return $output;
06201     }
06202 
06203     /**
06204      * Return TSCpid (cached)
06205      * Using t3lib_BEfunc::getTSCpid()
06206      *
06207      * @param   string      Tablename
06208      * @param   string      UID value
06209      * @param   string      PID value
06210      * @return  integer     Returns the REAL pid of the record, if possible. If both $uid and $pid is strings, then pid=-1 is returned as an error indication.
06211      * @see t3lib_BEfunc::getTSCpid()
06212      */
06213     function getTSCpid($table, $uid, $pid) {
06214         $key = $table . ':' . $uid . ':' . $pid;
06215         if (!isset($this->cache_getTSCpid[$key])) {
06216             $this->cache_getTSCpid[$key] = t3lib_BEfunc::getTSCpid($table, $uid, $pid);
06217         }
06218         return $this->cache_getTSCpid[$key];
06219     }
06220 
06221     /**
06222      * Returns true if descriptions should be loaded always
06223      *
06224      * @param   string      Table for which to check
06225      * @return  boolean
06226      */
06227     function doLoadTableDescr($table) {
06228         global $TCA;
06229         return $TCA[$table]['interface']['always_description'];
06230     }
06231 
06232     /**
06233      * Returns an array of available languages (to use for FlexForms)
06234      *
06235      * @param   boolean     If set, only languages which are paired with a static_info_table / static_language record will be returned.
06236      * @param   boolean     If set, an array entry for a default language is set.
06237      * @return  array
06238      */
06239     function getAvailableLanguages($onlyIsoCoded = 1, $setDefault = 1) {
06240         $isL = t3lib_extMgm::isLoaded('static_info_tables');
06241 
06242             // Find all language records in the system:
06243         $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('static_lang_isocode,title,uid', 'sys_language', 'pid=0 AND hidden=0' . t3lib_BEfunc::deleteClause('sys_language'), '', 'title');
06244 
06245             // Traverse them:
06246         $output = array();
06247         if ($setDefault) {
06248             $output[0] = array(
06249                 'uid' => 0,
06250                 'title' => 'Default language',
06251                 'ISOcode' => 'DEF'
06252             );
06253         }
06254         while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
06255             $output[$row['uid']] = $row;
06256 
06257             if ($isL && $row['static_lang_isocode']) {
06258                 $rr = t3lib_BEfunc::getRecord('static_languages', $row['static_lang_isocode'], 'lg_iso_2');
06259                 if ($rr['lg_iso_2']) {
06260                     $output[$row['uid']]['ISOcode'] = $rr['lg_iso_2'];
06261                 }
06262             }
06263 
06264             if ($onlyIsoCoded && !$output[$row['uid']]['ISOcode']) {
06265                 unset($output[$row['uid']]);
06266             }
06267         }
06268         return $output;
06269     }
06270 
06271     /**
06272      * Initializes language icons etc.
06273      *
06274      * param    string  Table name
06275      * param    array   Record
06276      * param    string  Sys language uid OR ISO language code prefixed with "v", eg. "vDA"
06277      * @return  void
06278      */
06279     function getLanguageIcon($table, $row, $sys_language_uid) {
06280         global $TCA, $LANG;
06281 
06282         $mainKey = $table . ':' . $row['uid'];
06283 
06284         if (!isset($this->cachedLanguageFlag[$mainKey])) {
06285             t3lib_BEfunc::fixVersioningPid($table, $row);
06286             list($tscPID, $thePidValue) = $this->getTSCpid($table, $row['uid'], $row['pid']);
06287 
06288             $t8Tools = t3lib_div::makeInstance('t3lib_transl8tools');
06289             $this->cachedLanguageFlag[$mainKey] = $t8Tools->getSystemLanguages($tscPID, $this->backPath);
06290         }
06291 
06292             // Convert sys_language_uid to sys_language_uid if input was in fact a string (ISO code expected then)
06293         if (!t3lib_div::testInt($sys_language_uid)) {
06294             foreach ($this->cachedLanguageFlag[$mainKey] as $rUid => $cD) {
06295                 if ('v' . $cD['ISOcode'] === $sys_language_uid) {
06296                     $sys_language_uid = $rUid;
06297                 }
06298             }
06299         }
06300 
06301         $out = '';
06302         if ($this->cachedLanguageFlag[$mainKey][$sys_language_uid]['flagIcon']) {
06303             $out .= t3lib_iconWorks::getSpriteIcon($this->cachedLanguageFlag[$mainKey][$sys_language_uid]['flagIcon']);
06304             $out .= '&nbsp;';
06305         } else if ($this->cachedLanguageFlag[$mainKey][$sys_language_uid]['title']) {
06306             $out .= '[' . $this->cachedLanguageFlag[$mainKey][$sys_language_uid]['title'] . ']';
06307             $out .= '&nbsp;';
06308         }
06309         return $out;
06310     }
06311 
06312     /**
06313      * Rendering preview output of a field value which is not shown as a form field but just outputted.
06314      *
06315      * @param   string      The value to output
06316      * @param   array       Configuration for field.
06317      * @param   string      Name of field.
06318      * @return   string     HTML formatted output
06319      */
06320     function previewFieldValue($value, $config, $field = '') {
06321         if ($config['config']['type'] === 'group' &&
06322             ($config['config']['internal_type'] === 'file' ||
06323              $config['config']['internal_type'] === 'file_reference')) {
06324                 // Ignore uploadfolder if internal_type is file_reference
06325             if ($config['config']['internal_type'] === 'file_reference') {
06326                 $config['config']['uploadfolder'] = '';
06327             }
06328 
06329             $show_thumbs = TRUE;
06330             $table = 'tt_content';
06331 
06332                 // Making the array of file items:
06333             $itemArray = t3lib_div::trimExplode(',', $value, 1);
06334 
06335                 // Showing thumbnails:
06336             $thumbsnail = '';
06337             if ($show_thumbs) {
06338                 $imgs = array();
06339                 foreach ($itemArray as $imgRead) {
06340                     $imgP = explode('|', $imgRead);
06341                     $imgPath = rawurldecode($imgP[0]);
06342 
06343                     $rowCopy = array();
06344                     $rowCopy[$field] = $imgPath;
06345 
06346                         // Icon + clickmenu:
06347                     $absFilePath = t3lib_div::getFileAbsFileName($config['config']['uploadfolder'] ? $config['config']['uploadfolder'] . '/' . $imgPath : $imgPath);
06348 
06349                     $fileInformation = pathinfo($imgPath);
06350                     $fileIcon = t3lib_iconWorks::getSpriteIconForFile($imgPath,
06351                         array('title' =>
06352                             htmlspecialchars($fileInformation['basename'] .
06353                                 ($absFilePath && @is_file($absFilePath) ?
06354                                 ' (' . t3lib_div::formatSize(filesize($absFilePath)) . 'bytes)' :
06355                                 ' - FILE NOT FOUND!')
06356                             )
06357                         )
06358                     );
06359 
06360                     $imgs[] = '<span class="nobr">' . t3lib_BEfunc::thumbCode($rowCopy, $table, $field, $this->backPath, 'thumbs.php', $config['config']['uploadfolder'], 0, ' align="middle"') .
06361                               ($absFilePath ? $this->getClickMenu($fileIcon, $absFilePath) : $fileIcon) .
06362                               $imgPath .
06363                               '</span>';
06364                 }
06365                 $thumbsnail = implode('<br />', $imgs);
06366             }
06367 
06368             return $thumbsnail;
06369         } else {
06370             return nl2br(htmlspecialchars($value));
06371         }
06372     }
06373 
06374     /**
06375      * Generates and return information about which languages the current user should see in preview, configured by options.additionalPreviewLanguages
06376      *
06377      * return array Array of additional languages to preview
06378      */
06379     function getAdditionalPreviewLanguages() {
06380         if (!isset($this->cachedAdditionalPreviewLanguages)) {
06381             if ($GLOBALS['BE_USER']->getTSConfigVal('options.additionalPreviewLanguages')) {
06382                 $uids = t3lib_div::intExplode(',', $GLOBALS['BE_USER']->getTSConfigVal('options.additionalPreviewLanguages'));
06383                 foreach ($uids as $uid) {
06384                     if ($sys_language_rec = t3lib_BEfunc::getRecord('sys_language', $uid)) {
06385                         $this->cachedAdditionalPreviewLanguages[$uid] = array('uid' => $uid);
06386 
06387                         if ($sys_language_rec['static_lang_isocode'] && t3lib_extMgm::isLoaded('static_info_tables')) {
06388                             $staticLangRow = t3lib_BEfunc::getRecord('static_languages', $sys_language_rec['static_lang_isocode'], 'lg_iso_2');
06389                             if ($staticLangRow['lg_iso_2']) {
06390                                 $this->cachedAdditionalPreviewLanguages[$uid]['uid'] = $uid;
06391                                 $this->cachedAdditionalPreviewLanguages[$uid]['ISOcode'] = $staticLangRow['lg_iso_2'];
06392                             }
06393                         }
06394                     }
06395                 }
06396             } else {
06397                     // None:
06398                 $this->cachedAdditionalPreviewLanguages = array();
06399             }
06400         }
06401         return $this->cachedAdditionalPreviewLanguages;
06402     }
06403 
06404     /**
06405      * Push a new element to the dynNestedStack. Thus, every object know, if it's
06406      * nested in a tab or IRRE level and in which order this was processed.
06407      *
06408      * @param   string      $type: Type of the level, e.g. "tab" or "inline"
06409      * @param   string      $ident: Identifier of the level
06410      * @return  void
06411      */
06412     function pushToDynNestedStack($type, $ident) {
06413         $this->dynNestedStack[] = array($type, $ident);
06414     }
06415 
06416     /**
06417      * Remove an element from the dynNestedStack. If $type and $ident
06418      * are set, the last element will only be removed, if it matches
06419      * what is expected to be removed.
06420      *
06421      * @param   string      $type: Type of the level, e.g. "tab" or "inline"
06422      * @param   string      $ident: Identifier of the level
06423      * @return  void
06424      */
06425     function popFromDynNestedStack($type = NULL, $ident = NULL) {
06426         if ($type != NULL && $ident != NULL) {
06427             $last = end($this->dynNestedStack);
06428             if ($type == $last[0] && $ident == $last[1]) {
06429                 array_pop($this->dynNestedStack);
06430             }
06431         } else {
06432             array_pop($this->dynNestedStack);
06433         }
06434     }
06435 
06436     /**
06437      * Get the dynNestedStack as associative array.
06438      * The result is e.g. ['tab','DTM-ABCD-1'], ['inline','data[13][table][uid][field]'], ['tab','DTM-DEFG-2'], ...
06439      *
06440      * @param   boolean     $json: Return a JSON string instead of an array - default: false
06441      * @param   boolean     $skipFirst: Skip the first element in the dynNestedStack - default: false
06442      * @return  mixed       Returns an associative array by default. If $json is true, it will be returned as JSON string.
06443      */
06444     function getDynNestedStack($json = FALSE, $skipFirst = FALSE) {
06445         $result = $this->dynNestedStack;
06446         if ($skipFirst) {
06447             array_shift($result);
06448         }
06449         return ($json ? json_encode($result) : $result);
06450     }
06451 
06452     /**
06453      * Takes care of registering properties in requiredFields and requiredElements.
06454      * The current hierarchy of IRRE and/or Tabs is stored. Thus, it is possible to determine,
06455      * which required field/element was filled incorrectly and show it, even if the Tab or IRRE
06456      * level is hidden.
06457      *
06458      * @param   string      $type: Type of requirement ('field' or 'range')
06459      * @param   string      $name: The name of the form field
06460      * @param   mixed       $value: For type 'field' string, for type 'range' array
06461      * @return  void
06462      */
06463     protected function registerRequiredProperty($type, $name, $value) {
06464         if ($type == 'field' && is_string($value)) {
06465             $this->requiredFields[$name] = $value;
06466                 // requiredFields have name/value swapped! For backward compatibility we keep this:
06467             $itemName = $value;
06468         } elseif ($type == 'range' && is_array($value)) {
06469             $this->requiredElements[$name] = $value;
06470             $itemName = $name;
06471         }
06472             // Set the situation of nesting for the current field:
06473         $this->registerNestedElement($itemName);
06474     }
06475 
06476     /**
06477      * Sets the current situation of nested tabs and inline levels for a given element.
06478      *
06479      * @param   string      $itemName: The element the nesting should be stored for
06480      * @param   boolean     $setLevel: Set the reverse level lookup - default: true
06481      * @return  void
06482      */
06483     protected function registerNestedElement($itemName, $setLevel = TRUE) {
06484         $dynNestedStack = $this->getDynNestedStack();
06485         if (count($dynNestedStack) && preg_match('/^(.+\])\[(\w+)\]$/', $itemName, $match)) {
06486             array_shift($match);
06487             $this->requiredNested[$itemName] = array(
06488                 'parts' => $match,
06489                 'level' => $dynNestedStack,
06490             );
06491         }
06492     }
06493 
06494     /**
06495      * Insert additional style sheet link
06496      *
06497      * @param   string      $key: some key identifying the style sheet
06498      * @param   string      $href: uri to the style sheet file
06499      * @param   string      $title: value for the title attribute of the link element
06500      * @return  string      $relation: value for the rel attribute of the link element
06501      * @return  void
06502      */
06503     public function addStyleSheet($key, $href, $title = '', $relation = 'stylesheet') {
06504         $GLOBALS['SOBE']->doc->addStyleSheet($key, $href, $title, $relation);
06505     }
06506 }
06507 
06508 
06509 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tceforms.php'])) {
06510     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tceforms.php']);
06511 }
06512 
06513 ?>