PageRenderTime 93ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/t3lib/class.t3lib_tceforms.php

https://github.com/andreaswolf/typo3-tceforms
PHP | 6513 lines | 4223 code | 671 blank | 1619 comment | 831 complexity | 62ef0b9f429b94ccbed1910110392289 MD5 | raw file
Possible License(s): Apache-2.0, BSD-2-Clause, LGPL-3.0
  1. <?php
  2. /***************************************************************
  3. * Copyright notice
  4. *
  5. * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
  6. * All rights reserved
  7. *
  8. * This script is part of the TYPO3 project. The TYPO3 project is
  9. * free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * The GNU General Public License can be found at
  15. * http://www.gnu.org/copyleft/gpl.html.
  16. * A copy is found in the textfile GPL.txt and important notices to the license
  17. * from the author is found in LICENSE.txt distributed with these scripts.
  18. *
  19. *
  20. * This script is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * This copyright notice MUST APPEAR in all copies of the script!
  26. ***************************************************************/
  27. /**
  28. * Contains TYPO3 Core Form generator - AKA "TCEforms"
  29. *
  30. * $Id$
  31. * Revised for TYPO3 3.6 August/2003 by Kasper Skårhøj
  32. * XHTML compliant
  33. *
  34. * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  35. */
  36. /**
  37. * [CLASS/FUNCTION INDEX of SCRIPT]
  38. *
  39. *
  40. *
  41. * 196: class t3lib_TCEforms
  42. * 302: function t3lib_TCEforms()
  43. * 338: function initDefaultBEmode()
  44. *
  45. * SECTION: Rendering the forms, fields etc
  46. * 385: function getSoloField($table,$row,$theFieldToReturn)
  47. * 424: function getMainFields($table,$row,$depth=0)
  48. * 618: function getListedFields($table,$row,$list)
  49. * 660: function getPaletteFields($table,$row,$palette,$header='',$itemList='',$collapsedHeader='')
  50. * 737: function getSingleField($table,$field,$row,$altName='',$palette=0,$extra='',$pal=0)
  51. * 900: function getSingleField_SW($table,$field,$row,&$PA)
  52. *
  53. * SECTION: Rendering of each TCEform field type
  54. * 976: function getSingleField_typeInput($table,$field,$row,&$PA)
  55. * 1057: function getSingleField_typeText($table,$field,$row,&$PA)
  56. * 1178: function getSingleField_typeCheck($table,$field,$row,&$PA)
  57. * 1244: function getSingleField_typeRadio($table,$field,$row,&$PA)
  58. * 1279: function getSingleField_typeSelect($table,$field,$row,&$PA)
  59. * 1359: function getSingleField_typeSelect_single($table,$field,$row,&$PA,$config,$selItems,$nMV_label)
  60. * 1490: function getSingleField_typeSelect_checkbox($table,$field,$row,&$PA,$config,$selItems,$nMV_label)
  61. * 1609: function getSingleField_typeSelect_singlebox($table,$field,$row,&$PA,$config,$selItems,$nMV_label)
  62. * 1719: function getSingleField_typeSelect_multiple($table,$field,$row,&$PA,$config,$selItems,$nMV_label)
  63. * 1823: function getSingleField_typeGroup($table,$field,$row,&$PA)
  64. * 1992: function getSingleField_typeNone($table,$field,$row,&$PA)
  65. * 2008: function getSingleField_typeNone_render($config,$itemValue)
  66. * 2070: function getSingleField_typeFlex($table,$field,$row,&$PA)
  67. * 2205: function getSingleField_typeFlex_langMenu($languages,$elName,$selectedLanguage,$multi=1)
  68. * 2224: function getSingleField_typeFlex_sheetMenu($sArr,$elName,$sheetKey)
  69. * 2259: function getSingleField_typeFlex_draw($dataStruct,$editData,$cmdData,$table,$field,$row,&$PA,$formPrefix='',$level=0,$tRows=array())
  70. * 2452: function getSingleField_typeUnknown($table,$field,$row,&$PA)
  71. * 2467: function getSingleField_typeUser($table,$field,$row,&$PA)
  72. *
  73. * SECTION: Field content processing
  74. * 2496: function formatValue ($config, $itemValue)
  75. *
  76. * SECTION: "Configuration" fetching/processing functions
  77. * 2588: function getRTypeNum($table,$row)
  78. * 2614: function rearrange($fields)
  79. * 2640: function getExcludeElements($table,$row,$typeNum)
  80. * 2688: function getFieldsToAdd($table,$row,$typeNum)
  81. * 2713: function mergeFieldsWithAddedFields($fields,$fieldsToAdd)
  82. * 2745: function setTSconfig($table,$row,$field='')
  83. * 2767: function getSpecConfForField($table,$row,$field)
  84. * 2788: function getSpecConfFromString($extraString, $defaultExtras)
  85. * 3007: function loadPaletteElements($table, $row, $palette, $itemList='')
  86. *
  87. * SECTION: Display of localized content etc.
  88. * 2816: function registerDefaultLanguageData($table,$rec)
  89. * 2848: function getLanguageOverlayRawValue($table, $row, $field, $fieldConf)
  90. * 2876: function renderDefaultLanguageContent($table,$field,$row,$item)
  91. * 2899: function renderDefaultLanguageDiff($table,$field,$row,$item)
  92. *
  93. * SECTION: Form element helper functions
  94. * 2955: function dbFileIcons($fName,$mode,$allowed,$itemArray,$selector='',$params=array(),$onFocus='')
  95. * 3108: function getClipboardElements($allowed,$mode)
  96. * 3157: function getClickMenu($str,$table,$uid='')
  97. * 3178: function renderWizards($itemKinds,$wizConf,$table,$row,$field,&$PA,$itemName,$specConf,$RTE=0)
  98. * 3382: function getIcon($icon)
  99. * 3409: function optionTagStyle($iconString)
  100. * 3425: function extractValuesOnlyFromValueLabelList($itemFormElValue)
  101. * 3447: function wrapOpenPalette($header,$table,$row,$palette,$retFunc=0)
  102. * 3471: function checkBoxParams($itemName,$thisValue,$c,$iCount,$addFunc='')
  103. * 3485: function elName($itemName)
  104. * 3496: function noTitle($str,$wrapParts=array())
  105. * 3505: function blur()
  106. * 3514: function thisReturnUrl()
  107. * 3527: function getSingleHiddenField($table,$field,$row)
  108. * 3549: function formWidth($size=48,$textarea=0)
  109. * 3576: function formWidthText($size=48,$wrap='')
  110. * 3592: function formElStyle($type)
  111. * 3603: function formElClass($type)
  112. * 3614: function formElStyleClassValue($type, $class=FALSE)
  113. * 3638: function insertDefStyle($type)
  114. * 3657: function getDynTabMenu($parts, $idString)
  115. *
  116. * SECTION: Item-array manipulation functions (check/select/radio)
  117. * 3696: function initItemArray($fieldValue)
  118. * 3714: function addItems($items,$iArray)
  119. * 3736: function procItems($items,$iArray,$config,$table,$row,$field)
  120. * 3760: function addSelectOptionsToItemArray($items,$fieldValue,$TSconfig,$field)
  121. * 3980: function addSelectOptionsToItemArray_makeModuleData($value)
  122. * 4002: function foreignTable($items,$fieldValue,$TSconfig,$field,$pFFlag=0)
  123. *
  124. * SECTION: Template functions
  125. * 4083: function setNewBEDesign()
  126. * 4138: function intoTemplate($inArr,$altTemplate='')
  127. * 4162: function addUserTemplateMarkers($marker,$table,$field,$row,&$PA)
  128. * 4173: function wrapLabels($str)
  129. * 4186: function wrapTotal($c,$rec,$table)
  130. * 4199: function replaceTableWrap($arr,$rec,$table)
  131. * 4236: function wrapBorder(&$out_array,&$out_pointer)
  132. * 4258: function rplColorScheme($inTemplate)
  133. * 4278: function getDivider()
  134. * 4288: function printPalette($palArr)
  135. * 4339: function helpTextIcon($table,$field,$force=0)
  136. * 4359: function helpText($table,$field)
  137. * 4380: function setColorScheme($scheme)
  138. * 4404: function resetSchemes()
  139. * 4415: function storeSchemes()
  140. * 4427: function restoreSchemes()
  141. *
  142. * SECTION: JavaScript related functions
  143. * 4457: function JStop()
  144. * 4508: function JSbottom($formname='forms[0]')
  145. * 4835: function dbFileCon($formObj='document.forms[0]')
  146. * 5053: function printNeededJSFunctions()
  147. * 5080: function printNeededJSFunctions_top()
  148. *
  149. * SECTION: Various helper functions
  150. * 5128: function getDefaultRecord($table,$pid=0)
  151. * 5167: function getRecordPath($table,$rec)
  152. * 5181: function readPerms()
  153. * 5195: function sL($str)
  154. * 5208: function getLL($str)
  155. * 5229: function isPalettesCollapsed($table,$palette)
  156. * 5245: function isDisplayCondition($displayCond,$row,$ffValueKey='')
  157. * 5349: function getTSCpid($table,$uid,$pid)
  158. * 5363: function doLoadTableDescr($table)
  159. * 5375: function getAvailableLanguages($onlyIsoCoded=1,$setDefault=1)
  160. *
  161. *
  162. * 5417: class t3lib_TCEforms_FE extends t3lib_TCEforms
  163. * 5425: function wrapLabels($str)
  164. * 5435: function printPalette($palArr)
  165. * 5460: function setFancyDesign()
  166. *
  167. * TOTAL FUNCTIONS: 100
  168. * (This index is automatically created/updated by the extension "extdeveval")
  169. *
  170. */
  171. /**
  172. * 'TCEforms' - Class for creating the backend editing forms.
  173. *
  174. * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  175. * @coauthor René Fritz <r.fritz@colorcube.de>
  176. * @package TYPO3
  177. * @subpackage t3lib
  178. */
  179. class t3lib_TCEforms {
  180. // variables not commented yet.... (do so...)
  181. var $palFieldArr = array();
  182. var $disableWizards = 0;
  183. var $isPalettedoc = 0;
  184. var $paletteMargin = 1;
  185. var $defStyle = ''; // 'font-family:Verdana;font-size:10px;';
  186. var $cachedTSconfig = array();
  187. var $cachedTSconfig_fieldLevel = array();
  188. var $cachedLanguageFlag = array();
  189. var $cachedAdditionalPreviewLanguages = NULL;
  190. var $transformedRow = array();
  191. var $extJSCODE = '';
  192. var $printNeededJS = array();
  193. var $hiddenFieldAccum = array();
  194. var $TBE_EDITOR_fieldChanged_func = '';
  195. var $loadMD5_JS = 1;
  196. var $prevBorderStyle = '[nothing here...]'; // Something unique...
  197. var $allowUpload = 0; // If set direct upload fields will be shown
  198. var $titleLen = 15; // @deprecated since TYPO3 4.1: $BE_USER->uc['titleLen'] but what is default??
  199. var $defaultLanguageData = array(); // Array where records in the default language is stored. (processed by transferdata)
  200. var $defaultLanguageData_diff = array(); // Array where records in the default language is stored (raw without any processing. used for making diff)
  201. var $additionalPreviewLanguageData = array();
  202. // EXTERNAL, static
  203. var $backPath = ''; // Set this to the 'backPath' pointing back to the typo3 admin directory from the script where this form is displayed.
  204. var $returnUrl = ''; // Alternative return URL path (default is t3lib_div::linkThisScript())
  205. 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.
  206. 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.
  207. var $disableRTE = 0; // If set, the RTE is disabled (from form display, eg. by checkbox in the bottom of the page!)
  208. var $globalShowHelp = 1; // If false, then all CSH will be disabled, regardless of settings in $this->edit_showFieldHelp
  209. var $localizationMode = ''; // If true, the forms are rendering only localization relevant fields of the records.
  210. 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.
  211. var $doPrintPalette = 1; // If set to false, palettes will NEVER be rendered.
  212. /**
  213. * Set to initialized clipboard object; Then the element browser will offer a link to paste in records from clipboard.
  214. *
  215. * @var t3lib_clipboard
  216. */
  217. var $clipObj = FALSE;
  218. var $enableClickMenu = FALSE; // Enable click menu on reference icons.
  219. var $enableTabMenu = FALSE; // Enable Tab Menus.
  220. var $renderReadonly = FALSE; // When enabled all fields are rendered non-editable.
  221. 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)
  222. var $form_largeComp = 1.33; // Form field width compensation: Compensation for large documents, doc-tab (editing)
  223. 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.
  224. var $maxTextareaWidth = 48; // The maximum abstract value for textareas
  225. var $maxInputWidth = 48; // The maximum abstract value for input fields
  226. var $defaultMultipleSelectorStyle = 'width:250px;'; // Default style for the selector boxes used for multiple items in "select" and "group" types.
  227. // INTERNAL, static
  228. var $prependFormFieldNames = 'data'; // The string to prepend formfield names with.
  229. var $prependCmdFieldNames = 'cmd'; // The string to prepend commands for tcemain::process_cmdmap with.
  230. var $prependFormFieldNames_file = 'data_files'; // The string to prepend FILE form field names with.
  231. var $formName = 'editform'; // The name attribute of the form.
  232. var $allowOverrideMatrix = array(); // Whitelist that allows TCA field configuration to be overridden by TSconfig, @see overrideFieldConf()
  233. // INTERNAL, dynamic
  234. var $perms_clause = ''; // Set by readPerms() (caching)
  235. var $perms_clause_set = 0; // Set by readPerms() (caching-flag)
  236. 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).
  237. var $docLarge = 0; // If set, the forms will be rendered a little wider, more precisely with a factor of $this->form_largeComp.
  238. var $clientInfo = array(); // Loaded with info about the browser when class is instantiated.
  239. var $RTEenabled = 0; // True, if RTE is possible for the current user (based on result from BE_USER->isRTE())
  240. 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)
  241. var $RTEcounter = 0; // Counter that is incremented before an RTE is created. Can be used for unique ids etc.
  242. var $colorScheme; // Contains current color scheme
  243. var $classScheme; // Contains current class scheme
  244. var $defColorScheme; // Contains the default color scheme
  245. var $defClassScheme; // Contains the default class scheme
  246. var $fieldStyle; // Contains field style values
  247. var $borderStyle; // Contains border style values.
  248. var $commentMessages = array(); // An accumulation of messages from the class.
  249. // INTERNAL, templates
  250. var $totalWrap = '<hr />|<hr />'; // Total wrapping for the table rows.
  251. var $fieldTemplate = '<strong>###FIELD_NAME###</strong><br />###FIELD_ITEM###<hr />'; // Field template
  252. var $sectionWrap = ''; // Wrapping template code for a section
  253. var $palFieldTemplateHeader = ''; // Template for palette headers
  254. var $palFieldTemplate = ''; // Template for palettes
  255. // INTERNAL, working memory
  256. var $excludeElements = ''; // Set to the fields NOT to display, if any.
  257. 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)
  258. 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!
  259. 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.
  260. 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.
  261. var $requiredElements = array(); // Used to register the min and max number of elements for selectorboxes where that apply (in the "group" type for instance)
  262. var $requiredNested = array(); // Used to determine where $requiredFields or $requiredElements are nested (in Tabs or IRRE)
  263. var $renderDepth = 0; // Keeps track of the rendering depth of nested records.
  264. var $savedSchemes = array(); // Color scheme buffer.
  265. var $dynNestedStack = array(); // holds the path an element is nested in (e.g. required for RTEhtmlarea)
  266. // Internal, registers for user defined functions etc.
  267. var $additionalCode_pre = array(); // Additional HTML code, printed before the form.
  268. var $additionalJS_pre = array(); // Additional JavaScript, printed before the form
  269. var $additionalJS_post = array(); // Additional JavaScript printed after the form
  270. 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.
  271. 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)
  272. /**
  273. * Instance of t3lib_tceforms_inline
  274. *
  275. * @var t3lib_TCEforms_inline
  276. */
  277. var $inline;
  278. var $hookObjectsMainFields = array(); // Array containing hook class instances called once for a form
  279. var $hookObjectsSingleField = array(); // Array containing hook class instances called for each field
  280. var $extraFormHeaders = array(); // Rows gettings inserted into the alt_doc headers (when called from alt_doc.php)
  281. public $templateFile = ''; // Form templates, relative to typo3 directory
  282. /**
  283. * Constructor function, setting internal variables, loading the styles used.
  284. *
  285. * @return void
  286. */
  287. function t3lib_TCEforms() {
  288. global $CLIENT, $TYPO3_CONF_VARS;
  289. $this->clientInfo = t3lib_div::clientInfo();
  290. $this->RTEenabled = $GLOBALS['BE_USER']->isRTE();
  291. if (!$this->RTEenabled) {
  292. $this->RTEenabled_notReasons = implode(LF, $GLOBALS['BE_USER']->RTE_errors);
  293. $this->commentMessages[] = 'RTE NOT ENABLED IN SYSTEM due to:' . LF . $this->RTEenabled_notReasons;
  294. }
  295. // Default color+class scheme
  296. $this->defColorScheme = array(
  297. $GLOBALS['SOBE']->doc->bgColor, // Background for the field AND palette
  298. t3lib_div::modifyHTMLColorAll($GLOBALS['SOBE']->doc->bgColor, -20), // Background for the field header
  299. t3lib_div::modifyHTMLColorAll($GLOBALS['SOBE']->doc->bgColor, -10), // Background for the palette field header
  300. 'black', // Field header font color
  301. '#666666' // Palette field header font color
  302. );
  303. $this->defColorScheme = array();
  304. // Override / Setting defaults from TBE_STYLES array
  305. $this->resetSchemes();
  306. // Setting the current colorScheme to default.
  307. $this->defColorScheme = $this->colorScheme;
  308. $this->defClassScheme = $this->classScheme;
  309. // Define whitelist that allows TCA field configuration to be overridden by TSconfig, @see overrideFieldConf():
  310. $this->allowOverrideMatrix = array(
  311. 'input' => array('size', 'max'),
  312. 'text' => array('cols', 'rows', 'wrap'),
  313. 'check' => array('cols', 'showIfRTE'),
  314. 'select' => array('size', 'autoSizeMax', 'maxitems', 'minitems'),
  315. 'group' => array('size', 'autoSizeMax', 'max_size', 'show_thumbs', 'maxitems', 'minitems', 'disable_controls'),
  316. 'inline' => array('appearance', 'behaviour', 'foreign_label', 'foreign_selector', 'foreign_unique', 'maxitems', 'minitems', 'size', 'autoSizeMax', 'symmetric_label'),
  317. );
  318. // Create instance of t3lib_TCEforms_inline only if this a non-IRRE-AJAX call:
  319. if (!isset($GLOBALS['ajaxID']) || strpos($GLOBALS['ajaxID'], 't3lib_TCEforms_inline::') !== 0) {
  320. $this->inline = t3lib_div::makeInstance('t3lib_TCEforms_inline');
  321. }
  322. // Create instance of t3lib_TCEforms_suggest only if this a non-Suggest-AJAX call:
  323. if (!isset($GLOBALS['ajaxID']) || strpos($GLOBALS['ajaxID'], 't3lib_TCEforms_suggest::') !== 0) {
  324. $this->suggest = t3lib_div::makeInstance('t3lib_TCEforms_suggest');
  325. }
  326. // Prepare user defined objects (if any) for hooks which extend this function:
  327. $this->hookObjectsMainFields = array();
  328. if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getMainFieldsClass'])) {
  329. foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getMainFieldsClass'] as $classRef) {
  330. $this->hookObjectsMainFields[] = t3lib_div::getUserObj($classRef);
  331. }
  332. }
  333. $this->hookObjectsSingleField = array();
  334. if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getSingleFieldClass'])) {
  335. foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getSingleFieldClass'] as $classRef) {
  336. $this->hookObjectsSingleField[] = t3lib_div::getUserObj($classRef);
  337. }
  338. }
  339. $this->templateFile = 'templates/tceforms.html';
  340. }
  341. /**
  342. * Initialize various internal variables.
  343. *
  344. * @return void
  345. */
  346. function initDefaultBEmode() {
  347. global $BE_USER;
  348. $this->prependFormFieldNames = 'data';
  349. $this->formName = 'editform';
  350. $this->setNewBEDesign();
  351. $this->docLarge = $BE_USER->uc['edit_wideDocument'] ? 1 : 0;
  352. $this->edit_showFieldHelp = $BE_USER->uc['edit_showFieldHelp'];
  353. $this->edit_docModuleUpload = $BE_USER->uc['edit_docModuleUpload'];
  354. $this->titleLen = $BE_USER->uc['titleLen']; // @deprecated since TYPO3 4.1
  355. $this->inline->init($this);
  356. $this->suggest->init($this);
  357. }
  358. /*******************************************************
  359. *
  360. * Rendering the forms, fields etc
  361. *
  362. *******************************************************/
  363. /**
  364. * Will return the TCEform element for just a single field from a record.
  365. * The field must be listed in the currently displayed fields (as found in [types][showitem]) for the record.
  366. * This also means that the $table/$row supplied must be complete so the list of fields to show can be found correctly
  367. *
  368. * @param string The table name
  369. * @param array The record from the table for which to render a field.
  370. * @param string The field name to return the TCEform element for.
  371. * @return string HTML output
  372. * @see getMainFields()
  373. */
  374. function getSoloField($table, $row, $theFieldToReturn) {
  375. global $TCA;
  376. if ($TCA[$table]) {
  377. t3lib_div::loadTCA($table);
  378. $typeNum = $this->getRTypeNum($table, $row);
  379. if ($TCA[$table]['types'][$typeNum]) {
  380. $itemList = $TCA[$table]['types'][$typeNum]['showitem'];
  381. if ($itemList) {
  382. $fields = t3lib_div::trimExplode(',', $itemList, 1);
  383. $excludeElements = $this->excludeElements = $this->getExcludeElements($table, $row, $typeNum);
  384. foreach ($fields as $fieldInfo) {
  385. $parts = explode(';', $fieldInfo);
  386. $theField = trim($parts[0]);
  387. if (!in_array($theField, $excludeElements) && !strcmp($theField, $theFieldToReturn)) {
  388. if ($TCA[$table]['columns'][$theField]) {
  389. $sField = $this->getSingleField($table, $theField, $row, $parts[1], 1, $parts[3], $parts[2]);
  390. return $sField['ITEM'];
  391. }
  392. }
  393. }
  394. }
  395. }
  396. }
  397. }
  398. /**
  399. * Based on the $table and $row of content, this displays the complete TCEform for the record.
  400. * 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.
  401. *
  402. * @param string The table name
  403. * @param array The record from the table for which to render a field.
  404. * @param integer Depth level
  405. * @return string HTML output
  406. * @see getSoloField()
  407. */
  408. function getMainFields($table, $row, $depth = 0) {
  409. global $TCA, $TYPO3_CONF_VARS;
  410. $this->renderDepth = $depth;
  411. // Init vars:
  412. $out_array = array(array());
  413. $out_array_meta = array(array(
  414. 'title' => $this->getLL('l_generalTab')
  415. ));
  416. $out_pointer = 0;
  417. $out_sheet = 0;
  418. $this->palettesRendered = array();
  419. $this->palettesRendered[$this->renderDepth][$table] = array();
  420. // Hook: getMainFields_preProcess (requested by Thomas Hempel for use with the "dynaflex" extension)
  421. foreach ($this->hookObjectsMainFields as $hookObj) {
  422. if (method_exists($hookObj, 'getMainFields_preProcess')) {
  423. $hookObj->getMainFields_preProcess($table, $row, $this);
  424. }
  425. }
  426. if ($TCA[$table]) {
  427. // Load the full TCA for the table.
  428. t3lib_div::loadTCA($table);
  429. // Get dividers2tabs setting from TCA of the current table:
  430. $dividers2tabs =& $TCA[$table]['ctrl']['dividers2tabs'];
  431. // Load the description content for the table.
  432. if ($this->edit_showFieldHelp || $this->doLoadTableDescr($table)) {
  433. $GLOBALS['LANG']->loadSingleTableDescription($table);
  434. }
  435. // Get the current "type" value for the record.
  436. $typeNum = $this->getRTypeNum($table, $row);
  437. // Find the list of fields to display:
  438. if ($TCA[$table]['types'][$typeNum]) {
  439. $itemList = $TCA[$table]['types'][$typeNum]['showitem'];
  440. if ($itemList) { // If such a list existed...
  441. // Explode the field list and possibly rearrange the order of the fields, if configured for
  442. $fields = t3lib_div::trimExplode(',', $itemList, 1);
  443. if ($this->fieldOrder) {
  444. $fields = $this->rearrange($fields);
  445. }
  446. // Get excluded fields, added fiels and put it together:
  447. $excludeElements = $this->excludeElements = $this->getExcludeElements($table, $row, $typeNum);
  448. $fields = $this->mergeFieldsWithAddedFields($fields, $this->getFieldsToAdd($table, $row, $typeNum));
  449. // If TCEforms will render a tab menu in the next step, push the name to the tab stack:
  450. $tabIdentString = '';
  451. $tabIdentStringMD5 = '';
  452. if (strstr($itemList, '--div--') !== false && $this->enableTabMenu && $dividers2tabs) {
  453. $tabIdentString = 'TCEforms:' . $table . ':' . $row['uid'];
  454. $tabIdentStringMD5 = $GLOBALS['TBE_TEMPLATE']->getDynTabMenuId($tabIdentString);
  455. // Remember that were currently working on the general tab:
  456. if (isset($fields[0]) && strpos($fields[0], '--div--') !== 0) {
  457. $this->pushToDynNestedStack('tab', $tabIdentStringMD5 . '-1');
  458. }
  459. }
  460. // Traverse the fields to render:
  461. $cc = 0;
  462. foreach ($fields as $fieldInfo) {
  463. // Exploding subparts of the field configuration:
  464. $parts = explode(';', $fieldInfo);
  465. // Getting the style information out:
  466. $color_style_parts = t3lib_div::trimExplode('-', $parts[4]);
  467. if (strcmp($color_style_parts[0], '')) {
  468. $this->setColorScheme($GLOBALS['TBE_STYLES']['colorschemes'][intval($color_style_parts[0])]);
  469. }
  470. if (strcmp($color_style_parts[1], '')) {
  471. $this->fieldStyle = $GLOBALS['TBE_STYLES']['styleschemes'][intval($color_style_parts[1])];
  472. if (!isset($this->fieldStyle)) {
  473. $this->fieldStyle = $GLOBALS['TBE_STYLES']['styleschemes'][0];
  474. }
  475. }
  476. if (strcmp($color_style_parts[2], '')) {
  477. $this->wrapBorder($out_array[$out_sheet], $out_pointer);
  478. $this->borderStyle = $GLOBALS['TBE_STYLES']['borderschemes'][intval($color_style_parts[2])];
  479. if (!isset($this->borderStyle)) {
  480. $this->borderStyle = $GLOBALS['TBE_STYLES']['borderschemes'][0];
  481. }
  482. }
  483. // Render the field:
  484. $theField = $parts[0];
  485. if (!in_array($theField, $excludeElements)) {
  486. if ($TCA[$table]['columns'][$theField]) {
  487. $sFieldPal = '';
  488. if ($parts[2] && !isset($this->palettesRendered[$this->renderDepth][$table][$parts[2]])) {
  489. $sFieldPal = $this->getPaletteFields($table, $row, $parts[2]);
  490. $this->palettesRendered[$this->renderDepth][$table][$parts[2]] = 1;
  491. }
  492. $sField = $this->getSingleField($table, $theField, $row, $parts[1], 0, $parts[3], $parts[2]);
  493. if ($sField) {
  494. $sField .= $sFieldPal;
  495. }
  496. $out_array[$out_sheet][$out_pointer] .= $sField;
  497. } elseif ($theField == '--div--') {
  498. if ($cc > 0) {
  499. $out_array[$out_sheet][$out_pointer] .= $this->getDivider();
  500. if ($this->enableTabMenu && $dividers2tabs) {
  501. $this->wrapBorder($out_array[$out_sheet], $out_pointer);
  502. // Remove last tab entry from the dynNestedStack:
  503. $out_sheet++;
  504. // Remove the previous sheet from stack (if any):
  505. $this->popFromDynNestedStack('tab', $tabIdentStringMD5 . '-' . ($out_sheet));
  506. // Remember on which sheet we're currently working:
  507. $this->pushToDynNestedStack('tab', $tabIdentStringMD5 . '-' . ($out_sheet + 1));
  508. $out_array[$out_sheet] = array();
  509. $out_array_meta[$out_sheet]['title'] = $this->sL($parts[1]);
  510. // Register newline for Tab
  511. $out_array_meta[$out_sheet]['newline'] = ($parts[2] == "newline");
  512. }
  513. } else { // Setting alternative title for "General" tab if "--div--" is the very first element.
  514. $out_array_meta[$out_sheet]['title'] = $this->sL($parts[1]);
  515. // Only add the first tab to the dynNestedStack if there are more tabs:
  516. if ($tabIdentString && strpos($itemList, '--div--', strlen($fieldInfo))) {
  517. $this->pushToDynNestedStack('tab', $tabIdentStringMD5 . '-1');
  518. }
  519. }
  520. } elseif ($theField == '--palette--') {
  521. if ($parts[2] && !isset($this->palettesRendered[$this->renderDepth][$table][$parts[2]])) {
  522. // render a 'header' if not collapsed
  523. if ($TCA[$table]['palettes'][$parts[2]]['canNotCollapse'] AND $parts[1]) {
  524. $out_array[$out_sheet][$out_pointer] .= $this->getPaletteFields($table, $row, $parts[2], $this->sL($parts[1]));
  525. } else {
  526. $out_array[$out_sheet][$out_pointer] .= $this->getPaletteFields($table, $row, $parts[2], '', '', $this->sL($parts[1]));
  527. }
  528. $this->palettesRendered[$this->renderDepth][$table][$parts[2]] = 1;
  529. }
  530. }
  531. }
  532. $cc++;
  533. }
  534. }
  535. }
  536. }
  537. // Hook: getMainFields_postProcess (requested by Thomas Hempel for use with the "dynaflex" extension)
  538. foreach ($this->hookObjectsMainFields as $hookObj) {
  539. if (method_exists($hookObj, 'getMainFields_postProcess')) {
  540. $hookObj->getMainFields_postProcess($table, $row, $this);
  541. }
  542. }
  543. // Wrapping a border around it all:
  544. $this->wrapBorder($out_array[$out_sheet], $out_pointer);
  545. // Resetting styles:
  546. $this->resetSchemes();
  547. // Rendering Main palettes, if any
  548. $mParr = t3lib_div::trimExplode(',', $TCA[$table]['ctrl']['mainpalette']);
  549. $i = 0;
  550. if (count($mParr)) {
  551. foreach ($mParr as $mP) {
  552. if (!isset($this->palettesRendered[$this->renderDepth][$table][$mP])) {
  553. $temp_palettesCollapsed = $this->palettesCollapsed;
  554. $this->palettesCollapsed = 0;
  555. $label = ($i == 0 ? $this->getLL('l_generalOptions') : $this->getLL('l_generalOptions_more'));
  556. $out_array[$out_sheet][$out_pointer] .= $this->getPaletteFields($table, $row, $mP, $label);
  557. $this->palettesCollapsed = $temp_palettesCollapsed;
  558. $this->palettesRendered[$this->renderDepth][$table][$mP] = 1;
  559. }
  560. $this->wrapBorder($out_array[$out_sheet], $out_pointer);
  561. $i++;
  562. if ($this->renderDepth) {
  563. $this->renderDepth--;
  564. }
  565. }
  566. }
  567. // Return the imploded $out_array:
  568. if ($out_sheet > 0) { // There were --div-- dividers around...
  569. // Create parts array for the tab menu:
  570. $parts = array();
  571. foreach ($out_array as $idx => $sheetContent) {
  572. $content = implode('', $sheetContent);
  573. if ($content) {
  574. // Wrap content (row) with table-tag, otherwise tab/sheet will be disabled (see getdynTabMenu() )
  575. $content = '<table border="0" cellspacing="0" cellpadding="0" width="100%">' . $content . '</table>';
  576. }
  577. $parts[$idx] = array(
  578. 'label' => $out_array_meta[$idx]['title'],
  579. 'content' => $content,
  580. 'newline' => $out_array_meta[$idx]['newline'], // Newline for this tab/sheet
  581. );
  582. }
  583. if (count($parts) > 1) {
  584. // Unset the current level of tab menus:
  585. $this->popFromDynNestedStack('tab', $tabIdentStringMD5 . '-' . ($out_sheet + 1));
  586. $dividersToTabsBehaviour = (isset($TCA[$table]['ctrl']['dividers2tabs']) ? $TCA[$table]['ctrl']['dividers2tabs'] : 1);
  587. $output = $this->getDynTabMenu($parts, $tabIdentString, $dividersToTabsBehaviour);
  588. } else {
  589. // If there is only one tab/part there is no need to wrap it into the dynTab code
  590. $output = isset($parts[0]) ? trim($parts[0]['content']) : '';
  591. }
  592. $output = '
  593. <tr>
  594. <td colspan="2">
  595. ' . $output . '
  596. </td>
  597. </tr>';
  598. } else {
  599. // Only one, so just implode:
  600. $output = implode('', $out_array[$out_sheet]);
  601. }
  602. return $output;
  603. }
  604. /**
  605. * Will return the TCEform elements for a pre-defined list of fields.
  606. * 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.
  607. * Used for displaying forms for the frontend edit icons for instance.
  608. *
  609. * @param string The table name
  610. * @param array The record array.
  611. * @param string Commalist of fields from the table. These will be shown in the specified order in a form.
  612. * @return string TCEform elements in a string.
  613. */
  614. function getListedFields($table, $row, $list) {
  615. global $TCA;
  616. t3lib_div::loadTCA($table);
  617. if ($this->edit_showFieldHelp || $this->doLoadTableDescr($table)) {
  618. $GLOBALS['LANG']->loadSingleTableDescription($table);
  619. }
  620. $out = '';
  621. $types_fieldConfig = t3lib_BEfunc::getTCAtypes($table, $row, 1);
  622. $editFieldList = array_unique(t3lib_div::trimExplode(',', $list, 1));
  623. foreach ($editFieldList as $theFieldC) {
  624. list($theField, $palFields) = preg_split('/\[|\]/', $theFieldC);
  625. $theField = trim($theField);
  626. $palFields = trim($palFields);
  627. if ($TCA[$table]['columns'][$theField]) {
  628. $parts = t3lib_div::trimExplode(';', $types_fieldConfig[$theField]['origString']);
  629. $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.
  630. $out .= $sField;
  631. } elseif ($theField == '--div--') {
  632. $out .= $this->getDivider();
  633. }
  634. if ($palFields) {
  635. $out .= $this->getPaletteFields($table, $row, '', '', implode(',', t3lib_div::trimExplode('|', $palFields, 1)));
  636. }
  637. }
  638. return $out;
  639. }
  640. /**
  641. * Creates a palette (collection of secondary options).
  642. *
  643. * @param string The table name
  644. * @param array The row array
  645. * @param string The palette number/pointer
  646. * @param string Header string for the palette (used when in-form). If not set, no header item is made.
  647. * @param string Optional alternative list of fields for the palette
  648. * @param string Optional Link text for activating a palette (when palettes does not have another form element to belong to).
  649. * @return string HTML code.
  650. */
  651. function getPaletteFields($table, $row, $palette, $header = '', $itemList = '', $collapsedHeader = NULL) {
  652. if (!$this->doPrintPalette) {
  653. return '';
  654. }
  655. $out = '';
  656. $parts = $this->loadPaletteElements($table, $row, $palette, $itemList);
  657. // Put palette together if there are fields in it:
  658. if (count($parts)) {
  659. $realFields = 0;
  660. foreach ($parts as $part) {
  661. if ($part['NAME'] !== '--linebreak--') {
  662. $realFields++;
  663. }
  664. }
  665. if ($realFields > 0) {
  666. if ($header) {
  667. $out .= $this->intoTemplate(
  668. array('HEADER' => htmlspecialchars($header)),
  669. $this->palFieldTemplateHeader
  670. );
  671. }
  672. $collapsed = $this->isPalettesCollapsed($table, $palette);
  673. $thePalIcon = '';
  674. if ($collapsed && $collapsedHeader !== NULL) {
  675. list($thePalIcon,) = $this->wrapOpenPalette(
  676. t3lib_iconWorks::getSpriteIcon(
  677. 'actions-system-options-view',
  678. array('title' => htmlspecialchars($this->getLL('l_moreOptions')))
  679. ), $table, $row, $palette, 1);
  680. $thePalIcon = '<span style="margin-left: 20px;">' . $thePalIcon . $collapsedHeader . '</span>';
  681. }
  682. $paletteHtml = $this->wrapPaletteField($this->printPalette($parts), $table, $row, $palette, $collapsed);
  683. $out .= $this->intoTemplate(
  684. array('PALETTE' => $thePalIcon . $paletteHtml),
  685. $this->palFieldTemplate
  686. );
  687. }
  688. }
  689. return $out;
  690. }
  691. /**
  692. * Returns the form HTML code for a database table field.
  693. *
  694. * @param string The table name
  695. * @param string The field name
  696. * @param array The record to edit from the database table.
  697. * @param string Alternative field name label to show.
  698. * @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).
  699. * @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.
  700. * @param integer The palette pointer.
  701. * @return mixed String (normal) or array (palettes)
  702. */
  703. function getSingleField($table, $field, $row, $altName = '', $palette = 0, $extra = '', $pal = 0) {
  704. global $TCA, $BE_USER;
  705. // Hook: getSingleField_preProcess
  706. foreach ($this->hookObjectsSingleField as $hookObj) {
  707. if (method_exists($hookObj, 'getSingleField_preProcess')) {
  708. $hookObj->getSingleField_preProcess($table, $field, $row, $altName, $palette, $extra, $pal, $this);
  709. }
  710. }
  711. $out = '';
  712. $PA = array();
  713. $PA['altName'] = $altName;
  714. $PA['palette'] = $palette;
  715. $PA['extra'] = $extra;
  716. $PA['pal'] = $pal;
  717. // Make sure to load full $TCA array for the table:
  718. t3lib_div::loadTCA($table);
  719. // Get the TCA configuration for the current field:
  720. $PA['fieldConf'] = $TCA[$table]['columns'][$field];
  721. $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
  722. $skipThisField = $this->inline->skipField($table, $field, $row, $PA['fieldConf']['config']);
  723. // Now, check if this field is configured and editable (according to excludefields + other configuration)
  724. if (is_array($PA['fieldConf']) &&
  725. !$skipThisField &&
  726. (!$PA['fieldConf']['exclude'] || $BE_USER->check('non_exclude_fields', $table . ':' . $field)) &&
  727. $PA['fieldConf']['config']['form_type'] != 'passthrough' &&
  728. ($this->RTEenabled || !$PA['fieldConf']['config']['showIfRTE']) &&
  729. (!$PA['fieldConf']['displayCond'] || $this->isDisplayCondition($PA['fieldConf']['displayCond'], $row)) &&
  730. (!$TCA[$table]['ctrl']['languageField'] || $PA['fieldConf']['l10n_display'] || strcmp($PA['fieldConf']['l10n_mode'], 'exclude') || $row[$TCA[$table]['ctrl']['languageField']] <= 0) &&
  731. (!$TCA[$table]['ctrl']['languageField'] || !$this->localizationMode || $this->localizationMode === $PA['fieldConf']['l10n_cat'])
  732. ) {
  733. // Fetching the TSconfig for the current table/field. This includes the $row which means that
  734. $PA['fieldTSConfig'] = $this->setTSconfig($table, $row, $field);
  735. // If the field is NOT disabled from TSconfig (which it could have been) then render it
  736. if (!$PA['fieldTSConfig']['disabled']) {
  737. // Override fieldConf by fieldTSconfig:
  738. $PA['fieldConf']['config'] = $this->overrideFieldConf($PA['fieldConf']['config'], $PA['fieldTSConfig']);
  739. // Init variables:
  740. $PA['itemFormElName'] = $this->prependFormFieldNames . '[' . $table . '][' . $row['uid'] . '][' . $field . ']'; // Form field name
  741. $PA['itemFormElName_file'] = $this->prependFormFieldNames_file . '[' . $table . '][' . $row['uid'] . '][' . $field . ']'; // Form field name, in case of file uploads
  742. $PA['itemFormElValue'] = $row[$field]; // The value to show in the form field.
  743. $PA['itemFormElID'] = $this->prependFormFieldNames . '_' . $table . '_' . $row['uid'] . '_' . $field;
  744. // set field to read-only if configured for translated records to show default language content as readonly
  745. if ($PA['fieldConf']['l10n_display'] && t3lib_div::inList($PA['fieldConf']['l10n_display'], 'defaultAsReadonly') && $row[$TCA[$table]['ctrl']['languageField']] > 0) {
  746. $PA['fieldConf']['config']['readOnly'] = true;
  747. $PA['itemFormElValue'] = $this->defaultLanguageData[$table . ':' . $row['uid']][$field];
  748. }
  749. // 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"
  750. if (
  751. ($TCA[$table]['ctrl']['type'] && !strcmp($field, $TCA[$table]['ctrl']['type'])) ||
  752. ($TCA[$table]['ctrl']['requestUpdate'] && t3lib_div::inList($TCA[$table]['ctrl']['requestUpdate'], $field))) {
  753. if ($GLOBALS['BE_USER']->jsConfirmation(1)) {
  754. $alertMsgOnChange = 'if (confirm(TBE_EDITOR.labels.onChangeAlert) && TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };';
  755. } else {
  756. $alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };';
  757. }
  758. } else {
  759. $alertMsgOnChange = '';
  760. }
  761. // Render as a hidden field?
  762. if (in_array($field, $this->hiddenFieldListArr)) {
  763. $this->hiddenFieldAccum[] = '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
  764. } else { // Render as a normal field:
  765. // 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.
  766. if (!$PA['palette']) {
  767. $paletteFields = $this->loadPaletteElements($table, $row, $PA['pal']);
  768. if ($PA['pal'] && $this->isPalettesCollapsed($table, $PA['pal']) && count($paletteFields)) {
  769. list($thePalIcon, $palJSfunc) = $this->wrapOpenPalette(t3lib_iconWorks::getSpriteIcon('actions-system-options-view', array('title' => htmlspecialchars($this->getLL('l_moreOptions')))), $table, $row, $PA['pal'], 1);
  770. } else {
  771. $thePalIcon = '';
  772. $palJSfunc = '';
  773. }
  774. }
  775. // onFocus attribute to add to the field:
  776. $PA['onFocus'] = ($palJSfunc && !$BE_USER->uc['dontShowPalettesOnFocusInAB']) ? ' onfocus="' . htmlspecialchars($palJSfunc) . '"' : '';
  777. // Find item
  778. $item = '';
  779. $PA['label'] = ($PA['altName'] ? $PA['altName'] : $PA['fieldConf']['label']);
  780. $PA['label'] = ($PA['fieldTSConfig']['label'] ? $PA['fieldTSConfig']['label'] : $PA['label']);
  781. $PA['label'] = ($PA['fieldTSConfig']['label.'][$GLOBALS['LANG']->lang] ? $PA['fieldTSConfig']['label.'][$GLOBALS['LANG']->lang] : $PA['label']);
  782. $PA['label'] = $this->sL($PA['label']);
  783. // JavaScript code for event handlers:
  784. $PA['fieldChangeFunc'] = array();
  785. $PA['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = "TBE_EDITOR.fieldChanged('" . $table . "','" . $row['uid'] . "','" . $field . "','" . $PA['itemFormElName'] . "');";
  786. $PA['fieldChangeFunc']['alert'] = $alertMsgOnChange;
  787. // if this is the child of an inline type and it is the field creating the label
  788. if ($this->inline->isInlineChildAndLabelField($table, $field)) {
  789. $inlineObjectId = implode(
  790. t3lib_TCEforms_inline::Structure_Separator,
  791. array(
  792. $this->inline->inlineNames['object'],
  793. $table,
  794. $row['uid']
  795. )
  796. );
  797. $PA['fieldChangeFunc']['inline'] = "inline.handleChangedField('" . $PA['itemFormElName'] . "','" . $inlineObjectId . "');";
  798. }
  799. // Based on the type of the item, call a render function:
  800. $item = $this->getSingleField_SW($table, $field, $row, $PA);
  801. // Add language + diff
  802. if ($PA['fieldConf']['l10n_display'] && (t3lib_div::inList($PA['fieldConf']['l10n_display'], 'hideDiff') || t3lib_div::inList($PA['fieldConf']['l10n_display'], 'defaultAsReadonly'))) {
  803. $renderLanguageDiff = false;
  804. } else {
  805. $renderLanguageDiff = true;
  806. }
  807. if ($renderLanguageDiff) {
  808. $item = $this->renderDefaultLanguageContent($table, $field, $row, $item);
  809. $item = $this->renderDefaultLanguageDiff($table, $field, $row, $item);
  810. }
  811. // 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
  812. $label = t3lib_div::deHSCentities(htmlspecialchars($PA['label']));
  813. if (t3lib_div::testInt($row['uid']) && $PA['fieldTSConfig']['linkTitleToSelf'] && !t3lib_div::_GP('columnsOnly')) {
  814. $lTTS_url = $this->backPath . 'alt_doc.php?edit[' . $table . '][' . $row['uid'] . ']=edit&columnsOnly=' . $field . '&returnUrl=' . rawurlencode($this->thisReturnUrl());
  815. $label = '<a href="' . htmlspecialchars($lTTS_url) . '">' . $label . '</a>';
  816. }
  817. // wrap the label with help text
  818. $PA['label'] = $label = t3lib_BEfunc::wrapInHelp($table, $field, $label);
  819. // Create output value:
  820. if ($PA['fieldConf']['config']['form_type'] == 'user' && $PA['fieldConf']['config']['noTableWrapping']) {
  821. $out = $item;
  822. } elseif ($PA['palette']) {
  823. // Array:
  824. $out = array(
  825. 'NAME' => $label,
  826. 'ID' => $row['uid'],
  827. 'FIELD' => $field,
  828. 'TABLE' => $table,
  829. 'ITEM' => $item
  830. );
  831. $out = $this->addUserTemplateMarkers($out, $table, $field, $row, $PA);
  832. } else {
  833. // String:
  834. $out = array(
  835. 'NAME' => $label,
  836. 'ITEM' => $item,
  837. 'TABLE' => $table,
  838. 'ID' => $row['uid'],
  839. 'PAL_LINK_ICON' => $thePalIcon,
  840. 'FIELD' => $field
  841. );
  842. $out = $this->addUserTemplateMarkers($out, $table, $field, $row, $PA);
  843. // String:
  844. $out = $this->intoTemplate($out);
  845. }
  846. }
  847. } else {
  848. $this->commentMessages[] = $this->prependFormFieldNames . '[' . $table . '][' . $row['uid'] . '][' . $field . ']: Disabled by TSconfig';
  849. }
  850. }
  851. // Hook: getSingleField_postProcess
  852. foreach ($this->hookObjectsSingleField as $hookObj) {
  853. if (method_exists($hookObj, 'getSingleField_postProcess')) {
  854. $hookObj->getSingleField_postProcess($table, $field, $row, $out, $PA, $this);
  855. }
  856. }
  857. // Return value (string or array)
  858. return $out;
  859. }
  860. /**
  861. * Rendering a single item for the form
  862. *
  863. * @param string Table name of record
  864. * @param string Fieldname to render
  865. * @param array The record
  866. * @param array parameters array containing a lot of stuff. Value by Reference!
  867. * @return string Returns the item as HTML code to insert
  868. * @access private
  869. * @see getSingleField(), getSingleField_typeFlex_draw()
  870. */
  871. function getSingleField_SW($table, $field, $row, &$PA) {
  872. $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
  873. // Hook: getSingleField_beforeRender
  874. foreach ($this->hookObjectsSingleField as $hookObject) {
  875. if (method_exists($hookObject, 'getSingleField_beforeRender')) {
  876. $hookObject->getSingleField_beforeRender($table, $field, $row, $PA);
  877. }
  878. }
  879. switch ($PA['fieldConf']['config']['form_type']) {
  880. case 'input':
  881. $item = $this->getSingleField_typeInput($table, $field, $row, $PA);
  882. break;
  883. case 'text':
  884. $item = $this->getSingleField_typeText($table, $field, $row, $PA);
  885. break;
  886. case 'check':
  887. $item = $this->getSingleField_typeCheck($table, $field, $row, $PA);
  888. break;
  889. case 'radio':
  890. $item = $this->getSingleField_typeRadio($table, $field, $row, $PA);
  891. break;
  892. case 'select':
  893. $item = $this->getSingleField_typeSelect($table, $field, $row, $PA);
  894. break;
  895. case 'group':
  896. $item = $this->getSingleField_typeGroup($table, $field, $row, $PA);
  897. break;
  898. case 'inline':
  899. $item = $this->inline->getSingleField_typeInline($table, $field, $row, $PA);
  900. break;
  901. case 'none':
  902. $item = $this->getSingleField_typeNone($table, $field, $row, $PA);
  903. break;
  904. case 'user':
  905. $item = $this->getSingleField_typeUser($table, $field, $row, $PA);
  906. break;
  907. case 'flex':
  908. $item = $this->getSingleField_typeFlex($table, $field, $row, $PA);
  909. break;
  910. default:
  911. $item = $this->getSingleField_typeUnknown($table, $field, $row, $PA);
  912. break;
  913. }
  914. return $item;
  915. }
  916. /**********************************************************
  917. *
  918. * Rendering of each TCEform field type
  919. *
  920. ************************************************************/
  921. /**
  922. * Generation of TCEform elements of the type "input"
  923. * This will render a single-line input form field, possibly with various control/validation features
  924. *
  925. * @param string The table name of the record
  926. * @param string The field name which this element is supposed to edit
  927. * @param array The record data array where the value(s) for the field can be found
  928. * @param array An array with additional configuration options.
  929. * @return string The HTML code for the TCEform field
  930. */
  931. function getSingleField_typeInput($table, $field, $row, &$PA) {
  932. $config = $PA['fieldConf']['config'];
  933. $specConf = $this->getSpecConfFromString($PA['extra'], $PA['fieldConf']['defaultExtras']);
  934. $size = t3lib_div::intInRange($config['size'] ? $config['size'] : 30, 5, $this->maxInputWidth);
  935. $evalList = t3lib_div::trimExplode(',', $config['eval'], 1);
  936. $classAndStyleAttributes = $this->formWidthAsArray($size);
  937. $fieldAppendix = '';
  938. $cssClasses = array($classAndStyleAttributes['class']);
  939. $cssStyle = $classAndStyleAttributes['style'];
  940. if (!isset($config['checkbox'])) {
  941. $config['checkbox'] = '0';
  942. $checkboxIsset = FALSE;
  943. } else {
  944. $checkboxIsset = TRUE;
  945. }
  946. if (in_array('date', $evalList) || in_array('datetime', $evalList)) {
  947. if (in_array('datetime', $evalList)) {
  948. $class = 'datetime';
  949. } else {
  950. $class = 'date';
  951. }
  952. $dateRange = '';
  953. if (isset($config['range']['lower'])) {
  954. $dateRange .= ' lower-' . intval($config['range']['lower']);
  955. }
  956. if (isset($config['range']['upper'])) {
  957. $dateRange .= ' upper-' . intval($config['range']['upper']);
  958. }
  959. $inputId = uniqid('tceforms-' . $class . 'field-');
  960. $cssClasses[] = 'tceforms-textfield tceforms-' . $class . 'field' . $dateRange;
  961. $fieldAppendix = t3lib_iconWorks::getSpriteIcon(
  962. 'actions-edit-pick-date',
  963. array(
  964. 'style' => 'cursor:pointer;',
  965. 'id' => 'picker-' . $inputId
  966. )
  967. );
  968. } elseif (in_array('timesec', $evalList)) {
  969. $inputId = uniqid('tceforms-timesecfield-');
  970. $cssClasses[] = 'tceforms-textfield tceforms-timesecfield';
  971. } elseif (in_array('year', $evalList)) {
  972. $inputId = uniqid('tceforms-yearfield-');
  973. $cssClasses[] = 'tceforms-textfield tceforms-yearfield';
  974. } elseif (in_array('time', $evalList)) {
  975. $inputId = uniqid('tceforms-timefield-');
  976. $cssClasses[] = 'tceforms-textfield tceforms-timefield';
  977. } elseif (in_array('int', $evalList)) {
  978. $inputId = uniqid('tceforms-intfield-');
  979. $cssClasses[] = 'tceforms-textfield tceforms-intfield';
  980. } elseif (in_array('double2', $evalList)) {
  981. $inputId = uniqid('tceforms-double2field-');
  982. $cssClasses[] = 'tceforms-textfield tceforms-double2field';
  983. } else {
  984. $inputId = uniqid('tceforms-textfield-');
  985. $cssClasses[] = 'tceforms-textfield';
  986. if ($checkboxIsset === FALSE) {
  987. $config['checkbox'] = '';
  988. }
  989. }
  990. if (isset($config['wizards']['link'])) {
  991. $inputId = uniqid('tceforms-linkfield-');
  992. $cssClasses[] = 'tceforms-textfield tceforms-linkfield';
  993. } elseif (isset($config['wizards']['color'])) {
  994. $inputId = uniqid('tceforms-colorfield-');
  995. $cssClasses[] = 'tceforms-textfield tceforms-colorfield';
  996. }
  997. if ($this->renderReadonly || $config['readOnly']) {
  998. $itemFormElValue = $PA['itemFormElValue'];
  999. if (in_array('date', $evalList)) {
  1000. $config['format'] = 'date';
  1001. } elseif (in_array('datetime', $evalList)) {
  1002. $config['format'] = 'datetime';
  1003. } elseif (in_array('time', $evalList)) {
  1004. $config['format'] = 'time';
  1005. }
  1006. if (in_array('password', $evalList)) {
  1007. $itemFormElValue = $itemFormElValue ? '*********' : '';
  1008. }
  1009. return $this->getSingleField_typeNone_render($config, $itemFormElValue);
  1010. }
  1011. foreach ($evalList as $func) {
  1012. switch ($func) {
  1013. case 'required':
  1014. $this->registerRequiredProperty('field', $table . '_' . $row['uid'] . '_' . $field, $PA['itemFormElName']);
  1015. // Mark this field for date/time disposal:
  1016. if (array_intersect($evalList, array('date', 'datetime', 'time'))) {
  1017. $this->requiredAdditional[$PA['itemFormElName']]['isPositiveNumber'] = true;
  1018. }
  1019. break;
  1020. default:
  1021. if (substr($func, 0, 3) == 'tx_') {
  1022. // Pair hook to the one in t3lib_TCEmain::checkValue_input_Eval()
  1023. $evalObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func] . ':&' . $func);
  1024. if (is_object($evalObj) && method_exists($evalObj, 'deevaluateFieldValue')) {
  1025. $_params = array(
  1026. 'value' => $PA['itemFormElValue']
  1027. );
  1028. $PA['itemFormElValue'] = $evalObj->deevaluateFieldValue($_params);
  1029. }
  1030. }
  1031. break;
  1032. }
  1033. }
  1034. $paramsList = "'" . $PA['itemFormElName'] . "','" . implode(',', $evalList) . "','" . trim($config['is_in']) . "'," . (isset($config['checkbox']) ? 1 : 0) . ",'" . $config['checkbox'] . "'";
  1035. if ((in_array('date', $evalList) || in_array('datetime', $evalList))) {
  1036. $item .= '<span class="t3-tceforms-input-wrapper-datetime" onmouseOver="if (document.getElementById(\'' .
  1037. $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\';">';
  1038. // Add server timezone offset to UTC to our stored date
  1039. if ($PA['itemFormElValue'] > 0) {
  1040. $PA['itemFormElValue'] += date('Z', $PA['itemFormElValue']);
  1041. }
  1042. } else {
  1043. $item .= '<span class="t3-tceforms-input-wrapper" onmouseOver="if (document.getElementById(\'' . $inputId .
  1044. '\').value) {this.className=\'t3-tceforms-input-wrapper-hover\';} else {this.className=\'t3-tceforms-input-wrapper\';};" onmouseOut="this.className=\'t3-tceforms-input-wrapper\';">';
  1045. }
  1046. $PA['fieldChangeFunc'] = array_merge(
  1047. array('typo3form.fieldGet' => 'typo3form.fieldGet(' . $paramsList . ');'),
  1048. $PA['fieldChangeFunc']
  1049. );
  1050. // old function "checkbox" now the option to set the date / remove the date
  1051. if (isset($config['checkbox'])) {
  1052. $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'])));
  1053. }
  1054. $mLgd = ($config['max'] ? $config['max'] : 256);
  1055. $iOnChange = implode('', $PA['fieldChangeFunc']);
  1056. $item .= '<input type="text" id="' . $inputId .
  1057. '" class="' . implode(' ', $cssClasses) . '" name="' . $PA['itemFormElName'] .
  1058. '_hr" value="" style="' . $cssStyle . '" maxlength="' . $mLgd . '" onchange="' .
  1059. htmlspecialchars($iOnChange) . '"' . $PA['onFocus'] . ' />'; // This is the EDITABLE form field.
  1060. $item .= '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' .
  1061. 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.
  1062. $item .= $fieldAppendix . '</span><div style="clear:both;"></div>';
  1063. $this->extJSCODE .= 'typo3form.fieldSet(' . $paramsList . ');';
  1064. // going through all custom evaluations configured for this field
  1065. foreach ($evalList as $evalData) {
  1066. if (substr($evalData, 0, 3) == 'tx_') {
  1067. $evalObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$evalData] . ':&' . $evalData);
  1068. if (is_object($evalObj) && method_exists($evalObj, 'returnFieldJS')) {
  1069. $this->extJSCODE .= "\n\nfunction " . $evalData . "(value) {\n" . $evalObj->returnFieldJS() . "\n}\n";
  1070. }
  1071. }
  1072. }
  1073. // Creating an alternative item without the JavaScript handlers.
  1074. $altItem = '<input type="hidden" name="' . $PA['itemFormElName'] . '_hr" value="" />';
  1075. $altItem .= '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
  1076. // Wrap a wizard around the item?
  1077. $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'] . '_hr', $specConf);
  1078. return $item;
  1079. }
  1080. /**
  1081. * Generation of TCEform elements of the type "text"
  1082. * This will render a <textarea> OR RTE area form field, possibly with various control/validation features
  1083. *
  1084. * @param string The table name of the record
  1085. * @param string The field name which this element is supposed to edit
  1086. * @param array The record data array where the value(s) for the field can be found
  1087. * @param array An array with additional configuration options.
  1088. * @return string The HTML code for the TCEform field
  1089. */
  1090. function getSingleField_typeText($table, $field, $row, &$PA) {
  1091. // Init config:
  1092. $config = $PA['fieldConf']['config'];
  1093. $evalList = t3lib_div::trimExplode(',', $config['eval'], 1);
  1094. if ($this->renderReadonly || $config['readOnly']) {
  1095. return $this->getSingleField_typeNone_render($config, $PA['itemFormElValue']);
  1096. }
  1097. // Setting columns number:
  1098. $cols = t3lib_div::intInRange($config['cols'] ? $config['cols'] : 30, 5, $this->maxTextareaWidth);
  1099. // Setting number of rows:
  1100. $origRows = $rows = t3lib_div::intInRange($config['rows'] ? $config['rows'] : 5, 1, 20);
  1101. if (strlen($PA['itemFormElValue']) > $this->charsPerRow * 2) {
  1102. $cols = $this->maxTextareaWidth;
  1103. $rows = t3lib_div::intInRange(round(strlen($PA['itemFormElValue']) / $this->charsPerRow), count(explode(LF, $PA['itemFormElValue'])), 20);
  1104. if ($rows < $origRows) {
  1105. $rows = $origRows;
  1106. }
  1107. }
  1108. if (in_array('required', $evalList)) {
  1109. $this->requiredFields[$table . '_' . $row['uid'] . '_' . $field] = $PA['itemFormElName'];
  1110. }
  1111. // Init RTE vars:
  1112. $RTEwasLoaded = 0; // Set true, if the RTE is loaded; If not a normal textarea is shown.
  1113. $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...
  1114. // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. Traditionally, this is where RTE configuration has been found.
  1115. $specConf = $this->getSpecConfFromString($PA['extra'], $PA['fieldConf']['defaultExtras']);
  1116. // Setting up the altItem form field, which is a hidden field containing the value
  1117. $altItem = '<input type="hidden" name="' . htmlspecialchars($PA['itemFormElName']) . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
  1118. // If RTE is generally enabled (TYPO3_CONF_VARS and user settings)
  1119. if ($this->RTEenabled) {
  1120. $p = t3lib_BEfunc::getSpecConfParametersFromArray($specConf['rte_transform']['parameters']);
  1121. 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.
  1122. t3lib_BEfunc::fixVersioningPid($table, $row);
  1123. list($tscPID, $thePidValue) = $this->getTSCpid($table, $row['uid'], $row['pid']);
  1124. // If the pid-value is not negative (that is, a pid could NOT be fetched)
  1125. if ($thePidValue >= 0) {
  1126. $RTEsetup = $GLOBALS['BE_USER']->getTSConfig('RTE', t3lib_BEfunc::getPagesTSconfig($tscPID));
  1127. $RTEtypeVal = t3lib_BEfunc::getTCAtypeValue($table, $row);
  1128. $thisConfig = t3lib_BEfunc::RTEsetup($RTEsetup['properties'], $table, $field, $RTEtypeVal);
  1129. if (!$thisConfig['disabled']) {
  1130. if (!$this->disableRTE) {
  1131. $this->RTEcounter++;
  1132. // Find alternative relative path for RTE images/links:
  1133. $eFile = t3lib_parsehtml_proc::evalWriteFile($specConf['static_write'], $row);
  1134. $RTErelPath = is_array($eFile) ? dirname($eFile['relEditFile']) : '';
  1135. // Get RTE object, draw form and set flag:
  1136. $RTEobj = t3lib_BEfunc::RTEgetObj();
  1137. $item = $RTEobj->drawRTE($this, $table, $field, $row, $PA, $specConf, $thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue);
  1138. // Wizard:
  1139. $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'], $specConf, 1);
  1140. $RTEwasLoaded = 1;
  1141. } else {
  1142. $RTEwouldHaveBeenLoaded = 1;
  1143. $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!)';
  1144. }
  1145. } else {
  1146. $this->commentMessages[] = $PA['itemFormElName'] . ': RTE is disabled by the Page TSconfig, "RTE"-key (eg. by RTE.default.disabled=0 or such)';
  1147. }
  1148. } else {
  1149. $this->commentMessages[] = $PA['itemFormElName'] . ': PID value could NOT be fetched. Rare error, normally with new records.';
  1150. }
  1151. } else {
  1152. if (!isset($specConf['richtext'])) {
  1153. $this->commentMessages[] = $PA['itemFormElName'] . ': RTE was not configured for this field in TCA-types';
  1154. }
  1155. if (!(!$p['flag'] || !$row[$p['flag']])) {
  1156. $this->commentMessages[] = $PA['itemFormElName'] . ': Field-flag (' . $PA['flag'] . ') has been set to disable RTE!';
  1157. }
  1158. }
  1159. }
  1160. // Display ordinary field if RTE was not loaded.
  1161. if (!$RTEwasLoaded) {
  1162. if ($specConf['rte_only']) { // Show message, if no RTE (field can only be edited with RTE!)
  1163. $item = '<p><em>' . htmlspecialchars($this->getLL('l_noRTEfound')) . '</em></p>';
  1164. } else {
  1165. if ($specConf['nowrap']) {
  1166. $wrap = 'off';
  1167. } else {
  1168. $wrap = ($config['wrap'] ? $config['wrap'] : 'virtual');
  1169. }
  1170. $classes = array();
  1171. if ($specConf['fixed-font']) {
  1172. $classes[] = 'fixed-font';
  1173. }
  1174. if ($specConf['enable-tab']) {
  1175. $classes[] = 'enable-tab';
  1176. }
  1177. $formWidthText = $this->formWidthText($cols, $wrap);
  1178. // Extract class attributes from $formWidthText (otherwise it would be added twice to the output)
  1179. $res = array();
  1180. if (preg_match('/ class="(.+?)"/', $formWidthText, $res)) {
  1181. $formWidthText = str_replace(' class="' . $res[1] . '"', '', $formWidthText);
  1182. $classes = array_merge($classes, explode(' ', $res[1]));
  1183. }
  1184. if (count($classes)) {
  1185. $class = ' class="tceforms-textarea ' . implode(' ', $classes) . '"';
  1186. } else {
  1187. $class = 'tceforms-textarea';
  1188. }
  1189. $evalList = t3lib_div::trimExplode(',', $config['eval'], 1);
  1190. foreach ($evalList as $func) {
  1191. switch ($func) {
  1192. case 'required':
  1193. $this->registerRequiredProperty('field', $table . '_' . $row['uid'] . '_' . $field, $PA['itemFormElName']);
  1194. break;
  1195. default:
  1196. if (substr($func, 0, 3) == 'tx_') {
  1197. // Pair hook to the one in t3lib_TCEmain::checkValue_input_Eval() and t3lib_TCEmain::checkValue_text_Eval()
  1198. $evalObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func] . ':&' . $func);
  1199. if (is_object($evalObj) && method_exists($evalObj, 'deevaluateFieldValue')) {
  1200. $_params = array(
  1201. 'value' => $PA['itemFormElValue']
  1202. );
  1203. $PA['itemFormElValue'] = $evalObj->deevaluateFieldValue($_params);
  1204. }
  1205. }
  1206. break;
  1207. }
  1208. }
  1209. $iOnChange = implode('', $PA['fieldChangeFunc']);
  1210. $item .= '
  1211. <textarea id="' . uniqid('tceforms-textarea-') . '" name="' . $PA['itemFormElName'] . '"' . $formWidthText . $class . ' rows="' . $rows . '" wrap="' . $wrap . '" onchange="' . htmlspecialchars($iOnChange) . '"' . $PA['onFocus'] . '>' .
  1212. t3lib_div::formatForTextarea($PA['itemFormElValue']) .
  1213. '</textarea>';
  1214. $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'], $specConf, $RTEwouldHaveBeenLoaded);
  1215. }
  1216. }
  1217. // Return field HTML:
  1218. return $item;
  1219. }
  1220. /**
  1221. * Generation of TCEform elements of the type "check"
  1222. * This will render a check-box OR an array of checkboxes
  1223. *
  1224. * @param string The table name of the record
  1225. * @param string The field name which this element is supposed to edit
  1226. * @param array The record data array where the value(s) for the field can be found
  1227. * @param array An array with additional configuration options.
  1228. * @return string The HTML code for the TCEform field
  1229. */
  1230. function getSingleField_typeCheck($table, $field, $row, &$PA) {
  1231. $config = $PA['fieldConf']['config'];
  1232. $disabled = '';
  1233. if ($this->renderReadonly || $config['readOnly']) {
  1234. $disabled = ' disabled="disabled"';
  1235. }
  1236. // Traversing the array of items:
  1237. $selItems = $this->initItemArray($PA['fieldConf']);
  1238. if ($config['itemsProcFunc']) {
  1239. $selItems = $this->procItems($selItems, $PA['fieldTSConfig']['itemsProcFunc.'], $config, $table, $row, $field);
  1240. }
  1241. if (!count($selItems)) {
  1242. $selItems[] = array('', '');
  1243. }
  1244. $thisValue = intval($PA['itemFormElValue']);
  1245. $cols = intval($config['cols']);
  1246. if ($cols > 1) {
  1247. $item .= '<table border="0" cellspacing="0" cellpadding="0" class="typo3-TCEforms-checkboxArray">';
  1248. for ($c = 0; $c < count($selItems); $c++) {
  1249. $p = $selItems[$c];
  1250. if (!($c % $cols)) {
  1251. $item .= '<tr>';
  1252. }
  1253. $cBP = $this->checkBoxParams($PA['itemFormElName'], $thisValue, $c, count($selItems), implode('', $PA['fieldChangeFunc']));
  1254. $cBName = $PA['itemFormElName'] . '_' . $c;
  1255. $cBID = $PA['itemFormElID'] . '_' . $c;
  1256. $item .= '<td nowrap="nowrap">' .
  1257. '<input type="checkbox"' . $this->insertDefStyle('check') . ' value="1" name="' . $cBName . '"' . $cBP . $disabled . ' id="' . $cBID . '" />' .
  1258. $this->wrapLabels('<label for="' . $cBID . '">' . htmlspecialchars($p[0]) . '</label>&nbsp;') .
  1259. '</td>';
  1260. if (($c % $cols) + 1 == $cols) {
  1261. $item .= '</tr>';
  1262. }
  1263. }
  1264. if ($c % $cols) {
  1265. $rest = $cols - ($c % $cols);
  1266. for ($c = 0; $c < $rest; $c++) {
  1267. $item .= '<td></td>';
  1268. }
  1269. if ($c > 0) {
  1270. $item .= '</tr>';
  1271. }
  1272. }
  1273. $item .= '</table>';
  1274. } else {
  1275. for ($c = 0; $c < count($selItems); $c++) {
  1276. $p = $selItems[$c];
  1277. $cBP = $this->checkBoxParams($PA['itemFormElName'], $thisValue, $c, count($selItems), implode('', $PA['fieldChangeFunc']));
  1278. $cBName = $PA['itemFormElName'] . '_' . $c;
  1279. $cBID = $PA['itemFormElID'] . '_' . $c;
  1280. $item .= ($c > 0 ? '<br />' : '') .
  1281. '<input type="checkbox"' . $this->insertDefStyle('check') . ' value="1" name="' . $cBName . '"' . $cBP . $PA['onFocus'] . $disabled . ' id="' . $cBID . '" />' .
  1282. $this->wrapLabels('<label for="' . $cBID . '">' . htmlspecialchars($p[0]) . '</label>');
  1283. }
  1284. }
  1285. if (!$disabled) {
  1286. $item .= '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($thisValue) . '" />';
  1287. }
  1288. return $item;
  1289. }
  1290. /**
  1291. * Generation of TCEform elements of the type "radio"
  1292. * This will render a series of radio buttons.
  1293. *
  1294. * @param string The table name of the record
  1295. * @param string The field name which this element is supposed to edit
  1296. * @param array The record data array where the value(s) for the field can be found
  1297. * @param array An array with additional configuration options.
  1298. * @return string The HTML code for the TCEform field
  1299. */
  1300. function getSingleField_typeRadio($table, $field, $row, &$PA) {
  1301. $config = $PA['fieldConf']['config'];
  1302. $disabled = '';
  1303. if ($this->renderReadonly || $config['readOnly']) {
  1304. $disabled = ' disabled="disabled"';
  1305. }
  1306. // Get items for the array:
  1307. $selItems = $this->initItemArray($PA['fieldConf']);
  1308. if ($config['itemsProcFunc']) {
  1309. $selItems = $this->procItems($selItems, $PA['fieldTSConfig']['itemsProcFunc.'], $config, $table, $row, $field);
  1310. }
  1311. // Traverse the items, making the form elements:
  1312. for ($c = 0; $c < count($selItems); $c++) {
  1313. $p = $selItems[$c];
  1314. $rID = $PA['itemFormElID'] . '_' . $c;
  1315. $rOnClick = implode('', $PA['fieldChangeFunc']);
  1316. $rChecked = (!strcmp($p[1], $PA['itemFormElValue']) ? ' checked="checked"' : '');
  1317. $item .= '<input type="radio"' . $this->insertDefStyle('radio') . ' name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($p[1]) . '" onclick="' . htmlspecialchars($rOnClick) . '"' . $rChecked . $PA['onFocus'] . $disabled . ' id="' . $rID . '" />
  1318. <label for="' . $rID . '">' . htmlspecialchars($p[0]) . '</label>
  1319. <br />';
  1320. }
  1321. return $item;
  1322. }
  1323. /**
  1324. * Generation of TCEform elements of the type "select"
  1325. * This will render a selector box element, or possibly a special construction with two selector boxes. That depends on configuration.
  1326. *
  1327. * @param string The table name of the record
  1328. * @param string The field name which this element is supposed to edit
  1329. * @param array The record data array where the value(s) for the field can be found
  1330. * @param array An array with additional configuration options.
  1331. * @return string The HTML code for the TCEform field
  1332. */
  1333. function getSingleField_typeSelect($table, $field, $row, &$PA) {
  1334. global $TCA;
  1335. // Field configuration from TCA:
  1336. $config = $PA['fieldConf']['config'];
  1337. $disabled = '';
  1338. if ($this->renderReadonly || $config['readOnly']) {
  1339. $disabled = ' disabled="disabled"';
  1340. }
  1341. // "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/.
  1342. $specConf = $this->getSpecConfFromString($PA['extra'], $PA['fieldConf']['defaultExtras']);
  1343. // Getting the selector box items from the system
  1344. $selItems = $this->addSelectOptionsToItemArray(
  1345. $this->initItemArray($PA['fieldConf']),
  1346. $PA['fieldConf'],
  1347. $this->setTSconfig($table, $row),
  1348. $field
  1349. );
  1350. // Possibly filter some items:
  1351. $keepItemsFunc = create_function('$value', 'return $value[1];');
  1352. $selItems = t3lib_div::keepItemsInArray($selItems, $PA['fieldTSConfig']['keepItems'], $keepItemsFunc);
  1353. // Possibly add some items:
  1354. $selItems = $this->addItems($selItems, $PA['fieldTSConfig']['addItems.']);
  1355. // Process items by a user function:
  1356. if (isset($config['itemsProcFunc']) && $config['itemsProcFunc']) {
  1357. $selItems = $this->procItems($selItems, $PA['fieldTSConfig']['itemsProcFunc.'], $config, $table, $row, $field);
  1358. }
  1359. // Possibly remove some items:
  1360. $removeItems = t3lib_div::trimExplode(',', $PA['fieldTSConfig']['removeItems'], 1);
  1361. foreach ($selItems as $tk => $p) {
  1362. // Checking languages and authMode:
  1363. $languageDeny = $TCA[$table]['ctrl']['languageField'] && !strcmp($TCA[$table]['ctrl']['languageField'], $field) && !$GLOBALS['BE_USER']->checkLanguageAccess($p[1]);
  1364. $authModeDeny = $config['form_type'] == 'select' && $config['authMode'] && !$GLOBALS['BE_USER']->checkAuthMode($table, $field, $p[1], $config['authMode']);
  1365. if (in_array($p[1], $removeItems) || $languageDeny || $authModeDeny) {
  1366. unset($selItems[$tk]);
  1367. } elseif (isset($PA['fieldTSConfig']['altLabels.'][$p[1]])) {
  1368. $selItems[$tk][0] = $this->sL($PA['fieldTSConfig']['altLabels.'][$p[1]]);
  1369. }
  1370. // Removing doktypes with no access:
  1371. if (($table === 'pages' || $table === 'pages_language_overlay') && $field === 'doktype') {
  1372. if (!($GLOBALS['BE_USER']->isAdmin() || t3lib_div::inList($GLOBALS['BE_USER']->groupData['pagetypes_select'], $p[1]))) {
  1373. unset($selItems[$tk]);
  1374. }
  1375. }
  1376. }
  1377. // Creating the label for the "No Matching Value" entry.
  1378. $nMV_label = isset($PA['fieldTSConfig']['noMatchingValue_label']) ? $this->sL($PA['fieldTSConfig']['noMatchingValue_label']) : '[ ' . $this->getLL('l_noMatchingValue') . ' ]';
  1379. // Prepare some values:
  1380. $maxitems = intval($config['maxitems']);
  1381. // If a SINGLE selector box...
  1382. if ($maxitems <= 1 && $config['renderMode'] !== 'tree') {
  1383. $item = $this->getSingleField_typeSelect_single($table, $field, $row, $PA, $config, $selItems, $nMV_label);
  1384. } elseif (!strcmp($config['renderMode'], 'checkbox')) { // Checkbox renderMode
  1385. $item = $this->getSingleField_typeSelect_checkbox($table, $field, $row, $PA, $config, $selItems, $nMV_label);
  1386. } elseif (!strcmp($config['renderMode'], 'singlebox')) { // Single selector box renderMode
  1387. $item = $this->getSingleField_typeSelect_singlebox($table, $field, $row, $PA, $config, $selItems, $nMV_label);
  1388. } elseif (!strcmp($config['renderMode'], 'tree')) { // Tree renderMode
  1389. $treeClass = t3lib_div::makeInstance('t3lib_TCEforms_Tree', $this);
  1390. $item = $treeClass->renderField($table, $field, $row, $PA, $config, $selItems, $nMV_label);
  1391. } else { // Traditional multiple selector box:
  1392. $item = $this->getSingleField_typeSelect_multiple($table, $field, $row, $PA, $config, $selItems, $nMV_label);
  1393. }
  1394. // Wizards:
  1395. if (!$disabled) {
  1396. $altItem = '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
  1397. $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'], $specConf);
  1398. }
  1399. return $item;
  1400. }
  1401. /**
  1402. * Creates a single-selector box
  1403. * (Render function for getSingleField_typeSelect())
  1404. *
  1405. * @param string See getSingleField_typeSelect()
  1406. * @param string See getSingleField_typeSelect()
  1407. * @param array See getSingleField_typeSelect()
  1408. * @param array See getSingleField_typeSelect()
  1409. * @param array (Redundant) content of $PA['fieldConf']['config'] (for convenience)
  1410. * @param array Items available for selection
  1411. * @param string Label for no-matching-value
  1412. * @return string The HTML code for the item
  1413. * @see getSingleField_typeSelect()
  1414. */
  1415. function getSingleField_typeSelect_single($table, $field, $row, &$PA, $config, $selItems, $nMV_label) {
  1416. // check against inline uniqueness
  1417. $inlineParent = $this->inline->getStructureLevel(-1);
  1418. if (is_array($inlineParent) && $inlineParent['uid']) {
  1419. if ($inlineParent['config']['foreign_table'] == $table && $inlineParent['config']['foreign_unique'] == $field) {
  1420. $uniqueIds = $this->inline->inlineData['unique'][$this->inline->inlineNames['object'] . '[' . $table . ']']['used'];
  1421. $PA['fieldChangeFunc']['inlineUnique'] = "inline.updateUnique(this,'" . $this->inline->inlineNames['object'] . '[' . $table . "]','" . $this->inline->inlineNames['form'] . "','" . $row['uid'] . "');";
  1422. }
  1423. // hide uid of parent record for symmetric relations
  1424. if ($inlineParent['config']['foreign_table'] == $table && ($inlineParent['config']['foreign_field'] == $field || $inlineParent['config']['symmetric_field'] == $field)) {
  1425. $uniqueIds[] = $inlineParent['uid'];
  1426. }
  1427. }
  1428. // Initialization:
  1429. $c = 0;
  1430. $sI = 0;
  1431. $noMatchingValue = 1;
  1432. $opt = array();
  1433. $selicons = array();
  1434. $onlySelectedIconShown = 0;
  1435. $size = intval($config['size']);
  1436. $selectedStyle = ''; // Style set on <select/>
  1437. $disabled = '';
  1438. if ($this->renderReadonly || $config['readOnly']) {
  1439. $disabled = ' disabled="disabled"';
  1440. $onlySelectedIconShown = 1;
  1441. }
  1442. // Icon configuration:
  1443. if ($config['suppress_icons'] == 'IF_VALUE_FALSE') {
  1444. $suppressIcons = !$PA['itemFormElValue'] ? 1 : 0;
  1445. } elseif ($config['suppress_icons'] == 'ONLY_SELECTED') {
  1446. $suppressIcons = 0;
  1447. $onlySelectedIconShown = 1;
  1448. } elseif ($config['suppress_icons']) {
  1449. $suppressIcons = 1;
  1450. } else {
  1451. $suppressIcons = 0;
  1452. }
  1453. // Traverse the Array of selector box items:
  1454. $optGroupStart = array();
  1455. $optGroupOpen = FALSE;
  1456. $classesForSelectTag = array();
  1457. foreach ($selItems as $p) {
  1458. $sM = (!strcmp($PA['itemFormElValue'], $p[1]) ? ' selected="selected"' : '');
  1459. if ($sM) {
  1460. $sI = $c;
  1461. $noMatchingValue = 0;
  1462. }
  1463. // Getting style attribute value (for icons):
  1464. if ($config['iconsInOptionTags']) {
  1465. $styleAttrValue = $this->optionTagStyle($p[2]);
  1466. if ($sM) {
  1467. list($selectIconFile, $selectIconInfo) = $this->getIcon($p[2]);
  1468. if (!empty($selectIconInfo)) {
  1469. $selectedStyle = ' style="background-image:url(' . $selectIconFile . ');"';
  1470. $classesForSelectTag[] = 'typo3-TCEforms-select-selectedItemWithBackgroundImage';
  1471. }
  1472. }
  1473. }
  1474. // Compiling the <option> tag:
  1475. if (!($p[1] != $PA['itemFormElValue'] && is_array($uniqueIds) && in_array($p[1], $uniqueIds))) {
  1476. if (!strcmp($p[1], '--div--')) {
  1477. $optGroupStart[0] = $p[0];
  1478. if ($config['iconsInOptionTags']) {
  1479. $optGroupStart[1] = $this->optgroupTagStyle($p[2]);
  1480. } else {
  1481. $optGroupStart[1] = $styleAttrValue;
  1482. }
  1483. } else {
  1484. if (count($optGroupStart)) {
  1485. if ($optGroupOpen) { // Closing last optgroup before next one starts
  1486. $opt[] = '</optgroup>' . LF;
  1487. }
  1488. $opt[] = '<optgroup label="' . t3lib_div::deHSCentities(htmlspecialchars($optGroupStart[0])) . '"' .
  1489. ($optGroupStart[1] ? ' style="' . htmlspecialchars($optGroupStart[1]) . '"' : '') .
  1490. ' class="c-divider">' . LF;
  1491. $optGroupOpen = TRUE;
  1492. $c--;
  1493. $optGroupStart = array();
  1494. }
  1495. $opt[] = '<option value="' . htmlspecialchars($p[1]) . '"' .
  1496. $sM .
  1497. ($styleAttrValue ? ' style="' . htmlspecialchars($styleAttrValue) . '"' : '') .
  1498. '>' . t3lib_div::deHSCentities(($p[0])) . '</option>' . LF;
  1499. }
  1500. }
  1501. // If there is an icon for the selector box (rendered in selicon-table below)...:
  1502. // if there is an icon ($p[2]), icons should be shown, and, if only selected are visible, is it selected
  1503. if ($p[2] && !$suppressIcons && (!$onlySelectedIconShown || $sM)) {
  1504. list($selIconFile, $selIconInfo) = $this->getIcon($p[2]);
  1505. if (!empty($selIconInfo)) {
  1506. $iOnClick = $this->elName($PA['itemFormElName']) . '.selectedIndex=' . $c . '; ' .
  1507. $this->elName($PA['itemFormElName']) . '.style.backgroundImage=' . $this->elName($PA['itemFormElName']) . '.options[' . $c . '].style.backgroundImage; ' .
  1508. implode('', $PA['fieldChangeFunc']) . $this->blur() . 'return false;';
  1509. } else {
  1510. $iOnClick = $this->elName($PA['itemFormElName']) . '.selectedIndex=' . $c . '; ' .
  1511. $this->elName($PA['itemFormElName']) . '.className=' . $this->elName($PA['itemFormElName']) . '.options[' . $c . '].className; ' .
  1512. implode('', $PA['fieldChangeFunc']) . $this->blur() . 'return false;';
  1513. }
  1514. $selicons[] = array(
  1515. (!$onlySelectedIconShown ? '<a href="#" onclick="' . htmlspecialchars($iOnClick) . '">' : '') .
  1516. $this->getIconHtml($p[2], htmlspecialchars($p[0]), htmlspecialchars($p[0])) .
  1517. (!$onlySelectedIconShown ? '</a>' : ''),
  1518. $c, $sM);
  1519. }
  1520. $c++;
  1521. }
  1522. if ($optGroupOpen) { // Closing optgroup if open
  1523. $opt[] = '</optgroup>';
  1524. $optGroupOpen = false;
  1525. }
  1526. // No-matching-value:
  1527. if ($PA['itemFormElValue'] && $noMatchingValue && !$PA['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
  1528. $nMV_label = @sprintf($nMV_label, $PA['itemFormElValue']);
  1529. $opt[] = '<option value="' . htmlspecialchars($PA['itemFormElValue']) . '" selected="selected">' . htmlspecialchars($nMV_label) . '</option>';
  1530. }
  1531. // Create item form fields:
  1532. $sOnChange = 'if (this.options[this.selectedIndex].value==\'--div--\') {this.selectedIndex=' . $sI . ';} ' . implode('', $PA['fieldChangeFunc']);
  1533. if (!$disabled) {
  1534. $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...
  1535. }
  1536. if ($config['iconsInOptionTags']) {
  1537. $classesForSelectTag[] = 'icon-select';
  1538. }
  1539. $item .= '<select' . $selectedStyle . ' id="' . uniqid('tceforms-select-') . '" name="' . $PA['itemFormElName'] . '"' .
  1540. $this->insertDefStyle('select', implode(' ', $classesForSelectTag)) .
  1541. ($size ? ' size="' . $size . '"' : '') .
  1542. ' onchange="' . htmlspecialchars($onChangeIcon . $sOnChange) . '"' .
  1543. $PA['onFocus'] . $disabled . '>';
  1544. $item .= implode('', $opt);
  1545. $item .= '</select>';
  1546. // Create icon table:
  1547. if (count($selicons) && !$config['noIconsBelowSelect']) {
  1548. $item .= '<table border="0" cellpadding="0" cellspacing="0" class="typo3-TCEforms-selectIcons">';
  1549. $selicon_cols = intval($config['selicon_cols']);
  1550. if (!$selicon_cols) {
  1551. $selicon_cols = count($selicons);
  1552. }
  1553. $sR = ceil(count($selicons) / $selicon_cols);
  1554. $selicons = array_pad($selicons, $sR * $selicon_cols, '');
  1555. for ($sa = 0; $sa < $sR; $sa++) {
  1556. $item .= '<tr>';
  1557. for ($sb = 0; $sb < $selicon_cols; $sb++) {
  1558. $sk = ($sa * $selicon_cols + $sb);
  1559. $imgN = 'selIcon_' . $table . '_' . $row['uid'] . '_' . $field . '_' . $selicons[$sk][1];
  1560. $imgS = ($selicons[$sk][2] ? $this->backPath . 'gfx/content_selected.gif' : 'clear.gif');
  1561. $item .= '<td><img name="' . htmlspecialchars($imgN) . '" src="' . $imgS . '" width="7" height="10" alt="" /></td>';
  1562. $item .= '<td>' . $selicons[$sk][0] . '</td>';
  1563. }
  1564. $item .= '</tr>';
  1565. }
  1566. $item .= '</table>';
  1567. }
  1568. return $item;
  1569. }
  1570. /**
  1571. * Creates a checkbox list (renderMode = "checkbox")
  1572. * (Render function for getSingleField_typeSelect())
  1573. *
  1574. * @param string See getSingleField_typeSelect()
  1575. * @param string See getSingleField_typeSelect()
  1576. * @param array See getSingleField_typeSelect()
  1577. * @param array See getSingleField_typeSelect()
  1578. * @param array (Redundant) content of $PA['fieldConf']['config'] (for convenience)
  1579. * @param array Items available for selection
  1580. * @param string Label for no-matching-value
  1581. * @return string The HTML code for the item
  1582. * @see getSingleField_typeSelect()
  1583. */
  1584. function getSingleField_typeSelect_checkbox(
  1585. $table, $field, $row, &$PA, $config, $selItems, $nMV_label) {
  1586. if (empty($selItems)) {
  1587. return '';
  1588. }
  1589. // Get values in an array (and make unique, which is fine because there can be no duplicates anyway):
  1590. $itemArray = array_flip($this->extractValuesOnlyFromValueLabelList($PA['itemFormElValue']));
  1591. $disabled = '';
  1592. if ($this->renderReadonly || $config['readOnly']) {
  1593. $disabled = ' disabled="disabled"';
  1594. }
  1595. // Traverse the Array of selector box items:
  1596. $tRows = array();
  1597. $c = 0;
  1598. if (!$disabled) {
  1599. $sOnChange = implode('', $PA['fieldChangeFunc']);
  1600. $setAll = array(); // Used to accumulate the JS needed to restore the original selection.
  1601. $unSetAll = array();
  1602. foreach ($selItems as $p) {
  1603. // Non-selectable element:
  1604. if (!strcmp($p[1], '--div--')) {
  1605. $tRows[] = '
  1606. <tr class="c-header">
  1607. <td colspan="3">' . htmlspecialchars($p[0]) . '</td>
  1608. </tr>';
  1609. } else {
  1610. // Selected or not by default:
  1611. $sM = '';
  1612. if (isset($itemArray[$p[1]])) {
  1613. $sM = ' checked="checked"';
  1614. unset($itemArray[$p[1]]);
  1615. }
  1616. // Icon:
  1617. if ($p[2]) {
  1618. $selIcon = $p[2];
  1619. } else {
  1620. $selIcon = t3lib_iconWorks::getSpriteIcon('empty-empty');
  1621. }
  1622. // Compile row:
  1623. $rowId = uniqid('select_checkbox_row_');
  1624. $onClickCell = $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked=!' . $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked;';
  1625. $onClick = 'this.attributes.getNamedItem("class").nodeValue = ' . $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked ? "c-selectedItem" : "c-unselectedItem";';
  1626. $setAll[] = $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked=1;';
  1627. $setAll[] .= '$(\'' . $rowId . '\').removeClassName(\'c-unselectedItem\');$(\'' . $rowId . '\').addClassName(\'c-selectedItem\');';
  1628. $unSetAll[] = $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked=0;';
  1629. $unSetAll[] .= '$(\'' . $rowId . '\').removeClassName(\'c-selectedItem\');$(\'' . $rowId . '\').addClassName(\'c-unselectedItem\');';
  1630. $restoreCmd[] = $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked=' . ($sM ? 1 : 0) . ';' .
  1631. '$(\'' . $rowId . '\').removeClassName(\'c-selectedItem\');$(\'' . $rowId . '\').removeClassName(\'c-unselectedItem\');' .
  1632. '$(\'' . $rowId . '\').addClassName(\'c-' . ($sM ? '' : 'un') . 'selectedItem\');';
  1633. // Check if some help text is available
  1634. // Since TYPO3 4.5 help text is expected to be an associative array
  1635. // with two key, "title" and "description"
  1636. // For the sake of backwards compatibility, we test if the help text
  1637. // is a string and use it as a description (this could happen if items
  1638. // are modified with an itemProcFunc)
  1639. $hasHelp = FALSE;
  1640. $help = '';
  1641. $helpArray = array();
  1642. if ((is_array($p[3]) && count($p[3]) > 0) || !empty($p[3])) {
  1643. $hasHelp = TRUE;
  1644. if (is_array($p[3])) {
  1645. $helpArray = $p[3];
  1646. } else {
  1647. $helpArray['description'] = $p[3];
  1648. }
  1649. }
  1650. $label = t3lib_div::deHSCentities(htmlspecialchars($p[0]));
  1651. if ($hasHelp) {
  1652. $help = t3lib_BEfunc::wrapInHelp('', '', '', $helpArray);
  1653. }
  1654. $tRows[] = '
  1655. <tr id="' . $rowId . '" class="' . ($sM ? 'c-selectedItem' : 'c-unselectedItem') . '" onclick="' . htmlspecialchars($onClick) . '" style="cursor: pointer;">
  1656. <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>
  1657. <td class="c-labelCell" onclick="' . htmlspecialchars($onClickCell) . '">' .
  1658. $this->getIconHtml($selIcon) .
  1659. $label .
  1660. '</td>
  1661. <td class="c-descr" onclick="' . htmlspecialchars($onClickCell) . '">' . ((empty($help)) ? '' : $help) . '</td>
  1662. </tr>';
  1663. $c++;
  1664. }
  1665. }
  1666. }
  1667. // Remaining values (invalid):
  1668. if (count($itemArray) && !$PA['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
  1669. foreach ($itemArray as $theNoMatchValue => $temp) {
  1670. // Compile <checkboxes> tag:
  1671. array_unshift($tRows, '
  1672. <tr class="c-invalidItem">
  1673. <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>
  1674. <td class="c-labelCell">' .
  1675. t3lib_div::deHSCentities(htmlspecialchars(@sprintf($nMV_label, $theNoMatchValue))) .
  1676. '</td><td>&nbsp;</td>
  1677. </tr>');
  1678. $c++;
  1679. }
  1680. }
  1681. // Add an empty hidden field which will send a blank value if all items are unselected.
  1682. $item .= '<input type="hidden" name="' . htmlspecialchars($PA['itemFormElName']) . '" value="" />';
  1683. // Remaining checkboxes will get their set-all link:
  1684. if (count($setAll)) {
  1685. $tableHead = '<thead>
  1686. <tr class="c-header-checkbox-controls t3-row-header">
  1687. <td class="c-checkbox">
  1688. <input type="checkbox" class="checkbox" onclick="if (checked) {' . htmlspecialchars(implode('', $setAll) . '} else {' . implode('', $unSetAll) . '}') . '">
  1689. </td>
  1690. <td colspan="2">
  1691. </td>
  1692. </tr></thead>';
  1693. }
  1694. // Implode rows in table:
  1695. $item .= '
  1696. <table border="0" cellpadding="0" cellspacing="0" class="typo3-TCEforms-select-checkbox">' .
  1697. $tableHead .
  1698. '<tbody>' . implode('', $tRows) . '</tbody>
  1699. </table>
  1700. ';
  1701. // Add revert icon
  1702. if (is_array($restoreCmd)) {
  1703. $item .= '<a href="#" onclick="' . implode('', $restoreCmd) . ' return false;' . '">' .
  1704. t3lib_iconWorks::getSpriteIcon('actions-edit-undo', array('title' => htmlspecialchars($this->getLL('l_revertSelection')))) . '</a>';
  1705. }
  1706. return $item;
  1707. }
  1708. /**
  1709. * Creates a selectorbox list (renderMode = "singlebox")
  1710. * (Render function for getSingleField_typeSelect())
  1711. *
  1712. * @param string See getSingleField_typeSelect()
  1713. * @param string See getSingleField_typeSelect()
  1714. * @param array See getSingleField_typeSelect()
  1715. * @param array See getSingleField_typeSelect()
  1716. * @param array (Redundant) content of $PA['fieldConf']['config'] (for convenience)
  1717. * @param array Items available for selection
  1718. * @param string Label for no-matching-value
  1719. * @return string The HTML code for the item
  1720. * @see getSingleField_typeSelect()
  1721. */
  1722. function getSingleField_typeSelect_singlebox($table, $field, $row, &$PA, $config, $selItems, $nMV_label) {
  1723. // Get values in an array (and make unique, which is fine because there can be no duplicates anyway):
  1724. $itemArray = array_flip($this->extractValuesOnlyFromValueLabelList($PA['itemFormElValue']));
  1725. $disabled = '';
  1726. if ($this->renderReadonly || $config['readOnly']) {
  1727. $disabled = ' disabled="disabled"';
  1728. }
  1729. // Traverse the Array of selector box items:
  1730. $opt = array();
  1731. $restoreCmd = array(); // Used to accumulate the JS needed to restore the original selection.
  1732. $c = 0;
  1733. foreach ($selItems as $p) {
  1734. // Selected or not by default:
  1735. $sM = '';
  1736. if (isset($itemArray[$p[1]])) {
  1737. $sM = ' selected="selected"';
  1738. $restoreCmd[] = $this->elName($PA['itemFormElName'] . '[]') . '.options[' . $c . '].selected=1;';
  1739. unset($itemArray[$p[1]]);
  1740. }
  1741. // Non-selectable element:
  1742. $nonSel = '';
  1743. if (!strcmp($p[1], '--div--')) {
  1744. $nonSel = ' onclick="this.selected=0;" class="c-divider"';
  1745. }
  1746. // Icon style for option tag:
  1747. if ($config['iconsInOptionTags']) {
  1748. $styleAttrValue = $this->optionTagStyle($p[2]);
  1749. }
  1750. // Compile <option> tag:
  1751. $opt[] = '<option value="' . htmlspecialchars($p[1]) . '"' .
  1752. $sM .
  1753. $nonSel .
  1754. ($styleAttrValue ? ' style="' . htmlspecialchars($styleAttrValue) . '"' : '') .
  1755. '>' . t3lib_div::deHSCentities(htmlspecialchars($p[0])) . '</option>';
  1756. $c++;
  1757. }
  1758. // Remaining values:
  1759. if (count($itemArray) && !$PA['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
  1760. foreach ($itemArray as $theNoMatchValue => $temp) {
  1761. // Compile <option> tag:
  1762. array_unshift($opt, '<option value="' . htmlspecialchars($theNoMatchValue) . '" selected="selected">' . t3lib_div::deHSCentities(htmlspecialchars(@sprintf($nMV_label, $theNoMatchValue))) . '</option>');
  1763. }
  1764. }
  1765. // Compile selector box:
  1766. $sOnChange = implode('', $PA['fieldChangeFunc']);
  1767. $selector_itemListStyle = isset($config['itemListStyle']) ? ' style="' . htmlspecialchars($config['itemListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"';
  1768. $size = intval($config['size']);
  1769. $cssPrefix = ($size === 1) ? 'tceforms-select' : 'tceforms-multiselect';
  1770. $size = $config['autoSizeMax'] ? t3lib_div::intInRange(count($selItems) + 1, t3lib_div::intInRange($size, 1), $config['autoSizeMax']) : $size;
  1771. $selectBox = '<select id="' . uniqid($cssPrefix) . '" name="' . $PA['itemFormElName'] . '[]"' .
  1772. $this->insertDefStyle('select', $cssPrefix) .
  1773. ($size ? ' size="' . $size . '"' : '') .
  1774. ' multiple="multiple" onchange="' . htmlspecialchars($sOnChange) . '"' .
  1775. $PA['onFocus'] .
  1776. $selector_itemListStyle .
  1777. $disabled . '>
  1778. ' .
  1779. implode('
  1780. ', $opt) . '
  1781. </select>';
  1782. // Add an empty hidden field which will send a blank value if all items are unselected.
  1783. if (!$disabled) {
  1784. $item .= '<input type="hidden" name="' . htmlspecialchars($PA['itemFormElName']) . '" value="" />';
  1785. }
  1786. // Put it all into a table:
  1787. $item .= '
  1788. <table border="0" cellspacing="0" cellpadding="0" width="1" class="typo3-TCEforms-select-singlebox">
  1789. <tr>
  1790. <td>
  1791. ' . $selectBox . '
  1792. <br/>
  1793. <em>' .
  1794. htmlspecialchars($this->getLL('l_holdDownCTRL')) .
  1795. '</em>
  1796. </td>
  1797. <td valign="top">
  1798. <a href="#" onclick="' . htmlspecialchars($this->elName($PA['itemFormElName'] . '[]') . '.selectedIndex=-1;' . implode('', $restoreCmd) . ' return false;') . '" title="' . htmlspecialchars($this->getLL('l_revertSelection')) . '">' .
  1799. t3lib_iconWorks::getSpriteIcon('actions-edit-undo') .
  1800. '</a>
  1801. </td>
  1802. </tr>
  1803. </table>
  1804. ';
  1805. return $item;
  1806. }
  1807. /**
  1808. * Creates a multiple-selector box (two boxes, side-by-side)
  1809. * (Render function for getSingleField_typeSelect())
  1810. *
  1811. * @param string See getSingleField_typeSelect()
  1812. * @param string See getSingleField_typeSelect()
  1813. * @param array See getSingleField_typeSelect()
  1814. * @param array See getSingleField_typeSelect()
  1815. * @param array (Redundant) content of $PA['fieldConf']['config'] (for convenience)
  1816. * @param array Items available for selection
  1817. * @param string Label for no-matching-value
  1818. * @return string The HTML code for the item
  1819. * @see getSingleField_typeSelect()
  1820. */
  1821. function getSingleField_typeSelect_multiple($table, $field, $row, &$PA, $config, $selItems, $nMV_label) {
  1822. $disabled = '';
  1823. if ($this->renderReadonly || $config['readOnly']) {
  1824. $disabled = ' disabled="disabled"';
  1825. }
  1826. // Setting this hidden field (as a flag that JavaScript can read out)
  1827. if (!$disabled) {
  1828. $item .= '<input type="hidden" name="' . $PA['itemFormElName'] . '_mul" value="' . ($config['multiple'] ? 1 : 0) . '" />';
  1829. }
  1830. // Set max and min items:
  1831. $maxitems = t3lib_div::intInRange($config['maxitems'], 0);
  1832. if (!$maxitems) {
  1833. $maxitems = 100000;
  1834. }
  1835. $minitems = t3lib_div::intInRange($config['minitems'], 0);
  1836. // Register the required number of elements:
  1837. $this->registerRequiredProperty('range', $PA['itemFormElName'], array($minitems, $maxitems, 'imgName' => $table . '_' . $row['uid'] . '_' . $field));
  1838. // Get "removeItems":
  1839. $removeItems = t3lib_div::trimExplode(',', $PA['fieldTSConfig']['removeItems'], 1);
  1840. // Get the array with selected items:
  1841. $itemArray = t3lib_div::trimExplode(',', $PA['itemFormElValue'], 1);
  1842. // Possibly filter some items:
  1843. $keepItemsFunc = create_function('$value', '$parts=explode(\'|\',$value,2); return rawurldecode($parts[0]);');
  1844. $itemArray = t3lib_div::keepItemsInArray($itemArray, $PA['fieldTSConfig']['keepItems'], $keepItemsFunc);
  1845. // Perform modification of the selected items array:
  1846. foreach ($itemArray as $tk => $tv) {
  1847. $tvP = explode('|', $tv, 2);
  1848. $evalValue = $tvP[0];
  1849. $isRemoved = in_array($evalValue, $removeItems) || ($config['form_type'] == 'select' && $config['authMode'] && !$GLOBALS['BE_USER']->checkAuthMode($table, $field, $evalValue, $config['authMode']));
  1850. if ($isRemoved && !$PA['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
  1851. $tvP[1] = rawurlencode(@sprintf($nMV_label, $evalValue));
  1852. } elseif (isset($PA['fieldTSConfig']['altLabels.'][$evalValue])) {
  1853. $tvP[1] = rawurlencode($this->sL($PA['fieldTSConfig']['altLabels.'][$evalValue]));
  1854. }
  1855. if ($tvP[1] == '') {
  1856. // Case: flexform, default values supplied, no label provided (bug #9795)
  1857. foreach ($selItems as $selItem) {
  1858. if ($selItem[1] == $tvP[0]) {
  1859. $tvP[1] = html_entity_decode($selItem[0]);
  1860. break;
  1861. }
  1862. }
  1863. }
  1864. $itemArray[$tk] = implode('|', $tvP);
  1865. }
  1866. $itemsToSelect = '';
  1867. if (!$disabled) {
  1868. // Create option tags:
  1869. $opt = array();
  1870. $styleAttrValue = '';
  1871. foreach ($selItems as $p) {
  1872. if ($config['iconsInOptionTags']) {
  1873. $styleAttrValue = $this->optionTagStyle($p[2]);
  1874. }
  1875. $opt[] = '<option value="' . htmlspecialchars($p[1]) . '"' .
  1876. ($styleAttrValue ? ' style="' . htmlspecialchars($styleAttrValue) . '"' : '') .
  1877. '>' . $p[0] . '</option>';
  1878. }
  1879. // Put together the selector box:
  1880. $selector_itemListStyle = isset($config['itemListStyle']) ? ' style="' . htmlspecialchars($config['itemListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"';
  1881. $size = intval($config['size']);
  1882. $size = $config['autoSizeMax'] ? t3lib_div::intInRange(count($itemArray) + 1, t3lib_div::intInRange($size, 1), $config['autoSizeMax']) : $size;
  1883. if ($config['exclusiveKeys']) {
  1884. $sOnChange = 'setFormValueFromBrowseWin(\'' . $PA['itemFormElName'] . '\',this.options[this.selectedIndex].value,this.options[this.selectedIndex].text,\'' . $config['exclusiveKeys'] . '\'); ';
  1885. } else {
  1886. $sOnChange = 'setFormValueFromBrowseWin(\'' . $PA['itemFormElName'] . '\',this.options[this.selectedIndex].value,this.options[this.selectedIndex].text); ';
  1887. }
  1888. $sOnChange .= implode('', $PA['fieldChangeFunc']);
  1889. $itemsToSelect = '
  1890. <select id="' . uniqid('tceforms-multiselect-') . '" name="' . $PA['itemFormElName'] . '_sel"' .
  1891. $this->insertDefStyle('select', 'tceforms-multiselect tceforms-itemstoselect') .
  1892. ($size ? ' size="' . $size . '"' : '') .
  1893. ' onchange="' . htmlspecialchars($sOnChange) . '"' .
  1894. $PA['onFocus'] .
  1895. $selector_itemListStyle . '>
  1896. ' . implode('
  1897. ', $opt) . '
  1898. </select>';
  1899. }
  1900. // Pass to "dbFileIcons" function:
  1901. $params = array(
  1902. 'size' => $size,
  1903. 'autoSizeMax' => t3lib_div::intInRange($config['autoSizeMax'], 0),
  1904. 'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"',
  1905. 'dontShowMoveIcons' => ($maxitems <= 1),
  1906. 'maxitems' => $maxitems,
  1907. 'info' => '',
  1908. 'headers' => array(
  1909. 'selector' => $this->getLL('l_selected') . ':<br />',
  1910. 'items' => $this->getLL('l_items') . ':<br />'
  1911. ),
  1912. 'noBrowser' => 1,
  1913. 'thumbnails' => $itemsToSelect,
  1914. 'readOnly' => $disabled
  1915. );
  1916. $item .= $this->dbFileIcons($PA['itemFormElName'], '', '', $itemArray, '', $params, $PA['onFocus']);
  1917. return $item;
  1918. }
  1919. /**
  1920. * Generation of TCEform elements of the type "group"
  1921. * This will render a selectorbox into which elements from either the file system or database can be inserted. Relations.
  1922. *
  1923. * @param string The table name of the record
  1924. * @param string The field name which this element is supposed to edit
  1925. * @param array The record data array where the value(s) for the field can be found
  1926. * @param array An array with additional configuration options.
  1927. * @return string The HTML code for the TCEform field
  1928. */
  1929. function getSingleField_typeGroup($table, $field, $row, &$PA) {
  1930. // Init:
  1931. $config = $PA['fieldConf']['config'];
  1932. $internal_type = $config['internal_type'];
  1933. $show_thumbs = $config['show_thumbs'];
  1934. $size = intval($config['size']);
  1935. $maxitems = t3lib_div::intInRange($config['maxitems'], 0);
  1936. if (!$maxitems) {
  1937. $maxitems = 100000;
  1938. }
  1939. $minitems = t3lib_div::intInRange($config['minitems'], 0);
  1940. $allowed = trim($config['allowed']);
  1941. $disallowed = trim($config['disallowed']);
  1942. $disabled = '';
  1943. if ($this->renderReadonly || $config['readOnly']) {
  1944. $disabled = ' disabled="disabled"';
  1945. }
  1946. $item .= '<input type="hidden" name="' . $PA['itemFormElName'] . '_mul" value="' . ($config['multiple'] ? 1 : 0) . '"' . $disabled . ' />';
  1947. $this->registerRequiredProperty('range', $PA['itemFormElName'], array($minitems, $maxitems, 'imgName' => $table . '_' . $row['uid'] . '_' . $field));
  1948. $info = '';
  1949. // "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/.
  1950. $specConf = $this->getSpecConfFromString($PA['extra'], $PA['fieldConf']['defaultExtras']);
  1951. // Acting according to either "file" or "db" type:
  1952. switch ((string) $config['internal_type']) {
  1953. case 'file_reference':
  1954. $config['uploadfolder'] = '';
  1955. // Fall through
  1956. case 'file': // If the element is of the internal type "file":
  1957. // Creating string showing allowed types:
  1958. $tempFT = t3lib_div::trimExplode(',', $allowed, 1);
  1959. if (!count($tempFT)) {
  1960. $info .= '*';
  1961. }
  1962. foreach ($tempFT as $ext) {
  1963. if ($ext) {
  1964. $info .= strtoupper($ext) . ' ';
  1965. }
  1966. }
  1967. // Creating string, showing disallowed types:
  1968. $tempFT_dis = t3lib_div::trimExplode(',', $disallowed, 1);
  1969. if (count($tempFT_dis)) {
  1970. $info .= '<br />';
  1971. }
  1972. foreach ($tempFT_dis as $ext) {
  1973. if ($ext) {
  1974. $info .= '-' . strtoupper($ext) . ' ';
  1975. }
  1976. }
  1977. // Making the array of file items:
  1978. $itemArray = t3lib_div::trimExplode(',', $PA['itemFormElValue'], 1);
  1979. // Showing thumbnails:
  1980. $thumbsnail = '';
  1981. if ($show_thumbs) {
  1982. $imgs = array();
  1983. foreach ($itemArray as $imgRead) {
  1984. $imgP = explode('|', $imgRead);
  1985. $imgPath = rawurldecode($imgP[0]);
  1986. $rowCopy = array();
  1987. $rowCopy[$field] = $imgPath;
  1988. $imgs[] = '<span class="nobr">' . t3lib_BEfunc::thumbCode($rowCopy, $table, $field, $this->backPath, 'thumbs.php', $config['uploadfolder'], 0, ' align="middle"') .
  1989. $imgPath .
  1990. '</span>';
  1991. }
  1992. $thumbsnail = implode('<br />', $imgs);
  1993. }
  1994. // Creating the element:
  1995. $noList = isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'list');
  1996. $params = array(
  1997. 'size' => $size,
  1998. 'dontShowMoveIcons' => ($maxitems <= 1),
  1999. 'autoSizeMax' => t3lib_div::intInRange($config['autoSizeMax'], 0),
  2000. 'maxitems' => $maxitems,
  2001. 'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"',
  2002. 'info' => $info,
  2003. 'thumbnails' => $thumbsnail,
  2004. 'readOnly' => $disabled,
  2005. 'noBrowser' => $noList || (isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'browser')),
  2006. 'noList' => $noList,
  2007. );
  2008. $item .= $this->dbFileIcons($PA['itemFormElName'], 'file', implode(',', $tempFT), $itemArray, '', $params, $PA['onFocus']);
  2009. if (!$disabled && !(isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'upload'))) {
  2010. // Adding the upload field:
  2011. if ($this->edit_docModuleUpload && $config['uploadfolder']) {
  2012. $item .= '<input type="file" name="' . $PA['itemFormElName_file'] . '" size="35" onchange="' . implode('', $PA['fieldChangeFunc']) . '" />';
  2013. }
  2014. }
  2015. break;
  2016. case 'folder': // If the element is of the internal type "folder":
  2017. // array of folder items:
  2018. $itemArray = t3lib_div::trimExplode(',', $PA['itemFormElValue'], 1);
  2019. // Creating the element:
  2020. $noList = isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'list');
  2021. $params = array(
  2022. 'size' => $size,
  2023. 'dontShowMoveIcons' => ($maxitems <= 1),
  2024. 'autoSizeMax' => t3lib_div::intInRange($config['autoSizeMax'], 0),
  2025. 'maxitems' => $maxitems,
  2026. 'style' => isset($config['selectedListStyle']) ?
  2027. ' style="' . htmlspecialchars($config['selectedListStyle']) . '"'
  2028. : ' style="' . $this->defaultMultipleSelectorStyle . '"',
  2029. 'info' => $info,
  2030. 'readOnly' => $disabled,
  2031. 'noBrowser' => $noList || (isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'browser')),
  2032. 'noList' => $noList,
  2033. );
  2034. $item .= $this->dbFileIcons(
  2035. $PA['itemFormElName'],
  2036. 'folder',
  2037. '',
  2038. $itemArray,
  2039. '',
  2040. $params,
  2041. $PA['onFocus']
  2042. );
  2043. break;
  2044. case 'db': // If the element is of the internal type "db":
  2045. // Creating string showing allowed types:
  2046. $tempFT = t3lib_div::trimExplode(',', $allowed, TRUE);
  2047. if (!strcmp(trim($tempFT[0]), '*')) {
  2048. $onlySingleTableAllowed = false;
  2049. $info .= '<span class="nobr">' .
  2050. htmlspecialchars($this->getLL('l_allTables')) .
  2051. '</span><br />';
  2052. } elseif ($tempFT) {
  2053. $onlySingleTableAllowed = (count($tempFT) == 1);
  2054. foreach ($tempFT as $theT) {
  2055. $info .= '<span class="nobr">' .
  2056. t3lib_iconWorks::getSpriteIconForRecord($theT, array()) .
  2057. htmlspecialchars($this->sL($GLOBALS['TCA'][$theT]['ctrl']['title'])) .
  2058. '</span><br />';
  2059. }
  2060. }
  2061. $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
  2062. $itemArray = array();
  2063. $imgs = array();
  2064. // Thumbnails:
  2065. $temp_itemArray = t3lib_div::trimExplode(',', $PA['itemFormElValue'], 1);
  2066. foreach ($temp_itemArray as $dbRead) {
  2067. $recordParts = explode('|', $dbRead);
  2068. list($this_table, $this_uid) = t3lib_BEfunc::splitTable_Uid($recordParts[0]);
  2069. // For the case that no table was found and only a single table is defined to be allowed, use that one:
  2070. if (!$this_table && $onlySingleTableAllowed) {
  2071. $this_table = $allowed;
  2072. }
  2073. $itemArray[] = array('table' => $this_table, 'id' => $this_uid);
  2074. if (!$disabled && $show_thumbs) {
  2075. $rr = t3lib_BEfunc::getRecordWSOL($this_table, $this_uid);
  2076. $imgs[] = '<span class="nobr">' .
  2077. $this->getClickMenu(
  2078. t3lib_iconWorks::getSpriteIconForRecord(
  2079. $this_table,
  2080. $rr,
  2081. array(
  2082. 'style' => 'vertical-align:top',
  2083. 'title' => htmlspecialchars(t3lib_BEfunc::getRecordPath($rr['pid'], $perms_clause, 15) . ' [UID: ' . $rr['uid'] . ']')
  2084. )
  2085. ),
  2086. $this_table,
  2087. $this_uid
  2088. ) .
  2089. '&nbsp;' .
  2090. t3lib_BEfunc::getRecordTitle($this_table, $rr, TRUE) . ' <span class="typo3-dimmed"><em>[' . $rr['uid'] . ']</em></span>' .
  2091. '</span>';
  2092. }
  2093. }
  2094. $thumbsnail = '';
  2095. if (!$disabled && $show_thumbs) {
  2096. $thumbsnail = implode('<br />', $imgs);
  2097. }
  2098. // Creating the element:
  2099. $noList = isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'list');
  2100. $params = array(
  2101. 'size' => $size,
  2102. 'dontShowMoveIcons' => ($maxitems <= 1),
  2103. 'autoSizeMax' => t3lib_div::intInRange($config['autoSizeMax'], 0),
  2104. 'maxitems' => $maxitems,
  2105. 'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"',
  2106. 'info' => $info,
  2107. 'thumbnails' => $thumbsnail,
  2108. 'readOnly' => $disabled,
  2109. 'noBrowser' => $noList || (isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'browser')),
  2110. 'noList' => $noList,
  2111. );
  2112. $item .= $this->dbFileIcons($PA['itemFormElName'], 'db', implode(',', $tempFT), $itemArray, '', $params, $PA['onFocus'], $table, $field, $row['uid']);
  2113. break;
  2114. }
  2115. // Wizards:
  2116. $altItem = '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
  2117. if (!$disabled) {
  2118. $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'], $specConf);
  2119. }
  2120. return $item;
  2121. }
  2122. /**
  2123. * Generation of TCEform elements of the type "none"
  2124. * This will render a non-editable display of the content of the field.
  2125. *
  2126. * @param string The table name of the record
  2127. * @param string The field name which this element is supposed to edit
  2128. * @param array The record data array where the value(s) for the field can be found
  2129. * @param array An array with additional configuration options.
  2130. * @return string The HTML code for the TCEform field
  2131. */
  2132. function getSingleField_typeNone($table, $field, $row, &$PA) {
  2133. // Init:
  2134. $config = $PA['fieldConf']['config'];
  2135. $itemValue = $PA['itemFormElValue'];
  2136. return $this->getSingleField_typeNone_render($config, $itemValue);
  2137. }
  2138. /**
  2139. * HTML rendering of a value which is not editable.
  2140. *
  2141. * @param array Configuration for the display
  2142. * @param string The value to display
  2143. * @return string The HTML code for the display
  2144. * @see getSingleField_typeNone();
  2145. */
  2146. function getSingleField_typeNone_render($config, $itemValue) {
  2147. // is colorScheme[0] the right value?
  2148. $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;';
  2149. if ($config['format']) {
  2150. $itemValue = $this->formatValue($config, $itemValue);
  2151. }
  2152. $rows = intval($config['rows']);
  2153. if ($rows > 1) {
  2154. if (!$config['pass_content']) {
  2155. $itemValue = nl2br(htmlspecialchars($itemValue));
  2156. }
  2157. // like textarea
  2158. $cols = t3lib_div::intInRange($config['cols'] ? $config['cols'] : 30, 5, $this->maxTextareaWidth);
  2159. if (!$config['fixedRows']) {
  2160. $origRows = $rows = t3lib_div::intInRange($rows, 1, 20);
  2161. if (strlen($itemValue) > $this->charsPerRow * 2) {
  2162. $cols = $this->maxTextareaWidth;
  2163. $rows = t3lib_div::intInRange(round(strlen($itemValue) / $this->charsPerRow), count(explode(LF, $itemValue)), 20);
  2164. if ($rows < $origRows) {
  2165. $rows = $origRows;
  2166. }
  2167. }
  2168. }
  2169. if ($this->docLarge) {
  2170. $cols = round($cols * $this->form_largeComp);
  2171. }
  2172. $width = ceil($cols * $this->form_rowsToStylewidth);
  2173. // hardcoded: 12 is the height of the font
  2174. $height = $rows * 12;
  2175. $item = '
  2176. <div style="' . htmlspecialchars($divStyle . ' overflow:auto; height:' . $height . 'px; width:' . $width . 'px;') . '" class="' . htmlspecialchars($this->formElClass('none')) . '">' .
  2177. $itemValue .
  2178. '</div>';
  2179. } else {
  2180. if (!$config['pass_content']) {
  2181. $itemValue = htmlspecialchars($itemValue);
  2182. }
  2183. $cols = $config['cols'] ? $config['cols'] : ($config['size'] ? $config['size'] : $this->maxInputWidth);
  2184. if ($this->docLarge) {
  2185. $cols = round($cols * $this->form_largeComp);
  2186. }
  2187. $width = ceil($cols * $this->form_rowsToStylewidth);
  2188. // overflow:auto crashes mozilla here. Title tag is usefull when text is longer than the div box (overflow:hidden).
  2189. $item = '
  2190. <div style="' . htmlspecialchars($divStyle . ' overflow:hidden; width:' . $width . 'px;') . '" class="' . htmlspecialchars($this->formElClass('none')) . '" title="' . $itemValue . '">' .
  2191. '<span class="nobr">' . (strcmp($itemValue, '') ? $itemValue : '&nbsp;') . '</span>' .
  2192. '</div>';
  2193. }
  2194. return $item;
  2195. }
  2196. /**
  2197. * Handler for Flex Forms
  2198. *
  2199. * @param string The table name of the record
  2200. * @param string The field name which this element is supposed to edit
  2201. * @param array The record data array where the value(s) for the field can be found
  2202. * @param array An array with additional configuration options.
  2203. * @return string The HTML code for the TCEform field
  2204. */
  2205. function getSingleField_typeFlex($table, $field, $row, &$PA) {
  2206. // Data Structure:
  2207. $dataStructArray = t3lib_BEfunc::getFlexFormDS($PA['fieldConf']['config'], $row, $table);
  2208. // Manipulate Flexform DS via TSConfig and group access lists
  2209. if (is_array($dataStructArray)) {
  2210. $flexFormHelper = t3lib_div::makeInstance('t3lib_TCEforms_Flexforms');
  2211. $dataStructArray = $flexFormHelper->modifyFlexFormDS($dataStructArray, $table, $field, $row, $PA['fieldConf']['config']);
  2212. unset($flexFormHelper);
  2213. }
  2214. // Get data structure:
  2215. if (is_array($dataStructArray)) {
  2216. // Get data:
  2217. $xmlData = $PA['itemFormElValue'];
  2218. $xmlHeaderAttributes = t3lib_div::xmlGetHeaderAttribs($xmlData);
  2219. $storeInCharset = strtolower($xmlHeaderAttributes['encoding']);
  2220. if ($storeInCharset) {
  2221. $currentCharset = $GLOBALS['LANG']->charSet;
  2222. $xmlData = $GLOBALS['LANG']->csConvObj->conv($xmlData, $storeInCharset, $currentCharset, 1);
  2223. }
  2224. $editData = t3lib_div::xml2array($xmlData);
  2225. if (!is_array($editData)) { // Must be XML parsing error...
  2226. $editData = array();
  2227. } elseif (!isset($editData['meta']) || !is_array($editData['meta'])) {
  2228. $editData['meta'] = array();
  2229. }
  2230. // Find the data structure if sheets are found:
  2231. $sheet = $editData['meta']['currentSheetId'] ? $editData['meta']['currentSheetId'] : 'sDEF'; // Sheet to display
  2232. // Create sheet menu:
  2233. //TODO; Why is this commented out?
  2234. // if (is_array($dataStructArray['sheets'])) {
  2235. // #$item.=$this->getSingleField_typeFlex_sheetMenu($dataStructArray['sheets'], $PA['itemFormElName'].'[meta][currentSheetId]', $sheet).'<br />';
  2236. // }
  2237. // Create language menu:
  2238. $langChildren = $dataStructArray['meta']['langChildren'] ? 1 : 0;
  2239. $langDisabled = $dataStructArray['meta']['langDisable'] ? 1 : 0;
  2240. $editData['meta']['currentLangId'] = array();
  2241. // Look up page overlays:
  2242. $checkPageLanguageOverlay = $GLOBALS['BE_USER']->getTSConfigVal('options.checkPageLanguageOverlay') ? TRUE : FALSE;
  2243. if ($checkPageLanguageOverlay) {
  2244. $pageOverlays = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
  2245. '*',
  2246. 'pages_language_overlay',
  2247. 'pid=' . intval($row['pid']) .
  2248. t3lib_BEfunc::deleteClause('pages_language_overlay') .
  2249. t3lib_BEfunc::versioningPlaceholderClause('pages_language_overlay'),
  2250. '',
  2251. '',
  2252. '',
  2253. 'sys_language_uid'
  2254. );
  2255. }
  2256. $languages = $this->getAvailableLanguages();
  2257. foreach ($languages as $lInfo) {
  2258. if ($GLOBALS['BE_USER']->checkLanguageAccess($lInfo['uid']) && (!$checkPageLanguageOverlay || $lInfo['uid'] <= 0 || is_array($pageOverlays[$lInfo['uid']]))) {
  2259. $editData['meta']['currentLangId'][] = $lInfo['ISOcode'];
  2260. }
  2261. }
  2262. if (!is_array($editData['meta']['currentLangId']) || !count($editData['meta']['currentLangId'])) {
  2263. $editData['meta']['currentLangId'] = array('DEF');
  2264. }
  2265. $editData['meta']['currentLangId'] = array_unique($editData['meta']['currentLangId']);
  2266. //TODO: Why is this commented out?
  2267. // if (!$langDisabled && count($languages) > 1) {
  2268. // $item.=$this->getSingleField_typeFlex_langMenu($languages, $PA['itemFormElName'].'[meta][currentLangId]', $editData['meta']['currentLangId']).'<br />';
  2269. // }
  2270. $PA['_noEditDEF'] = FALSE;
  2271. if ($langChildren || $langDisabled) {
  2272. $rotateLang = array('DEF');
  2273. } else {
  2274. if (!in_array('DEF', $editData['meta']['currentLangId'])) {
  2275. array_unshift($editData['meta']['currentLangId'], 'DEF');
  2276. $PA['_noEditDEF'] = TRUE;
  2277. }
  2278. $rotateLang = $editData['meta']['currentLangId'];
  2279. }
  2280. // Tabs sheets
  2281. if (is_array($dataStructArray['sheets'])) {
  2282. $tabsToTraverse = array_keys($dataStructArray['sheets']);
  2283. } else {
  2284. $tabsToTraverse = array($sheet);
  2285. }
  2286. foreach ($rotateLang as $lKey) {
  2287. if (!$langChildren && !$langDisabled) {
  2288. $item .= '<strong>' . $this->getLanguageIcon($table, $row, 'v' . $lKey) . $lKey . ':</strong>';
  2289. }
  2290. $tabParts = array();
  2291. foreach ($tabsToTraverse as $sheet) {
  2292. list ($dataStruct, $sheet) = t3lib_div::resolveSheetDefInDS($dataStructArray, $sheet);
  2293. // Render sheet:
  2294. if (is_array($dataStruct['ROOT']) && is_array($dataStruct['ROOT']['el'])) {
  2295. $lang = 'l' . $lKey; // Default language, other options are "lUK" or whatever country code (independant of system!!!)
  2296. $PA['_valLang'] = $langChildren && !$langDisabled ? $editData['meta']['currentLangId'] : 'DEF'; // Default language, other options are "lUK" or whatever country code (independant of system!!!)
  2297. $PA['_lang'] = $lang;
  2298. // Assemble key for loading the correct CSH file
  2299. $dsPointerFields = t3lib_div::trimExplode(',', $GLOBALS['TCA'][$table]['columns'][$field]['config']['ds_pointerField'], TRUE);
  2300. $PA['_cshKey'] = $table . '.' . $field;
  2301. foreach ($dsPointerFields as $key) {
  2302. $PA['_cshKey'] .= '.' . $row[$key];
  2303. }
  2304. // Push the sheet level tab to DynNestedStack
  2305. if (is_array($dataStructArray['sheets'])) {
  2306. $tabIdentString = $GLOBALS['TBE_TEMPLATE']->getDynTabMenuId('TCEFORMS:flexform:' . $PA['itemFormElName'] . $PA['_lang']);
  2307. $this->pushToDynNestedStack('tab', $tabIdentString . '-' . (count($tabParts) + 1));
  2308. }
  2309. // Render flexform:
  2310. $tRows = $this->getSingleField_typeFlex_draw(
  2311. $dataStruct['ROOT']['el'],
  2312. $editData['data'][$sheet][$lang],
  2313. $table,
  2314. $field,
  2315. $row,
  2316. $PA,
  2317. '[data][' . $sheet . '][' . $lang . ']'
  2318. );
  2319. $sheetContent = '<div class="typo3-TCEforms-flexForm">' . $tRows . '</div>';
  2320. // Pop the sheet level tab from DynNestedStack
  2321. if (is_array($dataStructArray['sheets'])) {
  2322. $this->popFromDynNestedStack('tab', $tabIdentString . '-' . (count($tabParts) + 1));
  2323. }
  2324. } else {
  2325. $sheetContent = 'Data Structure ERROR: No ROOT element found for sheet "' . $sheet . '".';
  2326. }
  2327. // Add to tab:
  2328. $tabParts[] = array(
  2329. 'label' => ($dataStruct['ROOT']['TCEforms']['sheetTitle'] ? $this->sL($dataStruct['ROOT']['TCEforms']['sheetTitle']) : $sheet),
  2330. 'description' => ($dataStruct['ROOT']['TCEforms']['sheetDescription'] ? $this->sL($dataStruct['ROOT']['TCEforms']['sheetDescription']) : ''),
  2331. 'linkTitle' => ($dataStruct['ROOT']['TCEforms']['sheetShortDescr'] ? $this->sL($dataStruct['ROOT']['TCEforms']['sheetShortDescr']) : ''),
  2332. 'content' => $sheetContent
  2333. );
  2334. }
  2335. if (is_array($dataStructArray['sheets'])) {
  2336. $dividersToTabsBehaviour = (isset($GLOBALS['TCA'][$table]['ctrl']['dividers2tabs']) ? $GLOBALS['TCA'][$table]['ctrl']['dividers2tabs'] : 1);
  2337. $item .= $this->getDynTabMenu($tabParts, 'TCEFORMS:flexform:' . $PA['itemFormElName'] . $PA['_lang'], $dividersToTabsBehaviour);
  2338. } else {
  2339. $item .= $sheetContent;
  2340. }
  2341. }
  2342. } else {
  2343. $item = 'Data Structure ERROR: ' . $dataStructArray;
  2344. }
  2345. return $item;
  2346. }
  2347. /**
  2348. * Creates the language menu for FlexForms:
  2349. *
  2350. * @param [type] $languages: ...
  2351. * @param [type] $elName: ...
  2352. * @param [type] $selectedLanguage: ...
  2353. * @param [type] $multi: ...
  2354. * @return string HTML for menu
  2355. */
  2356. function getSingleField_typeFlex_langMenu($languages, $elName, $selectedLanguage, $multi = 1) {
  2357. $opt = array();
  2358. foreach ($languages as $lArr) {
  2359. $opt[] = '<option value="' . htmlspecialchars($lArr['ISOcode']) . '"' . (in_array($lArr['ISOcode'], $selectedLanguage) ? ' selected="selected"' : '') . '>' . htmlspecialchars($lArr['title']) . '</option>';
  2360. }
  2361. $output = '<select id="' . uniqid('tceforms-multiselect-') . ' class="tceforms-select tceforms-multiselect tceforms-flexlangmenu" name="' . $elName . '[]"' . ($multi ? ' multiple="multiple" size="' . count($languages) . '"' : '') . '>' . implode('', $opt) . '</select>';
  2362. return $output;
  2363. }
  2364. /**
  2365. * Creates the menu for selection of the sheets:
  2366. *
  2367. * @param array Sheet array for which to render the menu
  2368. * @param string Form element name of the field containing the sheet pointer
  2369. * @param string Current sheet key
  2370. * @return string HTML for menu
  2371. */
  2372. function getSingleField_typeFlex_sheetMenu($sArr, $elName, $sheetKey) {
  2373. $tCells = array();
  2374. $pct = round(100 / count($sArr));
  2375. foreach ($sArr as $sKey => $sheetCfg) {
  2376. if ($GLOBALS['BE_USER']->jsConfirmation(1)) {
  2377. $onClick = 'if (confirm(TBE_EDITOR.labels.onChangeAlert) && TBE_EDITOR.checkSubmit(-1)){' . $this->elName($elName) . ".value='" . $sKey . "'; TBE_EDITOR.submitForm()};";
  2378. } else {
  2379. $onClick = 'if(TBE_EDITOR.checkSubmit(-1)){ ' . $this->elName($elName) . ".value='" . $sKey . "'; TBE_EDITOR.submitForm();}";
  2380. }
  2381. $tCells[] = '<td width="' . $pct . '%" style="' . ($sKey == $sheetKey ? 'background-color: #9999cc; font-weight: bold;' : 'background-color: #aaaaaa;') . ' cursor: hand;" onclick="' . htmlspecialchars($onClick) . '" align="center">' .
  2382. ($sheetCfg['ROOT']['TCEforms']['sheetTitle'] ? $this->sL($sheetCfg['ROOT']['TCEforms']['sheetTitle']) : $sKey) .
  2383. '</td>';
  2384. }
  2385. return '<table border="0" cellpadding="0" cellspacing="2" class="typo3-TCEforms-flexForm-sheetMenu"><tr>' . implode('', $tCells) . '</tr></table>';
  2386. }
  2387. /**
  2388. * Recursive rendering of flexforms
  2389. *
  2390. * @param array (part of) Data Structure for which to render. Keys on first level is flex-form fields
  2391. * @param array (part of) Data array of flexform corresponding to the input DS. Keys on first level is flex-form field names
  2392. * @param string Table name, eg. tt_content
  2393. * @param string Field name, eg. tx_templavoila_flex
  2394. * @param array The particular record from $table in which the field $field is found
  2395. * @param array Array of standard information for rendering of a form field in TCEforms, see other rendering functions too
  2396. * @param string Form field prefix, eg. "[data][sDEF][lDEF][...][...]"
  2397. * @param integer Indicates nesting level for the function call
  2398. * @param string Prefix for ID-values
  2399. * @param boolean Defines whether the next flexform level is open or closed. Comes from _TOGGLE pseudo field in FlexForm xml.
  2400. * @return string HTMl code for form.
  2401. */
  2402. function getSingleField_typeFlex_draw($dataStruct, $editData, $table, $field, $row, &$PA, $formPrefix = '', $level = 0, $idPrefix = 'ID', $toggleClosed = FALSE) {
  2403. $output = '';
  2404. $mayRestructureFlexforms = $GLOBALS['BE_USER']->checkLanguageAccess(0);
  2405. // Data Structure array must be ... and array of course...
  2406. if (is_array($dataStruct)) {
  2407. foreach ($dataStruct as $key => $value) { // Traversing fields in structure:
  2408. if (is_array($value)) { // The value of each entry must be an array.
  2409. // ********************
  2410. // Making the row:
  2411. // ********************
  2412. // Title of field:
  2413. $theTitle = htmlspecialchars(t3lib_div::fixed_lgd_cs($this->sL($value['tx_templavoila']['title']), 30));
  2414. // If it's a "section" or "container":
  2415. if ($value['type'] == 'array') {
  2416. // Creating IDs for form fields:
  2417. // 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.
  2418. $thisId = t3lib_div::shortMd5(uniqid('id', TRUE)); // This is a suffix used for forms on this level
  2419. $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.
  2420. // If it's a "section" containing other elements:
  2421. if ($value['section']) {
  2422. // Load script.aculo.us if flexform sections can be moved by drag'n'drop:
  2423. $GLOBALS['SOBE']->doc->getPageRenderer()->loadScriptaculous();
  2424. // Render header of section:
  2425. $output .= '<div class="t3-form-field-label-flexsection"><strong>' . $theTitle . '</strong></div>';
  2426. // Render elements in data array for section:
  2427. $tRows = array();
  2428. $cc = 0;
  2429. if (is_array($editData[$key]['el'])) {
  2430. foreach ($editData[$key]['el'] as $k3 => $v3) {
  2431. $cc = $k3;
  2432. if (is_array($v3)) {
  2433. $theType = key($v3);
  2434. $theDat = $v3[$theType];
  2435. $newSectionEl = $value['el'][$theType];
  2436. if (is_array($newSectionEl)) {
  2437. $tRows[] = $this->getSingleField_typeFlex_draw(
  2438. array($theType => $newSectionEl),
  2439. array($theType => $theDat),
  2440. $table,
  2441. $field,
  2442. $row,
  2443. $PA,
  2444. $formPrefix . '[' . $key . '][el][' . $cc . ']',
  2445. $level + 1,
  2446. $idTagPrefix,
  2447. $v3['_TOGGLE']
  2448. );
  2449. }
  2450. }
  2451. }
  2452. }
  2453. // Now, we generate "templates" for new elements that could be added to this section by traversing all possible types of content inside the section:
  2454. // 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...
  2455. // Preserving internal variables we don't want to change:
  2456. $TEMP_requiredElements = $this->requiredElements;
  2457. // Traversing possible types of new content in the section:
  2458. $newElementsLinks = array();
  2459. foreach ($value['el'] as $nnKey => $nCfg) {
  2460. $additionalJS_post_saved = $this->additionalJS_post;
  2461. $this->additionalJS_post = array();
  2462. $additionalJS_submit_saved = $this->additionalJS_submit;
  2463. $this->additionalJS_submit = array();
  2464. $newElementTemplate = $this->getSingleField_typeFlex_draw(
  2465. array($nnKey => $nCfg),
  2466. array(),
  2467. $table,
  2468. $field,
  2469. $row,
  2470. $PA,
  2471. $formPrefix . '[' . $key . '][el][' . $idTagPrefix . '-form]',
  2472. $level + 1,
  2473. $idTagPrefix
  2474. );
  2475. // Makes a "Add new" link:
  2476. $var = uniqid('idvar');
  2477. $replace = 'replace(/' . $idTagPrefix . '-/g,"' . $idTagPrefix . '-"+' . $var . '+"-")';
  2478. $onClickInsert = 'var ' . $var . ' = "' . 'idx"+(new Date()).getTime();';
  2479. // Do not replace $isTagPrefix in setActionStatus() because it needs section id!
  2480. $onClickInsert .= 'new Insertion.Bottom($("' . $idTagPrefix . '"), unescape("' . rawurlencode($newElementTemplate) . '").' . $replace . '); setActionStatus("' . $idTagPrefix . '");';
  2481. $onClickInsert .= 'eval(unescape("' . rawurlencode(implode(';', $this->additionalJS_post)) . '").' . $replace . ');';
  2482. $onClickInsert .= 'TBE_EDITOR.addActionChecks("submit", unescape("' . rawurlencode(implode(';', $this->additionalJS_submit)) . '").' . $replace . ');';
  2483. $onClickInsert .= 'return false;';
  2484. // 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...
  2485. $this->additionalJS_post = $additionalJS_post_saved;
  2486. $this->additionalJS_submit = $additionalJS_submit_saved;
  2487. $new = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:cm.new', 1);
  2488. $newElementsLinks[] = '<a href="#" onclick="' . htmlspecialchars($onClickInsert) . '">' .
  2489. t3lib_iconWorks::getSpriteIcon('actions-document-new') .
  2490. htmlspecialchars(t3lib_div::fixed_lgd_cs($this->sL($nCfg['tx_templavoila']['title']), 30)) . '</a>';
  2491. }
  2492. // Reverting internal variables we don't want to change:
  2493. $this->requiredElements = $TEMP_requiredElements;
  2494. // Adding the sections:
  2495. $toggleAll = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.toggleall', 1);
  2496. $output .= '
  2497. <div class="t3-form-field-toggle-flexsection">
  2498. <a href="#" onclick="' . htmlspecialchars('flexFormToggleSubs("' . $idTagPrefix . '"); return false;') . '">'
  2499. . t3lib_iconWorks::getSpriteIcon('actions-move-right', array('title' => $toggleAll)) . $toggleAll . '
  2500. </a>
  2501. </div>
  2502. <div id="' . $idTagPrefix . '" class="t3-form-field-container-flexsection">' . implode('', $tRows) . '</div>';
  2503. $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>' : '';
  2504. } else {
  2505. // It is a container
  2506. $toggleIcon_open = t3lib_iconWorks::getSpriteIcon('actions-move-down');
  2507. $toggleIcon_close = t3lib_iconWorks::getSpriteIcon('actions-move-right');
  2508. // Create on-click actions.
  2509. //$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.
  2510. $onClickRemove = 'if (confirm("Are you sure?")){/*###REMOVE###*/;$("' . $idTagPrefix . '").hide();setActionStatus("' . $idPrefix . '");} return false;';
  2511. $onClickToggle = 'flexFormToggle("' . $idTagPrefix . '"); return false;';
  2512. $onMove = 'flexFormSortable("' . $idPrefix . '")';
  2513. // 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.
  2514. // Putting together header of a section. Sections can be removed, copied, opened/closed, moved up and down:
  2515. // 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.
  2516. // 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.
  2517. $ctrlHeader = '
  2518. <table class="t3-form-field-header-flexsection" onmousedown="' . ($mayRestructureFlexforms ? htmlspecialchars($onMove) : '') . '">
  2519. <tr>
  2520. <td>
  2521. <a href="#" onclick="' . htmlspecialchars($onClickToggle) . '" id="' . $idTagPrefix . '-toggle">
  2522. ' . ($toggleClosed ? $toggleIcon_close : $toggleIcon_open) . '
  2523. </a>
  2524. <strong>' . $theTitle . '</strong> <em><span id="' . $idTagPrefix . '-preview"></span></em>
  2525. </td>
  2526. <td align="right">' .
  2527. ($mayRestructureFlexforms ? t3lib_iconWorks::getSpriteIcon('actions-move-move', array('title' => 'Drag to Move')) : '') .
  2528. ($mayRestructureFlexforms ? '<a href="#" onclick="' . htmlspecialchars($onClickRemove) . '">' . t3lib_iconWorks::getSpriteIcon('actions-edit-delete', array('title' => 'Delete')) : '') .
  2529. '</td>
  2530. </tr>
  2531. </table>';
  2532. $s = t3lib_div::revExplode('[]', $formPrefix, 2);
  2533. $actionFieldName = '_ACTION_FLEX_FORM' . $PA['itemFormElName'] . $s[0] . '][_ACTION][' . $s[1];
  2534. // Push the container to DynNestedStack as it may be toggled
  2535. $this->pushToDynNestedStack('flex', $idTagPrefix);
  2536. // Putting together the container:
  2537. $this->additionalJS_delete = array();
  2538. $output .= '
  2539. <div id="' . $idTagPrefix . '" class="t3-form-field-container-flexsections">
  2540. <input id="' . $idTagPrefix . '-action" type="hidden" name="' . htmlspecialchars($actionFieldName) . '" value=""/>
  2541. ' . $ctrlHeader . '
  2542. <div class="t3-form-field-record-flexsection" id="' . $idTagPrefix . '-content"' . ($toggleClosed ? ' style="display:none;"' : '') . '>' .
  2543. $this->getSingleField_typeFlex_draw(
  2544. $value['el'],
  2545. $editData[$key]['el'],
  2546. $table,
  2547. $field,
  2548. $row,
  2549. $PA,
  2550. $formPrefix . '[' . $key . '][el]',
  2551. $level + 1,
  2552. $idTagPrefix
  2553. ) . '
  2554. </div>
  2555. <input id="' . $idTagPrefix . '-toggleClosed" type="hidden" name="' . htmlspecialchars('data[' . $table . '][' . $row['uid'] . '][' . $field . ']' . $formPrefix . '[_TOGGLE]') . '" value="' . ($toggleClosed ? 1 : 0) . '" />
  2556. </div>';
  2557. $output = str_replace('/*###REMOVE###*/', t3lib_div::slashJS(htmlspecialchars(implode('', $this->additionalJS_delete))), $output);
  2558. // 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.
  2559. // Pop the container from DynNestedStack
  2560. $this->popFromDynNestedStack('flex', $idTagPrefix);
  2561. }
  2562. // If it's a "single form element":
  2563. } elseif (is_array($value['TCEforms']['config'])) { // Rendering a single form element:
  2564. if (is_array($PA['_valLang'])) {
  2565. $rotateLang = $PA['_valLang'];
  2566. } else {
  2567. $rotateLang = array($PA['_valLang']);
  2568. }
  2569. $conditionData = is_array($editData) ? $editData : array();
  2570. // add current $row to data processed by isDisplayCondition()
  2571. $conditionData['parentRec'] = $row;
  2572. $tRows = array();
  2573. foreach ($rotateLang as $vDEFkey) {
  2574. $vDEFkey = 'v' . $vDEFkey;
  2575. if (!$value['TCEforms']['displayCond'] || $this->isDisplayCondition($value['TCEforms']['displayCond'], $conditionData, $vDEFkey)) {
  2576. $fakePA = array();
  2577. $fakePA['fieldConf'] = array(
  2578. 'label' => $this->sL(trim($value['TCEforms']['label'])),
  2579. 'config' => $value['TCEforms']['config'],
  2580. 'defaultExtras' => $value['TCEforms']['defaultExtras'],
  2581. 'onChange' => $value['TCEforms']['onChange']
  2582. );
  2583. if ($PA['_noEditDEF'] && $PA['_lang'] === 'lDEF') {
  2584. $fakePA['fieldConf']['config'] = array(
  2585. 'type' => 'none',
  2586. 'rows' => 2
  2587. );
  2588. }
  2589. if (
  2590. $fakePA['fieldConf']['onChange'] == 'reload' ||
  2591. ($GLOBALS['TCA'][$table]['ctrl']['type'] && !strcmp($key, $GLOBALS['TCA'][$table]['ctrl']['type'])) ||
  2592. ($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'] && t3lib_div::inList($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'], $key))) {
  2593. if ($GLOBALS['BE_USER']->jsConfirmation(1)) {
  2594. $alertMsgOnChange = 'if (confirm(TBE_EDITOR.labels.onChangeAlert) && TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };';
  2595. } else {
  2596. $alertMsgOnChange = 'if(TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm();}';
  2597. }
  2598. } else {
  2599. $alertMsgOnChange = '';
  2600. }
  2601. $fakePA['fieldChangeFunc'] = $PA['fieldChangeFunc'];
  2602. if (strlen($alertMsgOnChange)) {
  2603. $fakePA['fieldChangeFunc']['alert'] = $alertMsgOnChange;
  2604. }
  2605. $fakePA['onFocus'] = $PA['onFocus'];
  2606. $fakePA['label'] = $PA['label'];
  2607. $fakePA['itemFormElName'] = $PA['itemFormElName'] . $formPrefix . '[' . $key . '][' . $vDEFkey . ']';
  2608. $fakePA['itemFormElName_file'] = $PA['itemFormElName_file'] . $formPrefix . '[' . $key . '][' . $vDEFkey . ']';
  2609. $fakePA['itemFormElID'] = $fakePA['itemFormElName'];
  2610. if (isset($editData[$key][$vDEFkey])) {
  2611. $fakePA['itemFormElValue'] = $editData[$key][$vDEFkey];
  2612. } else {
  2613. $fakePA['itemFormElValue'] = $fakePA['fieldConf']['config']['default'];
  2614. }
  2615. $theFormEl = $this->getSingleField_SW($table, $field, $row, $fakePA);
  2616. $theTitle = htmlspecialchars($fakePA['fieldConf']['label']);
  2617. if (!in_array('DEF', $rotateLang)) {
  2618. $defInfo = '<div class="typo3-TCEforms-originalLanguageValue">' . $this->getLanguageIcon($table, $row, 0) .
  2619. $this->previewFieldValue($editData[$key]['vDEF'], $fakePA['fieldConf'], $field) . '&nbsp;</div>';
  2620. } else {
  2621. $defInfo = '';
  2622. }
  2623. if (!$PA['_noEditDEF']) {
  2624. $prLang = $this->getAdditionalPreviewLanguages();
  2625. foreach ($prLang as $prL) {
  2626. $defInfo .= '<div class="typo3-TCEforms-originalLanguageValue">' . $this->getLanguageIcon($table, $row, 'v' . $prL['ISOcode']) .
  2627. $this->previewFieldValue($editData[$key]['v' . $prL['ISOcode']], $fakePA['fieldConf'], $field) . '&nbsp;</div>';
  2628. }
  2629. }
  2630. $languageIcon = '';
  2631. if ($vDEFkey != 'vDEF') {
  2632. $languageIcon = $this->getLanguageIcon($table, $row, $vDEFkey);
  2633. }
  2634. // Put row together
  2635. // possible linebreaks in the label through xml: \n => <br/>, usage of nl2br() not possible, so it's done through str_replace
  2636. $processedTitle = str_replace('\n', '<br />', $theTitle);
  2637. $tRows[] = '<div class="t3-form-field-container t3-form-field-container-flex">' .
  2638. '<div class="t3-form-field-label t3-form-field-label-flex">' .
  2639. $languageIcon .
  2640. t3lib_BEfunc::wrapInHelp($PA['_cshKey'], $key, $processedTitle) .
  2641. '</div>
  2642. <div class="t3-form-field t3-form-field-flex">' . $theFormEl . $defInfo . $this->renderVDEFDiff($editData[$key], $vDEFkey) . '</div>
  2643. </div>';
  2644. }
  2645. }
  2646. if (count($tRows)) {
  2647. $output .= implode('', $tRows);
  2648. }
  2649. }
  2650. }
  2651. }
  2652. }
  2653. return $output;
  2654. }
  2655. /**
  2656. * Handler for unknown types.
  2657. *
  2658. * @param string The table name of the record
  2659. * @param string The field name which this element is supposed to edit
  2660. * @param array The record data array where the value(s) for the field can be found
  2661. * @param array An array with additional configuration options.
  2662. * @return string The HTML code for the TCEform field
  2663. */
  2664. function getSingleField_typeUnknown($table, $field, $row, &$PA) {
  2665. $item = 'Unknown type: ' . $PA['fieldConf']['config']['form_type'] . '<br />';
  2666. return $item;
  2667. }
  2668. /**
  2669. * User defined field type
  2670. *
  2671. * @param string The table name of the record
  2672. * @param string The field name which this element is supposed to edit
  2673. * @param array The record data array where the value(s) for the field can be found
  2674. * @param array An array with additional configuration options.
  2675. * @return string The HTML code for the TCEform field
  2676. */
  2677. function getSingleField_typeUser($table, $field, $row, &$PA) {
  2678. $PA['table'] = $table;
  2679. $PA['field'] = $field;
  2680. $PA['row'] = $row;
  2681. $PA['pObj'] =& $this;
  2682. return t3lib_div::callUserFunction($PA['fieldConf']['config']['userFunc'], $PA, $this);
  2683. }
  2684. /************************************************************
  2685. *
  2686. * Field content processing
  2687. *
  2688. ************************************************************/
  2689. /**
  2690. * Format field content of various types if $config['format'] is set to date, filesize, ..., user
  2691. * This is primarily for the field type none but can be used for user field types for example
  2692. *
  2693. * @param array Configuration for the display
  2694. * @param string The value to display
  2695. * @return string Formatted Field content
  2696. */
  2697. function formatValue($config, $itemValue) {
  2698. $format = trim($config['format']);
  2699. switch ($format) {
  2700. case 'date':
  2701. if ($itemValue) {
  2702. $option = trim($config['format.']['option']);
  2703. if ($option) {
  2704. if ($config['format.']['strftime']) {
  2705. $value = strftime($option, $itemValue);
  2706. } else {
  2707. $value = date($option, $itemValue);
  2708. }
  2709. } else {
  2710. $value = date('d-m-Y', $itemValue);
  2711. }
  2712. } else {
  2713. $value = '';
  2714. }
  2715. if ($config['format.']['appendAge']) {
  2716. $value .= ' (' .
  2717. t3lib_BEfunc::calcAge(($GLOBALS['EXEC_TIME'] - $itemValue), $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.minutesHoursDaysYears')) .
  2718. ')';
  2719. }
  2720. $itemValue = $value;
  2721. break;
  2722. case 'datetime': // compatibility with "eval" (type "input")
  2723. $itemValue = date('H:i d-m-Y', $itemValue);
  2724. break;
  2725. case 'time': // compatibility with "eval" (type "input")
  2726. $itemValue = date('H:i', $itemValue);
  2727. break;
  2728. case 'timesec': // compatibility with "eval" (type "input")
  2729. $itemValue = date('H:i:s', $itemValue);
  2730. break;
  2731. case 'year': // compatibility with "eval" (type "input")
  2732. $itemValue = date('Y', $itemValue);
  2733. break;
  2734. case 'int':
  2735. $baseArr = array('dec' => 'd', 'hex' => 'x', 'HEX' => 'X', 'oct' => 'o', 'bin' => 'b');
  2736. $base = trim($config['format.']['base']);
  2737. $format = $baseArr[$base] ? $baseArr[$base] : 'd';
  2738. $itemValue = sprintf('%' . $format, $itemValue);
  2739. break;
  2740. case 'float':
  2741. $precision = t3lib_div::intInRange($config['format.']['precision'], 1, 10, 2);
  2742. $itemValue = sprintf('%.' . $precision . 'f', $itemValue);
  2743. break;
  2744. case 'number':
  2745. $format = trim($config['format.']['option']);
  2746. $itemValue = sprintf('%' . $format, $itemValue);
  2747. break;
  2748. case 'md5':
  2749. $itemValue = md5($itemValue);
  2750. break;
  2751. case 'filesize':
  2752. $value = t3lib_div::formatSize(intval($itemValue));
  2753. if ($config['format.']['appendByteSize']) {
  2754. $value .= ' (' . $itemValue . ')';
  2755. }
  2756. $itemValue = $value;
  2757. break;
  2758. case 'user':
  2759. $func = trim($config['format.']['userFunc']);
  2760. if ($func) {
  2761. $params = array(
  2762. 'value' => $itemValue,
  2763. 'args' => $config['format.']['userFunc'],
  2764. 'config' => $config,
  2765. 'pObj' => &$this
  2766. );
  2767. $itemValue = t3lib_div::callUserFunction($func, $params, $this);
  2768. }
  2769. break;
  2770. default:
  2771. break;
  2772. }
  2773. return $itemValue;
  2774. }
  2775. /************************************************************
  2776. *
  2777. * "Configuration" fetching/processing functions
  2778. *
  2779. ************************************************************/
  2780. /**
  2781. * Calculate and return the current "types" pointer value for a record
  2782. *
  2783. * @param string The table name. MUST be in $TCA
  2784. * @param array The row from the table, should contain at least the "type" field, if applicable.
  2785. * @return string Return the "type" value for this record, ready to pick a "types" configuration from the $TCA array.
  2786. */
  2787. function getRTypeNum($table, $row) {
  2788. global $TCA;
  2789. // If there is a "type" field configured...
  2790. if ($TCA[$table]['ctrl']['type']) {
  2791. $typeFieldName = $TCA[$table]['ctrl']['type'];
  2792. $typeFieldConfig = $TCA[$table]['columns'][$typeFieldName];
  2793. $typeNum = $this->getLanguageOverlayRawValue($table, $row, $typeFieldName, $typeFieldConfig);
  2794. if (!strcmp($typeNum, '')) {
  2795. $typeNum = 0;
  2796. } // If that value is an empty string, set it to "0" (zero)
  2797. } else {
  2798. $typeNum = 0; // If no "type" field, then set to "0" (zero)
  2799. }
  2800. $typeNum = (string) $typeNum; // Force to string. Necessary for eg '-1' to be recognized as a type value.
  2801. if (!$TCA[$table]['types'][$typeNum]) { // However, if the type "0" is not found in the "types" array, then default to "1" (for historical reasons)
  2802. $typeNum = 1;
  2803. }
  2804. return $typeNum;
  2805. }
  2806. /**
  2807. * Used to adhoc-rearrange the field order normally set in the [types][showitem] list
  2808. *
  2809. * @param array A [types][showitem] list of fields, exploded by ","
  2810. * @return array Returns rearranged version (keys are changed around as well.)
  2811. * @see getMainFields()
  2812. */
  2813. function rearrange($fields) {
  2814. $fO = array_flip(t3lib_div::trimExplode(',', $this->fieldOrder, 1));
  2815. $newFields = array();
  2816. foreach ($fields as $cc => $content) {
  2817. $cP = t3lib_div::trimExplode(';', $content);
  2818. if (isset($fO[$cP[0]])) {
  2819. $newFields[$fO[$cP[0]]] = $content;
  2820. unset($fields[$cc]);
  2821. }
  2822. }
  2823. ksort($newFields);
  2824. $fields = array_merge($newFields, $fields); // Candidate for t3lib_div::array_merge() if integer-keys will some day make trouble...
  2825. return $fields;
  2826. }
  2827. /**
  2828. * Producing an array of field names NOT to display in the form, based on settings from subtype_value_field, bitmask_excludelist_bits etc.
  2829. * Notice, this list is in NO way related to the "excludeField" flag
  2830. *
  2831. * @param string Table name, MUST be in $TCA
  2832. * @param array A record from table.
  2833. * @param string A "type" pointer value, probably the one calculated based on the record array.
  2834. * @return array Array with fieldnames as values. The fieldnames are those which should NOT be displayed "anyways"
  2835. * @see getMainFields()
  2836. */
  2837. function getExcludeElements($table, $row, $typeNum) {
  2838. global $TCA;
  2839. // Init:
  2840. $excludeElements = array();
  2841. // If a subtype field is defined for the type
  2842. if ($TCA[$table]['types'][$typeNum]['subtype_value_field']) {
  2843. $sTfield = $TCA[$table]['types'][$typeNum]['subtype_value_field'];
  2844. if (trim($TCA[$table]['types'][$typeNum]['subtypes_excludelist'][$row[$sTfield]])) {
  2845. $excludeElements = t3lib_div::trimExplode(',', $TCA[$table]['types'][$typeNum]['subtypes_excludelist'][$row[$sTfield]], 1);
  2846. }
  2847. }
  2848. // If a bitmask-value field has been configured, then find possible fields to exclude based on that:
  2849. if ($TCA[$table]['types'][$typeNum]['bitmask_value_field']) {
  2850. $sTfield = $TCA[$table]['types'][$typeNum]['bitmask_value_field'];
  2851. $sTValue = t3lib_div::intInRange($row[$sTfield], 0);
  2852. if (is_array($TCA[$table]['types'][$typeNum]['bitmask_excludelist_bits'])) {
  2853. foreach ($TCA[$table]['types'][$typeNum]['bitmask_excludelist_bits'] as $bitKey => $eList) {
  2854. $bit = substr($bitKey, 1);
  2855. if (t3lib_div::testInt($bit)) {
  2856. $bit = t3lib_div::intInRange($bit, 0, 30);
  2857. if (
  2858. (substr($bitKey, 0, 1) == '-' && !($sTValue & pow(2, $bit))) ||
  2859. (substr($bitKey, 0, 1) == '+' && ($sTValue & pow(2, $bit)))
  2860. ) {
  2861. $excludeElements = array_merge($excludeElements, t3lib_div::trimExplode(',', $eList, 1));
  2862. }
  2863. }
  2864. }
  2865. }
  2866. }
  2867. // Return the array of elements:
  2868. return $excludeElements;
  2869. }
  2870. /**
  2871. * Finds possible field to add to the form, based on subtype fields.
  2872. *
  2873. * @param string Table name, MUST be in $TCA
  2874. * @param array A record from table.
  2875. * @param string A "type" pointer value, probably the one calculated based on the record array.
  2876. * @return array An array containing two values: 1) Another array containing fieldnames to add and 2) the subtype value field.
  2877. * @see getMainFields()
  2878. */
  2879. function getFieldsToAdd($table, $row, $typeNum) {
  2880. global $TCA;
  2881. // Init:
  2882. $addElements = array();
  2883. // If a subtype field is defined for the type
  2884. if ($TCA[$table]['types'][$typeNum]['subtype_value_field']) {
  2885. $sTfield = $TCA[$table]['types'][$typeNum]['subtype_value_field'];
  2886. if (trim($TCA[$table]['types'][$typeNum]['subtypes_addlist'][$row[$sTfield]])) {
  2887. $addElements = t3lib_div::trimExplode(',', $TCA[$table]['types'][$typeNum]['subtypes_addlist'][$row[$sTfield]], 1);
  2888. }
  2889. }
  2890. // Return the return
  2891. return array($addElements, $sTfield);
  2892. }
  2893. /**
  2894. * Merges the current [types][showitem] array with the array of fields to add for the current subtype field of the "type" value.
  2895. *
  2896. * @param array A [types][showitem] list of fields, exploded by ","
  2897. * @param array The output from getFieldsToAdd()
  2898. * @return array Return the modified $fields array.
  2899. * @see getMainFields(),getFieldsToAdd()
  2900. */
  2901. function mergeFieldsWithAddedFields($fields, $fieldsToAdd) {
  2902. if (count($fieldsToAdd[0])) {
  2903. $c = 0;
  2904. foreach ($fields as $fieldInfo) {
  2905. $parts = explode(';', $fieldInfo);
  2906. if (!strcmp(trim($parts[0]), $fieldsToAdd[1])) {
  2907. array_splice(
  2908. $fields,
  2909. $c + 1,
  2910. 0,
  2911. $fieldsToAdd[0]
  2912. );
  2913. break;
  2914. }
  2915. $c++;
  2916. }
  2917. }
  2918. return $fields;
  2919. }
  2920. /**
  2921. * Returns TSconfig for table/row
  2922. * 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.
  2923. *
  2924. * @param string The table name
  2925. * @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.)
  2926. * @param string Optionally you can specify the field name as well. In that case the TSconfig for the field is returned.
  2927. * @return mixed The TSconfig values (probably in an array)
  2928. * @see t3lib_BEfunc::getTCEFORM_TSconfig()
  2929. */
  2930. function setTSconfig($table, $row, $field = '') {
  2931. $mainKey = $table . ':' . $row['uid'];
  2932. if (!isset($this->cachedTSconfig[$mainKey])) {
  2933. $this->cachedTSconfig[$mainKey] = t3lib_BEfunc::getTCEFORM_TSconfig($table, $row);
  2934. }
  2935. if ($field) {
  2936. return $this->cachedTSconfig[$mainKey][$field];
  2937. } else {
  2938. return $this->cachedTSconfig[$mainKey];
  2939. }
  2940. }
  2941. /**
  2942. * Overrides the TCA field configuration by TSconfig settings.
  2943. *
  2944. * Example TSconfig: TCEform.<table>.<field>.config.appearance.useSortable = 1
  2945. * This overrides the setting in $TCA[<table>]['columns'][<field>]['config']['appearance']['useSortable'].
  2946. *
  2947. * @param array $fieldConfig: TCA field configuration
  2948. * @param array $TSconfig: TSconfig
  2949. * @return array Changed TCA field configuration
  2950. */
  2951. function overrideFieldConf($fieldConfig, $TSconfig) {
  2952. if (is_array($TSconfig)) {
  2953. $TSconfig = t3lib_div::removeDotsFromTS($TSconfig);
  2954. $type = $fieldConfig['type'];
  2955. if (is_array($TSconfig['config']) && is_array($this->allowOverrideMatrix[$type])) {
  2956. // Check if the keys in TSconfig['config'] are allowed to override TCA field config:
  2957. foreach (array_keys($TSconfig['config']) as $key) {
  2958. if (!in_array($key, $this->allowOverrideMatrix[$type], TRUE)) {
  2959. unset($TSconfig['config'][$key]);
  2960. }
  2961. }
  2962. // Override TCA field config by remaining TSconfig['config']:
  2963. if (count($TSconfig['config'])) {
  2964. $fieldConfig = t3lib_div::array_merge_recursive_overrule($fieldConfig, $TSconfig['config']);
  2965. }
  2966. }
  2967. }
  2968. return $fieldConfig;
  2969. }
  2970. /**
  2971. * Returns the "special" configuration (from the "types" "showitem" list) for a fieldname based on input table/record
  2972. * (Not used anywhere...?)
  2973. *
  2974. * @param string The table name
  2975. * @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.)
  2976. * @param string Specify the field name.
  2977. * @return array
  2978. * @see getSpecConfFromString(), t3lib_BEfunc::getTCAtypes()
  2979. */
  2980. function getSpecConfForField($table, $row, $field) {
  2981. // Finds the current "types" configuration for the table/row:
  2982. $types_fieldConfig = t3lib_BEfunc::getTCAtypes($table, $row);
  2983. // If this is an array, then traverse it:
  2984. if (is_array($types_fieldConfig)) {
  2985. foreach ($types_fieldConfig as $vconf) {
  2986. // If the input field name matches one found in the 'types' list, then return the 'special' configuration.
  2987. if ($vconf['field'] == $field) {
  2988. return $vconf['spec'];
  2989. }
  2990. }
  2991. }
  2992. }
  2993. /**
  2994. * Returns the "special" configuration of an "extra" string (non-parsed)
  2995. *
  2996. * @param string The "Part 4" of the fields configuration in "types" "showitem" lists.
  2997. * @param string The ['defaultExtras'] value from field configuration
  2998. * @return array An array with the special options in.
  2999. * @see getSpecConfForField(), t3lib_BEfunc::getSpecConfParts()
  3000. */
  3001. function getSpecConfFromString($extraString, $defaultExtras) {
  3002. return t3lib_BEfunc::getSpecConfParts($extraString, $defaultExtras);
  3003. }
  3004. /**
  3005. * Loads the elements of a palette (collection of secondary options) in an array.
  3006. *
  3007. * @param string The table name
  3008. * @param array The row array
  3009. * @param string The palette number/pointer
  3010. * @param string Optional alternative list of fields for the palette
  3011. * @return array The palette elements
  3012. */
  3013. public function loadPaletteElements($table, $row, $palette, $itemList = '') {
  3014. global $TCA;
  3015. t3lib_div::loadTCA($table);
  3016. $parts = array();
  3017. // Getting excludeElements, if any.
  3018. if (!is_array($this->excludeElements)) {
  3019. $this->excludeElements = $this->getExcludeElements($table, $row, $this->getRTypeNum($table, $row));
  3020. }
  3021. // Load the palette TCEform elements
  3022. if ($TCA[$table] && (is_array($TCA[$table]['palettes'][$palette]) || $itemList)) {
  3023. $itemList = ($itemList ? $itemList : $TCA[$table]['palettes'][$palette]['showitem']);
  3024. if ($itemList) {
  3025. $fields = t3lib_div::trimExplode(',', $itemList, 1);
  3026. foreach ($fields as $info) {
  3027. $fieldParts = t3lib_div::trimExplode(';', $info);
  3028. $theField = $fieldParts[0];
  3029. if ($theField === '--linebreak--') {
  3030. $parts[]['NAME'] = '--linebreak--';
  3031. } elseif (!in_array($theField, $this->excludeElements) && $TCA[$table]['columns'][$theField]) {
  3032. $this->palFieldArr[$palette][] = $theField;
  3033. $elem = $this->getSingleField($table, $theField, $row, $fieldParts[1], 1, '', $fieldParts[2]);
  3034. if (is_array($elem)) {
  3035. $parts[] = $elem;
  3036. }
  3037. }
  3038. }
  3039. }
  3040. }
  3041. return $parts;
  3042. }
  3043. /************************************************************
  3044. *
  3045. * Display of localized content etc.
  3046. *
  3047. ************************************************************/
  3048. /**
  3049. * Will register data from original language records if the current record is a translation of another.
  3050. * 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.
  3051. * Function called from outside (see alt_doc.php + quick edit) before rendering a form for a record
  3052. *
  3053. * @param string Table name of the record being edited
  3054. * @param array Record array of the record being edited
  3055. * @return void
  3056. */
  3057. function registerDefaultLanguageData($table, $rec) {
  3058. global $TCA;
  3059. // Add default language:
  3060. if ($TCA[$table]['ctrl']['languageField']
  3061. && $rec[$TCA[$table]['ctrl']['languageField']] > 0
  3062. && $TCA[$table]['ctrl']['transOrigPointerField']
  3063. && intval($rec[$TCA[$table]['ctrl']['transOrigPointerField']]) > 0) {
  3064. $lookUpTable = $TCA[$table]['ctrl']['transOrigPointerTable'] ? $TCA[$table]['ctrl']['transOrigPointerTable'] : $table;
  3065. // Get data formatted:
  3066. $this->defaultLanguageData[$table . ':' . $rec['uid']] = t3lib_BEfunc::getRecordWSOL($lookUpTable, intval($rec[$TCA[$table]['ctrl']['transOrigPointerField']]));
  3067. // Get data for diff:
  3068. if ($TCA[$table]['ctrl']['transOrigDiffSourceField']) {
  3069. $this->defaultLanguageData_diff[$table . ':' . $rec['uid']] = unserialize($rec[$TCA[$table]['ctrl']['transOrigDiffSourceField']]);
  3070. }
  3071. // If there are additional preview languages, load information for them also:
  3072. $prLang = $this->getAdditionalPreviewLanguages();
  3073. foreach ($prLang as $prL) {
  3074. $t8Tools = t3lib_div::makeInstance('t3lib_transl8tools');
  3075. $tInfo = $t8Tools->translationInfo($lookUpTable, intval($rec[$TCA[$table]['ctrl']['transOrigPointerField']]), $prL['uid']);
  3076. if (is_array($tInfo['translations'][$prL['uid']])) {
  3077. $this->additionalPreviewLanguageData[$table . ':' . $rec['uid']][$prL['uid']] = t3lib_BEfunc::getRecordWSOL($table, intval($tInfo['translations'][$prL['uid']]['uid']));
  3078. }
  3079. }
  3080. }
  3081. }
  3082. /**
  3083. * Creates language-overlay for a field value
  3084. * This means the requested field value will be overridden with the data from the default language.
  3085. * Can be used to render read only fields for example.
  3086. *
  3087. * @param string Table name of the record being edited
  3088. * @param string Field name represented by $item
  3089. * @param array Record array of the record being edited in current language
  3090. * @param array Content of $PA['fieldConf']
  3091. * @return string Unprocessed field value merged with default language data if needed
  3092. */
  3093. function getLanguageOverlayRawValue($table, $row, $field, $fieldConf) {
  3094. global $TCA;
  3095. $value = $row[$field];
  3096. if (is_array($this->defaultLanguageData[$table . ':' . $row['uid']])) {
  3097. if ($fieldConf['l10n_mode'] == 'exclude'
  3098. || ($fieldConf['l10n_mode'] == 'mergeIfNotBlank' && strcmp(trim($this->defaultLanguageData[$table . ':' . $row['uid']][$field]), ''))) {
  3099. $value = $this->defaultLanguageData[$table . ':' . $row['uid']][$field];
  3100. }
  3101. }
  3102. return $value;
  3103. }
  3104. /**
  3105. * Renders the display of default language record content around current field.
  3106. * Will render content if any is found in the internal array, $this->defaultLanguageData, depending on registerDefaultLanguageData() being called prior to this.
  3107. *
  3108. * @param string Table name of the record being edited
  3109. * @param string Field name represented by $item
  3110. * @param array Record array of the record being edited
  3111. * @param string HTML of the form field. This is what we add the content to.
  3112. * @return string Item string returned again, possibly with the original value added to.
  3113. * @see getSingleField(), registerDefaultLanguageData()
  3114. */
  3115. function renderDefaultLanguageContent($table, $field, $row, $item) {
  3116. if (is_array($this->defaultLanguageData[$table . ':' . $row['uid']])) {
  3117. $dLVal = t3lib_BEfunc::getProcessedValue($table, $field, $this->defaultLanguageData[$table . ':' . $row['uid']][$field], 0, 1);
  3118. $fCfg = $GLOBALS['TCA'][$table]['columns'][$field];
  3119. // Don't show content if it's for IRRE child records:
  3120. if ($fCfg['config']['type'] != 'inline') {
  3121. if (strcmp($dLVal, '')) {
  3122. $item .= '<div class="typo3-TCEforms-originalLanguageValue">' . $this->getLanguageIcon($table, $row, 0) .
  3123. $this->previewFieldValue($dLVal, $fCfg, $field) . '&nbsp;</div>';
  3124. }
  3125. $prLang = $this->getAdditionalPreviewLanguages();
  3126. foreach ($prLang as $prL) {
  3127. $dlVal = t3lib_BEfunc::getProcessedValue($table, $field, $this->additionalPreviewLanguageData[$table . ':' . $row['uid']][$prL['uid']][$field], 0, 1);
  3128. if (strcmp($dlVal, '')) {
  3129. $item .= '<div class="typo3-TCEforms-originalLanguageValue">' . $this->getLanguageIcon($table, $row, 'v' . $prL['ISOcode']) .
  3130. $this->previewFieldValue($dlVal, $fCfg, $field) . '&nbsp;</div>';
  3131. }
  3132. }
  3133. }
  3134. }
  3135. return $item;
  3136. }
  3137. /**
  3138. * Renders the diff-view of default language record content compared with what the record was originally translated from.
  3139. * Will render content if any is found in the internal array, $this->defaultLanguageData, depending on registerDefaultLanguageData() being called prior to this.
  3140. *
  3141. * @param string Table name of the record being edited
  3142. * @param string Field name represented by $item
  3143. * @param array Record array of the record being edited
  3144. * @param string HTML of the form field. This is what we add the content to.
  3145. * @return string Item string returned again, possibly with the original value added to.
  3146. * @see getSingleField(), registerDefaultLanguageData()
  3147. */
  3148. function renderDefaultLanguageDiff($table, $field, $row, $item) {
  3149. if (is_array($this->defaultLanguageData_diff[$table . ':' . $row['uid']])) {
  3150. // Initialize:
  3151. $dLVal = array(
  3152. 'old' => $this->defaultLanguageData_diff[$table . ':' . $row['uid']],
  3153. 'new' => $this->defaultLanguageData[$table . ':' . $row['uid']],
  3154. );
  3155. if (isset($dLVal['old'][$field])) { // There must be diff-data:
  3156. if (strcmp($dLVal['old'][$field], $dLVal['new'][$field])) {
  3157. // Create diff-result:
  3158. $t3lib_diff_Obj = t3lib_div::makeInstance('t3lib_diff');
  3159. $diffres = $t3lib_diff_Obj->makeDiffDisplay(
  3160. t3lib_BEfunc::getProcessedValue($table, $field, $dLVal['old'][$field], 0, 1),
  3161. t3lib_BEfunc::getProcessedValue($table, $field, $dLVal['new'][$field], 0, 1)
  3162. );
  3163. $item .= '<div class="typo3-TCEforms-diffBox">' .
  3164. '<div class="typo3-TCEforms-diffBox-header">' . htmlspecialchars($this->getLL('l_changeInOrig')) . ':</div>' .
  3165. $diffres .
  3166. '</div>';
  3167. }
  3168. }
  3169. }
  3170. return $item;
  3171. }
  3172. /**
  3173. * Renders the diff-view of vDEF fields in flexforms
  3174. *
  3175. * @param string Table name of the record being edited
  3176. * @param string Field name represented by $item
  3177. * @param array Record array of the record being edited
  3178. * @param string HTML of the form field. This is what we add the content to.
  3179. * @return string Item string returned again, possibly with the original value added to.
  3180. * @see getSingleField(), registerDefaultLanguageData()
  3181. */
  3182. function renderVDEFDiff($vArray, $vDEFkey) {
  3183. if ($GLOBALS['TYPO3_CONF_VARS']['BE']['flexFormXMLincludeDiffBase'] && isset($vArray[$vDEFkey . '.vDEFbase']) && strcmp($vArray[$vDEFkey . '.vDEFbase'], $vArray['vDEF'])) {
  3184. // Create diff-result:
  3185. $t3lib_diff_Obj = t3lib_div::makeInstance('t3lib_diff');
  3186. $diffres = $t3lib_diff_Obj->makeDiffDisplay($vArray[$vDEFkey . '.vDEFbase'], $vArray['vDEF']);
  3187. $item .= '<div class="typo3-TCEforms-diffBox">' .
  3188. '<div class="typo3-TCEforms-diffBox-header">' . htmlspecialchars($this->getLL('l_changeInOrig')) . ':</div>' .
  3189. $diffres .
  3190. '</div>';
  3191. }
  3192. return $item;
  3193. }
  3194. /************************************************************
  3195. *
  3196. * Form element helper functions
  3197. *
  3198. ************************************************************/
  3199. /**
  3200. * Prints the selector box form-field for the db/file/select elements (multiple)
  3201. *
  3202. * @param string Form element name
  3203. * @param string Mode "db", "file" (internal_type for the "group" type) OR blank (then for the "select" type)
  3204. * @param string Commalist of "allowed"
  3205. * @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.
  3206. * @param string Alternative selector box.
  3207. * @param array An array of additional parameters, eg: "size", "info", "headers" (array with "selector" and "items"), "noBrowser", "thumbnails"
  3208. * @param string On focus attribute string
  3209. * @param string $table: (optional) Table name processing for
  3210. * @param string $field: (optional) Field of table name processing for
  3211. * @param string $uid: (optional) uid of table record processing for
  3212. * @return string The form fields for the selection.
  3213. */
  3214. function dbFileIcons($fName, $mode, $allowed, $itemArray, $selector = '', $params = array(), $onFocus = '', $table = '', $field = '', $uid = '') {
  3215. $disabled = '';
  3216. if ($this->renderReadonly || $params['readOnly']) {
  3217. $disabled = ' disabled="disabled"';
  3218. }
  3219. // Sets a flag which means some JavaScript is included on the page to support this element.
  3220. $this->printNeededJS['dbFileIcons'] = 1;
  3221. // INIT
  3222. $uidList = array();
  3223. $opt = array();
  3224. $itemArrayC = 0;
  3225. // Creating <option> elements:
  3226. if (is_array($itemArray)) {
  3227. $itemArrayC = count($itemArray);
  3228. switch ($mode) {
  3229. case 'db':
  3230. foreach ($itemArray as $pp) {
  3231. $pRec = t3lib_BEfunc::getRecordWSOL($pp['table'], $pp['id']);
  3232. if (is_array($pRec)) {
  3233. $pTitle = t3lib_BEfunc::getRecordTitle($pp['table'], $pRec, FALSE, TRUE);
  3234. $pUid = $pp['table'] . '_' . $pp['id'];
  3235. $uidList[] = $pUid;
  3236. $opt[] = '<option value="' . htmlspecialchars($pUid) . '">' . htmlspecialchars($pTitle) . '</option>';
  3237. }
  3238. }
  3239. break;
  3240. case 'file_reference':
  3241. case 'file':
  3242. foreach ($itemArray as $item) {
  3243. $itemParts = explode('|', $item);
  3244. $uidList[] = $pUid = $pTitle = $itemParts[0];
  3245. $opt[] = '<option value="' . htmlspecialchars(rawurldecode($itemParts[0])) . '">' . htmlspecialchars(basename(rawurldecode($itemParts[0]))) . '</option>';
  3246. }
  3247. break;
  3248. case 'folder':
  3249. foreach ($itemArray as $pp) {
  3250. $pParts = explode('|', $pp);
  3251. $uidList[] = $pUid = $pTitle = $pParts[0];
  3252. $opt[] = '<option value="' . htmlspecialchars(rawurldecode($pParts[0])) . '">' . htmlspecialchars(rawurldecode($pParts[0])) . '</option>';
  3253. }
  3254. break;
  3255. default:
  3256. foreach ($itemArray as $pp) {
  3257. $pParts = explode('|', $pp, 2);
  3258. $uidList[] = $pUid = $pParts[0];
  3259. $pTitle = $pParts[1];
  3260. $opt[] = '<option value="' . htmlspecialchars(rawurldecode($pUid)) . '">' . htmlspecialchars(rawurldecode($pTitle)) . '</option>';
  3261. }
  3262. break;
  3263. }
  3264. }
  3265. // Create selector box of the options
  3266. $sSize = $params['autoSizeMax'] ? t3lib_div::intInRange($itemArrayC + 1, t3lib_div::intInRange($params['size'], 1), $params['autoSizeMax']) : $params['size'];
  3267. if (!$selector) {
  3268. $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>';
  3269. }
  3270. $icons = array(
  3271. 'L' => array(),
  3272. 'R' => array(),
  3273. );
  3274. if (!$params['readOnly'] && !$params['noList']) {
  3275. if (!$params['noBrowser']) {
  3276. // check against inline uniqueness
  3277. $inlineParent = $this->inline->getStructureLevel(-1);
  3278. if (is_array($inlineParent) && $inlineParent['uid']) {
  3279. if ($inlineParent['config']['foreign_table'] == $table && $inlineParent['config']['foreign_unique'] == $field) {
  3280. $objectPrefix = $this->inline->inlineNames['object'] . '[' . $table . ']';
  3281. $aOnClickInline = $objectPrefix . '|inline.checkUniqueElement|inline.setUniqueElement';
  3282. $rOnClickInline = 'inline.revertUnique(\'' . $objectPrefix . '\',null,\'' . $uid . '\');';
  3283. }
  3284. }
  3285. $aOnClick = 'setFormValueOpenBrowser(\'' . $mode . '\',\'' . ($fName . '|||' . $allowed . '|' . $aOnClickInline) . '\'); return false;';
  3286. $icons['R'][] = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">' .
  3287. t3lib_iconWorks::getSpriteIcon('actions-insert-record', array('title' => htmlspecialchars($this->getLL('l_browse_' . ($mode == 'db' ? 'db' : 'file'))))) .
  3288. '</a>';
  3289. }
  3290. if (!$params['dontShowMoveIcons']) {
  3291. if ($sSize >= 5) {
  3292. $icons['L'][] = '<a href="#" onclick="setFormValueManipulate(\'' . $fName . '\',\'Top\'); return false;">' .
  3293. t3lib_iconWorks::getSpriteIcon('actions-move-to-top', array('title' => htmlspecialchars($this->getLL('l_move_to_top')))) .
  3294. '</a>';
  3295. }
  3296. $icons['L'][] = '<a href="#" onclick="setFormValueManipulate(\'' . $fName . '\',\'Up\'); return false;">' .
  3297. t3lib_iconWorks::getSpriteIcon('actions-move-up', array('title' => htmlspecialchars($this->getLL('l_move_up')))) .
  3298. '</a>';
  3299. $icons['L'][] = '<a href="#" onclick="setFormValueManipulate(\'' . $fName . '\',\'Down\'); return false;">' .
  3300. t3lib_iconWorks::getSpriteIcon('actions-move-down', array('title' => htmlspecialchars($this->getLL('l_move_down')))) .
  3301. '</a>';
  3302. if ($sSize >= 5) {
  3303. $icons['L'][] = '<a href="#" onclick="setFormValueManipulate(\'' . $fName . '\',\'Bottom\'); return false;">' .
  3304. t3lib_iconWorks::getSpriteIcon('actions-move-to-bottom', array('title' => htmlspecialchars($this->getLL('l_move_to_bottom')))) .
  3305. '</a>';
  3306. }
  3307. }
  3308. $clipElements = $this->getClipboardElements($allowed, $mode);
  3309. if (count($clipElements)) {
  3310. $aOnClick = '';
  3311. foreach ($clipElements as $elValue) {
  3312. if ($mode == 'db') {
  3313. list($itemTable, $itemUid) = explode('|', $elValue);
  3314. $itemTitle = $GLOBALS['LANG']->JScharCode(t3lib_BEfunc::getRecordTitle($itemTable, t3lib_BEfunc::getRecordWSOL($itemTable, $itemUid)));
  3315. $elValue = $itemTable . '_' . $itemUid;
  3316. } else {
  3317. // 'file', 'file_reference' and 'folder' mode
  3318. $itemTitle = 'unescape(\'' . rawurlencode(basename($elValue)) . '\')';
  3319. }
  3320. $aOnClick .= 'setFormValueFromBrowseWin(\'' . $fName . '\',unescape(\'' . rawurlencode(str_replace('%20', ' ', $elValue)) . '\'),' . $itemTitle . ');';
  3321. }
  3322. $aOnClick .= 'return false;';
  3323. $icons['R'][] = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">' .
  3324. t3lib_iconWorks::getSpriteIcon('actions-document-paste-into', array('title' => htmlspecialchars(sprintf($this->getLL('l_clipInsert_' . ($mode == 'db' ? 'db' : 'file')), count($clipElements))))) .
  3325. '</a>';
  3326. }
  3327. $rOnClick = $rOnClickInline . 'setFormValueManipulate(\'' . $fName . '\',\'Remove\'); return false';
  3328. $icons['L'][] = '<a href="#" onclick="' . htmlspecialchars($rOnClick) . '">' .
  3329. t3lib_iconWorks::getSpriteIcon('actions-selection-delete', array('title' => htmlspecialchars($this->getLL('l_remove_selected')))) .
  3330. '</a>';
  3331. }
  3332. $imagesOnly = FALSE;
  3333. if ($params['thumbnails'] && $params['info']) {
  3334. // In case we have thumbnails, check if only images are allowed.
  3335. // In this case, render them below the field, instead of to the right
  3336. $allowedExtensionList = t3lib_div::trimExplode(' ', strtolower($params['info']), TRUE);
  3337. $imageExtensionList = t3lib_div::trimExplode(',', strtolower($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']), TRUE);
  3338. $imagesOnly = TRUE;
  3339. foreach ($allowedExtensionList as $allowedExtension) {
  3340. if (!t3lib_div::inArray($imageExtensionList, $allowedExtension)) {
  3341. $imagesOnly = FALSE;
  3342. break;
  3343. }
  3344. }
  3345. }
  3346. if ($imagesOnly) {
  3347. $rightbox = '';
  3348. $thumbnails = '<div class="imagethumbs">' . $this->wrapLabels($params['thumbnails']) . '</div>';
  3349. } else {
  3350. $rightbox = $this->wrapLabels($params['thumbnails']);
  3351. $thumbnails = '';
  3352. }
  3353. // Hook: dbFileIcons_postProcess (requested by FAL-team for use with the "fal" extension)
  3354. if (is_array ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['dbFileIcons'])) {
  3355. foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['dbFileIcons'] as $classRef) {
  3356. $hookObject = t3lib_div::getUserObj($classRef);
  3357. if (!($hookObject instanceof t3lib_TCEforms_dbFileIconsHook)) {
  3358. throw new UnexpectedValueException(
  3359. '$hookObject must implement interface t3lib_TCEforms_dbFileIconsHook',
  3360. 1290167704
  3361. );
  3362. }
  3363. $additionalParams = array(
  3364. 'mode' => $mode,
  3365. 'allowed' => $allowed,
  3366. 'itemArray' => $itemArray,
  3367. 'onFocus' => $onFocus,
  3368. 'table' => $table,
  3369. 'field' => $field,
  3370. 'uid' => $uid
  3371. );
  3372. $hookObject->dbFileIcons_postProcess($params, $selector, $thumbnails, $icons, $rightbox, $fName, $uidList, $additionalParams, $this);
  3373. }
  3374. }
  3375. $str = '<table border="0" cellpadding="0" cellspacing="0" width="1">
  3376. ' . ($params['headers'] ? '
  3377. <tr>
  3378. <td>' . $this->wrapLabels($params['headers']['selector']) . '</td>
  3379. <td></td>
  3380. <td></td>
  3381. <td>' . ($params['thumbnails'] ? $this->wrapLabels($params['headers']['items']) : '') . '</td>
  3382. </tr>' : '') .
  3383. '
  3384. <tr>
  3385. <td valign="top">' .
  3386. $selector .
  3387. $thumbnails .
  3388. ($params['noList'] ? '' : '<span class="filetypes">' . $this->wrapLabels($params['info'])) .
  3389. '</span></td>
  3390. <td valign="top" class="icons">' .
  3391. implode('<br />', $icons['L']) . '</td>
  3392. <td valign="top" class="icons">' .
  3393. implode('<br />', $icons['R']) . '</td>
  3394. <td valign="top" class="thumbnails">' .
  3395. $rightbox .
  3396. '</td>
  3397. </tr>
  3398. </table>';
  3399. // Creating the hidden field which contains the actual value as a comma list.
  3400. $str .= '<input type="hidden" name="' . $fName . '" value="' . htmlspecialchars(implode(',', $uidList)) . '" />';
  3401. return $str;
  3402. }
  3403. /**
  3404. * Returns array of elements from clipboard to insert into GROUP element box.
  3405. *
  3406. * @param string Allowed elements, Eg "pages,tt_content", "gif,jpg,jpeg,png"
  3407. * @param string Mode of relations: "db" or "file"
  3408. * @return array Array of elements in values (keys are insignificant), if none found, empty array.
  3409. */
  3410. function getClipboardElements($allowed, $mode) {
  3411. $output = array();
  3412. if (is_object($this->clipObj)) {
  3413. switch ($mode) {
  3414. case 'file_reference':
  3415. case 'file':
  3416. $elFromTable = $this->clipObj->elFromTable('_FILE');
  3417. $allowedExts = t3lib_div::trimExplode(',', $allowed, 1);
  3418. if ($allowedExts) { // If there are a set of allowed extensions, filter the content:
  3419. foreach ($elFromTable as $elValue) {
  3420. $pI = pathinfo($elValue);
  3421. $ext = strtolower($pI['extension']);
  3422. if (in_array($ext, $allowedExts)) {
  3423. $output[] = $elValue;
  3424. }
  3425. }
  3426. } else { // If all is allowed, insert all: (This does NOT respect any disallowed extensions, but those will be filtered away by the backend TCEmain)
  3427. $output = $elFromTable;
  3428. }
  3429. break;
  3430. case 'db':
  3431. $allowedTables = t3lib_div::trimExplode(',', $allowed, 1);
  3432. if (!strcmp(trim($allowedTables[0]), '*')) { // All tables allowed for relation:
  3433. $output = $this->clipObj->elFromTable('');
  3434. } else { // Only some tables, filter them:
  3435. foreach ($allowedTables as $tablename) {
  3436. $elFromTable = $this->clipObj->elFromTable($tablename);
  3437. $output = array_merge($output, $elFromTable);
  3438. }
  3439. }
  3440. $output = array_keys($output);
  3441. break;
  3442. }
  3443. }
  3444. return $output;
  3445. }
  3446. /**
  3447. * Wraps the icon of a relation item (database record or file) in a link opening the context menu for the item.
  3448. * 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.
  3449. *
  3450. * @param string The icon HTML to wrap
  3451. * @param string Table name (eg. "pages" or "tt_content") OR the absolute path to the file
  3452. * @param integer The uid of the record OR if file, just blank value.
  3453. * @return string HTML
  3454. */
  3455. function getClickMenu($str, $table, $uid = '') {
  3456. if ($this->enableClickMenu) {
  3457. $onClick = $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($str, $table, $uid, 1, '', '+copy,info,edit,view', TRUE);
  3458. return '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $str . '</a>';
  3459. }
  3460. }
  3461. /**
  3462. * Rendering wizards for form fields.
  3463. *
  3464. * @param array Array with the real item in the first value, and an alternative item in the second value.
  3465. * @param array The "wizard" key from the config array for the field (from TCA)
  3466. * @param string Table name
  3467. * @param array The record array
  3468. * @param string The field name
  3469. * @param array Additional configuration array. (passed by reference!)
  3470. * @param string The field name
  3471. * @param array Special configuration if available.
  3472. * @param boolean Whether the RTE could have been loaded.
  3473. * @return string The new item value.
  3474. */
  3475. function renderWizards($itemKinds, $wizConf, $table, $row, $field, &$PA, $itemName, $specConf, $RTE = 0) {
  3476. // Init:
  3477. $fieldChangeFunc = $PA['fieldChangeFunc'];
  3478. $item = $itemKinds[0];
  3479. $outArr = array();
  3480. $colorBoxLinks = array();
  3481. $fName = '[' . $table . '][' . $row['uid'] . '][' . $field . ']';
  3482. $md5ID = 'ID' . t3lib_div::shortmd5($itemName);
  3483. $listFlag = '_list';
  3484. $prefixOfFormElName = 'data[' . $table . '][' . $row['uid'] . '][' . $field . ']';
  3485. if (t3lib_div::isFirstPartOfStr($PA['itemFormElName'], $prefixOfFormElName)) {
  3486. $flexFormPath = str_replace('][', '/', substr($PA['itemFormElName'], strlen($prefixOfFormElName) + 1, -1));
  3487. }
  3488. // 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":
  3489. if ($PA['fieldConf']['config']['form_type'] == 'select') {
  3490. if ($PA['fieldConf']['config']['maxitems'] <= 1) { // Single select situation:
  3491. $listFlag = '';
  3492. } elseif ($PA['fieldConf']['config']['renderMode'] == 'singlebox') {
  3493. $itemName .= '[]';
  3494. $listFlag = '';
  3495. }
  3496. }
  3497. // traverse wizards:
  3498. if (is_array($wizConf) && !$this->disableWizards) {
  3499. $parametersOfWizards =& $specConf['wizards']['parameters'];
  3500. foreach ($wizConf as $wid => $wConf) {
  3501. if (substr($wid, 0, 1) != '_'
  3502. && (!$wConf['enableByTypeConfig'] || is_array($parametersOfWizards) && in_array($wid, $parametersOfWizards))
  3503. && ($RTE || !$wConf['RTEonly'])
  3504. ) {
  3505. // Title / icon:
  3506. $iTitle = htmlspecialchars($this->sL($wConf['title']));
  3507. if ($wConf['icon']) {
  3508. $icon = $this->getIconHtml($wConf['icon'], $iTitle, $iTitle);
  3509. } else {
  3510. $icon = $iTitle;
  3511. }
  3512. //
  3513. switch ((string) $wConf['type']) {
  3514. case 'userFunc':
  3515. case 'script':
  3516. case 'popup':
  3517. case 'colorbox':
  3518. if (!$wConf['notNewRecords'] || t3lib_div::testInt($row['uid'])) {
  3519. // Setting &P array contents:
  3520. $params = array();
  3521. $params['params'] = $wConf['params'];
  3522. $params['exampleImg'] = $wConf['exampleImg'];
  3523. $params['table'] = $table;
  3524. $params['uid'] = $row['uid'];
  3525. $params['pid'] = $row['pid'];
  3526. $params['field'] = $field;
  3527. $params['flexFormPath'] = $flexFormPath;
  3528. $params['md5ID'] = $md5ID;
  3529. $params['returnUrl'] = $this->thisReturnUrl();
  3530. // Resolving script filename and setting URL.
  3531. if (!strcmp(substr($wConf['script'], 0, 4), 'EXT:')) {
  3532. $wScript = t3lib_div::getFileAbsFileName($wConf['script']);
  3533. if ($wScript) {
  3534. $wScript = '../' . substr($wScript, strlen(PATH_site));
  3535. } else {
  3536. break;
  3537. }
  3538. } else {
  3539. $wScript = $wConf['script'];
  3540. }
  3541. $url = $this->backPath . $wScript . (strstr($wScript, '?') ? '' : '?');
  3542. // If there is no script and the type is "colorbox", break right away:
  3543. if ((string) $wConf['type'] == 'colorbox' && !$wConf['script']) {
  3544. break;
  3545. }
  3546. // If "script" type, create the links around the icon:
  3547. if ((string) $wConf['type'] == 'script') {
  3548. $aUrl = $url . t3lib_div::implodeArrayForUrl('', array('P' => $params));
  3549. $outArr[] = '<a href="' . htmlspecialchars($aUrl) . '" onclick="' . $this->blur() . 'return !TBE_EDITOR.isFormChanged();">' .
  3550. $icon .
  3551. '</a>';
  3552. } else {
  3553. // ... else types "popup", "colorbox" and "userFunc" will need additional parameters:
  3554. $params['formName'] = $this->formName;
  3555. $params['itemName'] = $itemName;
  3556. $params['fieldChangeFunc'] = $fieldChangeFunc;
  3557. $params['fieldChangeFuncHash'] = t3lib_div::hmac(serialize($fieldChangeFunc));
  3558. switch ((string) $wConf['type']) {
  3559. case 'popup':
  3560. case 'colorbox':
  3561. // Current form value is passed as P[currentValue]!
  3562. $addJS = $wConf['popup_onlyOpenIfSelected'] ? 'if (!TBE_EDITOR.curSelected(\'' . $itemName . $listFlag . '\')){alert(' . $GLOBALS['LANG']->JScharCode($this->getLL('m_noSelItemForEdit')) . '); return false;}' : '';
  3563. $curSelectedValues = '+\'&P[currentSelectedValues]=\'+TBE_EDITOR.curSelected(\'' . $itemName . $listFlag . '\')';
  3564. $aOnClick = $this->blur() .
  3565. $addJS .
  3566. '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'] . '\');' .
  3567. 'vHWin.focus();return false;';
  3568. // Setting "colorBoxLinks" - user LATER to wrap around the color box as well:
  3569. $colorBoxLinks = Array('<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">', '</a>');
  3570. if ((string) $wConf['type'] == 'popup') {
  3571. $outArr[] = $colorBoxLinks[0] . $icon . $colorBoxLinks[1];
  3572. }
  3573. break;
  3574. case 'userFunc':
  3575. $params['item'] = &$item; // Reference set!
  3576. $params['icon'] = $icon;
  3577. $params['iTitle'] = $iTitle;
  3578. $params['wConf'] = $wConf;
  3579. $params['row'] = $row;
  3580. $outArr[] = t3lib_div::callUserFunction($wConf['userFunc'], $params, $this);
  3581. break;
  3582. }
  3583. }
  3584. // Hide the real form element?
  3585. if (is_array($wConf['hideParent']) || $wConf['hideParent']) {
  3586. $item = $itemKinds[1]; // Setting the item to a hidden-field.
  3587. if (is_array($wConf['hideParent'])) {
  3588. $item .= $this->getSingleField_typeNone_render($wConf['hideParent'], $PA['itemFormElValue']);
  3589. }
  3590. }
  3591. }
  3592. break;
  3593. case 'select':
  3594. $fieldValue = array('config' => $wConf);
  3595. $TSconfig = $this->setTSconfig($table, $row);
  3596. $TSconfig[$field] = $TSconfig[$field]['wizards.'][$wid . '.'];
  3597. $selItems = $this->addSelectOptionsToItemArray($this->initItemArray($fieldValue), $fieldValue, $TSconfig, $field);
  3598. $opt = array();
  3599. $opt[] = '<option>' . $iTitle . '</option>';
  3600. foreach ($selItems as $p) {
  3601. $opt[] = '<option value="' . htmlspecialchars($p[1]) . '">' . htmlspecialchars($p[0]) . '</option>';
  3602. }
  3603. if ($wConf['mode'] == 'append') {
  3604. $assignValue = $this->elName($itemName) . '.value=\'\'+this.options[this.selectedIndex].value+' . $this->elName($itemName) . '.value';
  3605. } elseif ($wConf['mode'] == 'prepend') {
  3606. $assignValue = $this->elName($itemName) . '.value+=\'\'+this.options[this.selectedIndex].value';
  3607. } else {
  3608. $assignValue = $this->elName($itemName) . '.value=this.options[this.selectedIndex].value';
  3609. }
  3610. $sOnChange = $assignValue . ';this.blur();this.selectedIndex=0;' . implode('', $fieldChangeFunc);
  3611. $outArr[] = '<select id="' . uniqid('tceforms-select-') . '" class="tceforms-select tceforms-wizardselect" name="_WIZARD' . $fName . '" onchange="' . htmlspecialchars($sOnChange) . '">' . implode('', $opt) . '</select>';
  3612. break;
  3613. case 'suggest':
  3614. if (isset($PA['fieldTSConfig']['suggest.']['default.']['hide']) &&
  3615. ((bool) $PA['fieldTSConfig']['suggest.']['default.']['hide'] == TRUE)) {
  3616. break;
  3617. }
  3618. $outArr[] = $this->suggest->renderSuggestSelector($PA['itemFormElName'], $table, $field, $row, $PA);
  3619. break;
  3620. }
  3621. // Color wizard colorbox:
  3622. if ((string) $wConf['type'] == 'colorbox') {
  3623. $dim = t3lib_div::intExplode('x', $wConf['dim']);
  3624. $dX = t3lib_div::intInRange($dim[0], 1, 200, 20);
  3625. $dY = t3lib_div::intInRange($dim[1], 1, 200, 20);
  3626. $color = $PA['itemFormElValue'] ? ' bgcolor="' . htmlspecialchars($PA['itemFormElValue']) . '"' : '';
  3627. $outArr[] = '<table border="0" cellpadding="0" cellspacing="0" id="' . $md5ID . '"' . $color . ' style="' . htmlspecialchars($wConf['tableStyle']) . '">
  3628. <tr>
  3629. <td>' .
  3630. $colorBoxLinks[0] . '<img ' .
  3631. t3lib_iconWorks::skinImg($this->backPath,
  3632. (strlen(trim($color)) == 0 || strcmp(trim($color), '0') == 0) ? 'gfx/colorpicker_empty.png' : 'gfx/colorpicker.png',
  3633. 'width="' . $dX . '" height="' . $dY . '"' . t3lib_BEfunc::titleAltAttrib(trim($iTitle . ' ' . $PA['itemFormElValue'])) . ' border="0"') .
  3634. '>' . $colorBoxLinks[1] .
  3635. '</td>
  3636. </tr>
  3637. </table>';
  3638. }
  3639. }
  3640. }
  3641. // For each rendered wizard, put them together around the item.
  3642. if (count($outArr)) {
  3643. if ($wizConf['_HIDDENFIELD']) {
  3644. $item = $itemKinds[1];
  3645. }
  3646. $outStr = '';
  3647. $vAlign = $wizConf['_VALIGN'] ? ' style="vertical-align:' . $wizConf['_VALIGN'] . '"' : '';
  3648. if (count($outArr) > 1 || $wizConf['_PADDING']) {
  3649. $dist = intval($wizConf['_DISTANCE']);
  3650. if ($wizConf['_VERTICAL']) {
  3651. $dist = $dist ? '<tr><td><img src="clear.gif" width="1" height="' . $dist . '" alt="" /></td></tr>' : '';
  3652. $outStr = '<tr><td>' . implode('</td></tr>' . $dist . '<tr><td>', $outArr) . '</td></tr>';
  3653. } else {
  3654. $dist = $dist ? '<td><img src="clear.gif" height="1" width="' . $dist . '" alt="" /></td>' : '';
  3655. $outStr = '<tr><td' . $vAlign . '>' . implode('</td>' . $dist . '<td' . $vAlign . '>', $outArr) . '</td></tr>';
  3656. }
  3657. $outStr = '<table border="0" cellpadding="' . intval($wizConf['_PADDING']) . '" cellspacing="' . intval($wizConf['_PADDING']) . '">' . $outStr . '</table>';
  3658. } else {
  3659. $outStr = implode('', $outArr);
  3660. }
  3661. if (!strcmp($wizConf['_POSITION'], 'left')) {
  3662. $outStr = '<tr><td' . $vAlign . '>' . $outStr . '</td><td' . $vAlign . '>' . $item . '</td></tr>';
  3663. } elseif (!strcmp($wizConf['_POSITION'], 'top')) {
  3664. $outStr = '<tr><td>' . $outStr . '</td></tr><tr><td>' . $item . '</td></tr>';
  3665. } elseif (!strcmp($wizConf['_POSITION'], 'bottom')) {
  3666. $outStr = '<tr><td>' . $item . '</td></tr><tr><td>' . $outStr . '</td></tr>';
  3667. } else {
  3668. $outStr = '<tr><td' . $vAlign . '>' . $item . '</td><td' . $vAlign . '>' . $outStr . '</td></tr>';
  3669. }
  3670. $item = '<table border="0" cellpadding="0" cellspacing="0">' . $outStr . '</table>';
  3671. }
  3672. }
  3673. return $item;
  3674. }
  3675. /**
  3676. * Get icon (for example for selector boxes)
  3677. *
  3678. * @param string Icon reference
  3679. * @return array Array with two values; the icon file reference (relative to PATH_typo3 minus backPath), the icon file information array (getimagesize())
  3680. */
  3681. function getIcon($icon) {
  3682. if (substr($icon, 0, 4) == 'EXT:') {
  3683. $file = t3lib_div::getFileAbsFileName($icon);
  3684. if ($file) {
  3685. $file = substr($file, strlen(PATH_site));
  3686. $selIconFile = $this->backPath . '../' . $file;
  3687. $selIconInfo = @getimagesize(PATH_site . $file);
  3688. }
  3689. } elseif (substr($icon, 0, 3) == '../') {
  3690. $selIconFile = $this->backPath . t3lib_div::resolveBackPath($icon);
  3691. $selIconInfo = @getimagesize(PATH_site . t3lib_div::resolveBackPath(substr($icon, 3)));
  3692. } elseif (substr($icon, 0, 4) == 'ext/' || substr($icon, 0, 7) == 'sysext/') {
  3693. $selIconFile = $this->backPath . $icon;
  3694. $selIconInfo = @getimagesize(PATH_typo3 . $icon);
  3695. } else {
  3696. $selIconFile = t3lib_iconWorks::skinImg($this->backPath, 'gfx/' . $icon, '', 1);
  3697. $iconPath = substr($selIconFile, strlen($this->backPath));
  3698. $selIconInfo = @getimagesize(PATH_typo3 . $iconPath);
  3699. }
  3700. return array($selIconFile, $selIconInfo);
  3701. }
  3702. /**
  3703. * Renders the $icon, supports a filename for skinImg or sprite-icon-name
  3704. * @param $icon the icon passed, could be a file-reference or a sprite Icon name
  3705. * @param string $alt alt attribute of the icon returned
  3706. * @param string $title title attribute of the icon return
  3707. * @return an tag representing to show the asked icon
  3708. */
  3709. protected function getIconHtml($icon, $alt = '', $title = '') {
  3710. $iconArray = $this->getIcon($icon);
  3711. if (is_file(t3lib_div::resolveBackPath(PATH_typo3 . PATH_typo3_mod . $iconArray[0]))) {
  3712. return '<img src="' . $iconArray[0] . '" alt="' . $alt . '" ' . ($title ? 'title="' . $title . '"' : '') . ' />';
  3713. } else {
  3714. return t3lib_iconWorks::getSpriteIcon($icon, array('alt'=> $alt, 'title'=> $title));
  3715. }
  3716. }
  3717. /**
  3718. * 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)
  3719. *
  3720. * @param string Icon string for option item
  3721. * @return string Style attribute content, if any
  3722. */
  3723. function optionTagStyle($iconString) {
  3724. if ($iconString) {
  3725. list($selIconFile, $selIconInfo) = $this->getIcon($iconString);
  3726. $padLeft = $selIconInfo[0] + 4;
  3727. if ($padLeft >= 18 && $padLeft <= 24) {
  3728. $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
  3729. }
  3730. $padTop = t3lib_div::intInRange(($selIconInfo[1] - 12) / 2, 0);
  3731. $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;';
  3732. return $styleAttr;
  3733. }
  3734. }
  3735. /**
  3736. * 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).
  3737. *
  3738. * @param string Icon string for option item
  3739. * @return string Style attribute content, if any
  3740. */
  3741. function optgroupTagStyle($iconString) {
  3742. if ($iconString) {
  3743. list($selIconFile, $selIconInfo) = $this->getIcon($iconString);
  3744. $padLeft = $selIconInfo[0] + 4;
  3745. if($padLeft >= 18 && $padLeft <= 24) {
  3746. // In order to get the same padding for all option tags even if icon sizes differ a little,
  3747. // set it to 22, if it was between 18 and 24 pixels.
  3748. $padLeft = 22;
  3749. }
  3750. $padTop = t3lib_div::intInRange(($selIconInfo[1] - 12) / 2, 0);
  3751. return 'background: #ffffff url(' . $selIconFile . ') 0 0 no-repeat; padding-top: ' . $padTop . 'px; padding-left: ' . $padLeft . 'px;';
  3752. }
  3753. }
  3754. /**
  3755. * Extracting values from a value/label list (as made by transferData class)
  3756. *
  3757. * @param string Value string where values are comma separated, intermixed with labels and rawurlencoded (this is what is delivered to TCEforms normally!)
  3758. * @param array Values in an array
  3759. * @return array Input string exploded with comma and for each value only the label part is set in the array. Keys are numeric
  3760. */
  3761. function extractValuesOnlyFromValueLabelList($itemFormElValue) {
  3762. // Get values of selected items:
  3763. $itemArray = t3lib_div::trimExplode(',', $itemFormElValue, 1);
  3764. foreach ($itemArray as $tk => $tv) {
  3765. $tvP = explode('|', $tv, 2);
  3766. $tvP[0] = rawurldecode($tvP[0]);
  3767. $itemArray[$tk] = $tvP[0];
  3768. }
  3769. return $itemArray;
  3770. }
  3771. /**
  3772. * Wraps a string with a link to the palette.
  3773. *
  3774. * @param string The string to wrap in an A-tag
  3775. * @param string The table name for which to open the palette.
  3776. * @param array The palette pointer.
  3777. * @param integer The record array
  3778. */
  3779. function wrapOpenPalette($header, $table, $row, $palette, $retFunc) {
  3780. $id = 'TCEFORMS_' . $table . '_' . $palette . '_' . $row['uid'];
  3781. $res = '<a href="#" onclick="TBE_EDITOR.toggle_display_states(\'' . $id . '\',\'block\',\'none\'); return false;" >' . $header . '</a>';
  3782. return array($res, '');
  3783. }
  3784. /**
  3785. * Add the id and the style property to the field palette
  3786. *
  3787. * @param string Palette Code
  3788. * @param string The table name for which to open the palette.
  3789. * @param string Palette ID
  3790. * @param string The record array
  3791. * @return boolean is collapsed
  3792. */
  3793. function wrapPaletteField($code, $table, $row, $palette, $collapsed) {
  3794. $display = $collapsed ? 'none' : 'block';
  3795. $id = 'TCEFORMS_' . $table . '_' . $palette . '_' . $row['uid'];
  3796. $code = '<div id="' . $id . '" style="display:' . $display . ';" >' . $code . '</div>';
  3797. return $code;
  3798. }
  3799. /**
  3800. * Creates checkbox parameters
  3801. *
  3802. * @param string Form element name
  3803. * @param integer The value of the checkbox (representing checkboxes with the bits)
  3804. * @param integer Checkbox # (0-9?)
  3805. * @param integer Total number of checkboxes in the array.
  3806. * @param string Additional JavaScript for the onclick handler.
  3807. * @return string The onclick attribute + possibly the checked-option set.
  3808. */
  3809. function checkBoxParams($itemName, $thisValue, $c, $iCount, $addFunc = '') {
  3810. $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)) . ');' .
  3811. $addFunc;
  3812. $str = ' onclick="' . htmlspecialchars($onClick) . '"' .
  3813. (($thisValue & pow(2, $c)) ? ' checked="checked"' : '');
  3814. return $str;
  3815. }
  3816. /**
  3817. * Returns element reference for form element name
  3818. *
  3819. * @param string Form element name
  3820. * @return string Form element reference (JS)
  3821. */
  3822. function elName($itemName) {
  3823. return 'document.' . $this->formName . "['" . $itemName . "']";
  3824. }
  3825. /**
  3826. * Returns 'this.blur();' string, if supported.
  3827. *
  3828. * @return string If the current browser supports styles, the string 'this.blur();' is returned.
  3829. */
  3830. function blur() {
  3831. return $GLOBALS['CLIENT']['FORMSTYLE'] ? 'this.blur();' : '';
  3832. }
  3833. /**
  3834. * Returns the "returnUrl" of the form. Can be set externally or will be taken from "t3lib_div::linkThisScript()"
  3835. *
  3836. * @return string Return URL of current script
  3837. */
  3838. function thisReturnUrl() {
  3839. return $this->returnUrl ? $this->returnUrl : t3lib_div::linkThisScript();
  3840. }
  3841. /**
  3842. * Returns the form field for a single HIDDEN field.
  3843. * (Not used anywhere...?)
  3844. *
  3845. * @param string Table name
  3846. * @param string Field name
  3847. * @param array The row
  3848. * @return string The hidden-field <input> tag.
  3849. */
  3850. function getSingleHiddenField($table, $field, $row) {
  3851. global $TCA;
  3852. $out = '';
  3853. t3lib_div::loadTCA($table);
  3854. if ($TCA[$table]['columns'][$field]) {
  3855. $uid = $row['uid'];
  3856. $itemName = $this->prependFormFieldNames . '[' . $table . '][' . $uid . '][' . $field . ']';
  3857. $itemValue = $row[$field];
  3858. $item .= '<input type="hidden" name="' . $itemName . '" value="' . htmlspecialchars($itemValue) . '" />';
  3859. $out = $item;
  3860. }
  3861. return $out;
  3862. }
  3863. /**
  3864. * Returns parameters to set the width for a <input>/<textarea>-element
  3865. *
  3866. * @param integer The abstract size value (1-48)
  3867. * @param boolean If this is for a text area.
  3868. * @return string Either a "style" attribute string or "cols"/"size" attribute string.
  3869. */
  3870. function formWidth($size = 48, $textarea = 0) {
  3871. $widthAndStyleAttributes = '';
  3872. $fieldWidthAndStyle = $this->formWidthAsArray($size, $textarea);
  3873. if (!$GLOBALS['CLIENT']['FORMSTYLE']) {
  3874. // If not setting the width by style-attribute
  3875. $widthAndStyleAttributes = ' ' . $fieldWidthAndStyle['width'];
  3876. } else {
  3877. // Setting width by style-attribute. 'cols' MUST be avoided with NN6+
  3878. $widthAndStyleAttributes = ' style="' . htmlspecialchars($fieldWidthAndStyle['style']) . '"';
  3879. if ($fieldWidthAndStyle['class']) {
  3880. $widthAndStyleAttributes .= ' class="' . htmlspecialchars($fieldWidthAndStyle['class']) . '"';
  3881. }
  3882. }
  3883. return $widthAndStyleAttributes;
  3884. }
  3885. /**
  3886. * Returns parameters to set the width for a <input>/<textarea>-element
  3887. *
  3888. * @param integer The abstract size value (1-48)
  3889. * @param boolean If set, calculates sizes for a text area.
  3890. * @return array An array containing style, class, and width attributes.
  3891. */
  3892. protected function formWidthAsArray($size = 48, $textarea = FALSE) {
  3893. $fieldWidthAndStyle = array('style' => '', 'class' => '', 'width' => '');
  3894. if ($this->docLarge) {
  3895. $size = round($size * $this->form_largeComp);
  3896. }
  3897. $widthAttribute = $textarea ? 'cols' : 'size';
  3898. if (!$GLOBALS['CLIENT']['FORMSTYLE']) {
  3899. // If not setting the width by style-attribute
  3900. $fieldWidthAndStyle['width'] = $widthAttribute . '="' . $size . '"';
  3901. } else {
  3902. // Setting width by style-attribute. 'cols' MUST be avoided with NN6+
  3903. $widthInPixels = ceil($size * $this->form_rowsToStylewidth);
  3904. $fieldWidthAndStyle['style'] = 'width: ' . $widthInPixels . 'px; '
  3905. . $this->defStyle
  3906. . $this->formElStyle($textarea ? 'text' : 'input');
  3907. $fieldWidthAndStyle['class'] = $this->formElClass($textarea ? 'text' : 'input');
  3908. }
  3909. return $fieldWidthAndStyle;
  3910. }
  3911. /**
  3912. * Returns parameters to set with for a textarea field
  3913. *
  3914. * @param integer The abstract width (1-48)
  3915. * @param string Empty or "off" (text wrapping in the field or not)
  3916. * @return string The "cols" attribute string (or style from formWidth())
  3917. * @see formWidth()
  3918. */
  3919. function formWidthText($size = 48, $wrap = '') {
  3920. $wTags = $this->formWidth($size, 1);
  3921. // 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...
  3922. if (strtolower(trim($wrap)) != 'off' && $GLOBALS['CLIENT']['BROWSER'] == 'net' && $GLOBALS['CLIENT']['VERSION'] >= 5) {
  3923. $wTags .= ' cols="' . $size . '"';
  3924. }
  3925. return $wTags;
  3926. }
  3927. /**
  3928. * Get style CSS values for the current field type.
  3929. *
  3930. * @param string Field type (eg. "check", "radio", "select")
  3931. * @return string CSS attributes
  3932. * @see formElStyleClassValue()
  3933. */
  3934. function formElStyle($type) {
  3935. return $this->formElStyleClassValue($type);
  3936. }
  3937. /**
  3938. * Get class attribute value for the current field type.
  3939. *
  3940. * @param string Field type (eg. "check", "radio", "select")
  3941. * @return string CSS attributes
  3942. * @see formElStyleClassValue()
  3943. */
  3944. function formElClass($type) {
  3945. return $this->formElStyleClassValue($type, TRUE);
  3946. }
  3947. /**
  3948. * Get style CSS values for the current field type.
  3949. *
  3950. * @param string Field type (eg. "check", "radio", "select")
  3951. * @param boolean If set, will return value only if prefixed with CLASS, otherwise must not be prefixed "CLASS"
  3952. * @return string CSS attributes
  3953. */
  3954. function formElStyleClassValue($type, $class = FALSE) {
  3955. // Get value according to field:
  3956. if (isset($this->fieldStyle[$type])) {
  3957. $style = trim($this->fieldStyle[$type]);
  3958. } else {
  3959. $style = trim($this->fieldStyle['all']);
  3960. }
  3961. // Check class prefixed:
  3962. if (substr($style, 0, 6) == 'CLASS:') {
  3963. $out = $class ? trim(substr($style, 6)) : '';
  3964. } else {
  3965. $out = !$class ? $style : '';
  3966. }
  3967. return $out;
  3968. }
  3969. /**
  3970. * Return default "style" / "class" attribute line.
  3971. *
  3972. * @param string Field type (eg. "check", "radio", "select")
  3973. * @param string Additional class(es) to be added
  3974. * @return string CSS attributes
  3975. */
  3976. function insertDefStyle($type, $additionalClass = '') {
  3977. $out = '';
  3978. $style = trim($this->defStyle . $this->formElStyle($type));
  3979. $out .= $style ? ' style="' . htmlspecialchars($style) . '"' : '';
  3980. $class = $this->formElClass($type);
  3981. $classAttributeValue = join(' ', array_filter(array($class, $additionalClass)));
  3982. $out .= $classAttributeValue ? ' class="' . htmlspecialchars($classAttributeValue) . '"' : '';
  3983. return $out;
  3984. }
  3985. /**
  3986. * Create dynamic tab menu
  3987. *
  3988. * @param array Parts for the tab menu, fed to template::getDynTabMenu()
  3989. * @param string ID string for the tab menu
  3990. * @param integer If set to '1' empty tabs will be removed, If set to '2' empty tabs will be disabled
  3991. * @return string HTML for the menu
  3992. */
  3993. function getDynTabMenu($parts, $idString, $dividersToTabsBehaviour = 1) {
  3994. if (is_object($GLOBALS['TBE_TEMPLATE'])) {
  3995. $GLOBALS['TBE_TEMPLATE']->backPath = $this->backPath;
  3996. return $GLOBALS['TBE_TEMPLATE']->getDynTabMenu($parts, $idString, 0, FALSE, 0, 1, FALSE, 1, $dividersToTabsBehaviour);
  3997. } else {
  3998. $output = '';
  3999. foreach ($parts as $singlePad) {
  4000. $output .= '
  4001. <h3>' . htmlspecialchars($singlePad['label']) . '</h3>
  4002. ' . ($singlePad['description'] ? '<p class="c-descr">' . nl2br(htmlspecialchars($singlePad['description'])) . '</p>' : '') . '
  4003. ' . $singlePad['content'];
  4004. }
  4005. return '<div class="typo3-dyntabmenu-divs">' . $output . '</div>';
  4006. }
  4007. }
  4008. /************************************************************
  4009. *
  4010. * Item-array manipulation functions (check/select/radio)
  4011. *
  4012. ************************************************************/
  4013. /**
  4014. * Initialize item array (for checkbox, selectorbox, radio buttons)
  4015. * Will resolve the label value.
  4016. *
  4017. * @param array The "columns" array for the field (from TCA)
  4018. * @return array An array of arrays with three elements; label, value, icon
  4019. */
  4020. function initItemArray($fieldValue) {
  4021. $items = array();
  4022. if (is_array($fieldValue['config']['items'])) {
  4023. foreach ($fieldValue['config']['items'] as $itemValue) {
  4024. $items[] = array($this->sL($itemValue[0]), $itemValue[1], $itemValue[2]);
  4025. }
  4026. }
  4027. return $items;
  4028. }
  4029. /**
  4030. * Merges items into an item-array
  4031. *
  4032. * @param array The existing item array
  4033. * @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.
  4034. * @return array The updated $item array
  4035. */
  4036. function addItems($items, $iArray) {
  4037. global $TCA;
  4038. if (is_array($iArray)) {
  4039. foreach ($iArray as $value => $label) {
  4040. $items[] = array($this->sl($label), $value);
  4041. }
  4042. }
  4043. return $items;
  4044. }
  4045. /**
  4046. * Perform user processing of the items arrays of checkboxes, selectorboxes and radio buttons.
  4047. *
  4048. * @param array The array of items (label,value,icon)
  4049. * @param array The "itemsProcFunc." from fieldTSconfig of the field.
  4050. * @param array The config array for the field.
  4051. * @param string Table name
  4052. * @param array Record row
  4053. * @param string Field name
  4054. * @return array The modified $items array
  4055. */
  4056. function procItems($items, $iArray, $config, $table, $row, $field) {
  4057. global $TCA;
  4058. $params = array();
  4059. $params['items'] = &$items;
  4060. $params['config'] = $config;
  4061. $params['TSconfig'] = $iArray;
  4062. $params['table'] = $table;
  4063. $params['row'] = $row;
  4064. $params['field'] = $field;
  4065. t3lib_div::callUserFunction($config['itemsProcFunc'], $params, $this);
  4066. return $items;
  4067. }
  4068. /**
  4069. * Add selector box items of more exotic kinds.
  4070. *
  4071. * @param array The array of items (label,value,icon)
  4072. * @param array The "columns" array for the field (from TCA)
  4073. * @param array TSconfig for the table/row
  4074. * @param string The fieldname
  4075. * @return array The $items array modified.
  4076. */
  4077. function addSelectOptionsToItemArray($items, $fieldValue, $TSconfig, $field) {
  4078. global $TCA;
  4079. // Values from foreign tables:
  4080. if ($fieldValue['config']['foreign_table']) {
  4081. $items = $this->foreignTable($items, $fieldValue, $TSconfig, $field);
  4082. if ($fieldValue['config']['neg_foreign_table']) {
  4083. $items = $this->foreignTable($items, $fieldValue, $TSconfig, $field, 1);
  4084. }
  4085. }
  4086. // Values from a file folder:
  4087. if ($fieldValue['config']['fileFolder']) {
  4088. $fileFolder = t3lib_div::getFileAbsFileName($fieldValue['config']['fileFolder']);
  4089. if (@is_dir($fileFolder)) {
  4090. // Configurations:
  4091. $extList = $fieldValue['config']['fileFolder_extList'];
  4092. $recursivityLevels = isset($fieldValue['config']['fileFolder_recursions']) ? t3lib_div::intInRange($fieldValue['config']['fileFolder_recursions'], 0, 99) : 99;
  4093. // Get files:
  4094. $fileFolder = rtrim($fileFolder, '/') . '/';
  4095. $fileArr = t3lib_div::getAllFilesAndFoldersInPath(array(), $fileFolder, $extList, 0, $recursivityLevels);
  4096. $fileArr = t3lib_div::removePrefixPathFromList($fileArr, $fileFolder);
  4097. foreach ($fileArr as $fileRef) {
  4098. $fI = pathinfo($fileRef);
  4099. $icon = t3lib_div::inList('gif,png,jpeg,jpg', strtolower($fI['extension'])) ? '../' . substr($fileFolder, strlen(PATH_site)) . $fileRef : '';
  4100. $items[] = array(
  4101. $fileRef,
  4102. $fileRef,
  4103. $icon
  4104. );
  4105. }
  4106. }
  4107. }
  4108. // If 'special' is configured:
  4109. if ($fieldValue['config']['special']) {
  4110. switch ($fieldValue['config']['special']) {
  4111. case 'tables':
  4112. $temp_tc = array_keys($TCA);
  4113. $descr = '';
  4114. foreach ($temp_tc as $theTableNames) {
  4115. if (!$TCA[$theTableNames]['ctrl']['adminOnly']) {
  4116. // Icon:
  4117. $icon = t3lib_iconWorks::mapRecordTypeToSpriteIconName($theTableNames, array());
  4118. // Add help text
  4119. $helpText = array();
  4120. $GLOBALS['LANG']->loadSingleTableDescription($theTableNames);
  4121. $helpTextArray = $GLOBALS['TCA_DESCR'][$theTableNames]['columns'][''];
  4122. if (!empty($helpTextArray['description'])) {
  4123. $helpText['description'] = $helpTextArray['description'];
  4124. }
  4125. // Item configuration:
  4126. $items[] = array(
  4127. $this->sL($TCA[$theTableNames]['ctrl']['title']),
  4128. $theTableNames,
  4129. $icon,
  4130. $helpText
  4131. );
  4132. }
  4133. }
  4134. break;
  4135. case 'pagetypes':
  4136. $theTypes = $TCA['pages']['columns']['doktype']['config']['items'];
  4137. foreach ($theTypes as $theTypeArrays) {
  4138. // Icon:
  4139. $icon = t3lib_iconWorks::mapRecordTypeToSpriteIconName('pages', array('doktype' => $theTypeArrays[1]));
  4140. // Item configuration:
  4141. $items[] = array(
  4142. $this->sL($theTypeArrays[0]),
  4143. $theTypeArrays[1],
  4144. $icon
  4145. );
  4146. }
  4147. break;
  4148. case 'exclude':
  4149. $theTypes = t3lib_BEfunc::getExcludeFields();
  4150. $descr = '';
  4151. foreach ($theTypes as $theTypeArrays) {
  4152. list($theTable, $theField) = explode(':', $theTypeArrays[1]);
  4153. // Add help text
  4154. $helpText = array();
  4155. $GLOBALS['LANG']->loadSingleTableDescription($theTable);
  4156. $helpTextArray = $GLOBALS['TCA_DESCR'][$theTable]['columns'][$theField];
  4157. if (!empty($helpTextArray['description'])) {
  4158. $helpText['description'] = $helpTextArray['description'];
  4159. }
  4160. // Item configuration:
  4161. $items[] = array(
  4162. rtrim($theTypeArrays[0], ':'),
  4163. $theTypeArrays[1],
  4164. 'empty-empty',
  4165. $helpText
  4166. );
  4167. }
  4168. break;
  4169. case 'explicitValues':
  4170. $theTypes = t3lib_BEfunc::getExplicitAuthFieldValues();
  4171. // Icons:
  4172. $icons = array(
  4173. 'ALLOW' => 'status-status-permission-granted',
  4174. 'DENY' => 'status-status-permission-denied',
  4175. );
  4176. // Traverse types:
  4177. foreach ($theTypes as $tableFieldKey => $theTypeArrays) {
  4178. if (is_array($theTypeArrays['items'])) {
  4179. // Add header:
  4180. $items[] = array(
  4181. $theTypeArrays['tableFieldLabel'],
  4182. '--div--',
  4183. );
  4184. // Traverse options for this field:
  4185. foreach ($theTypeArrays['items'] as $itemValue => $itemContent) {
  4186. // Add item to be selected:
  4187. $items[] = array(
  4188. '[' . $itemContent[2] . '] ' . $itemContent[1],
  4189. $tableFieldKey . ':' . preg_replace('/[:|,]/', '', $itemValue) . ':' . $itemContent[0],
  4190. $icons[$itemContent[0]]
  4191. );
  4192. }
  4193. }
  4194. }
  4195. break;
  4196. case 'languages':
  4197. $items = array_merge($items, t3lib_BEfunc::getSystemLanguages());
  4198. break;
  4199. case 'custom':
  4200. // Initialize:
  4201. $customOptions = $GLOBALS['TYPO3_CONF_VARS']['BE']['customPermOptions'];
  4202. if (is_array($customOptions)) {
  4203. foreach ($customOptions as $coKey => $coValue) {
  4204. if (is_array($coValue['items'])) {
  4205. // Add header:
  4206. $items[] = array(
  4207. $GLOBALS['LANG']->sl($coValue['header']),
  4208. '--div--',
  4209. );
  4210. // Traverse items:
  4211. foreach ($coValue['items'] as $itemKey => $itemCfg) {
  4212. // Icon:
  4213. if ($itemCfg[1]) {
  4214. list($icon) = $this->getIcon($itemCfg[1]);
  4215. } else {
  4216. $icon = 'empty-empty';
  4217. }
  4218. // Add help text
  4219. $helpText = array();
  4220. if (!empty($itemCfg[2])) {
  4221. $helpText['description'] = $GLOBALS['LANG']->sl($itemCfg[2]);
  4222. }
  4223. // Add item to be selected:
  4224. $items[] = array(
  4225. $GLOBALS['LANG']->sl($itemCfg[0]),
  4226. $coKey . ':' . preg_replace('/[:|,]/', '', $itemKey),
  4227. $icon,
  4228. $helpText,
  4229. );
  4230. }
  4231. }
  4232. }
  4233. }
  4234. break;
  4235. case 'modListGroup':
  4236. case 'modListUser':
  4237. $loadModules = t3lib_div::makeInstance('t3lib_loadModules');
  4238. $loadModules->load($GLOBALS['TBE_MODULES']);
  4239. $modList = $fieldValue['config']['special'] == 'modListUser' ? $loadModules->modListUser : $loadModules->modListGroup;
  4240. if (is_array($modList)) {
  4241. $descr = '';
  4242. foreach ($modList as $theMod) {
  4243. // Icon:
  4244. $icon = $GLOBALS['LANG']->moduleLabels['tabs_images'][$theMod . '_tab'];
  4245. if ($icon) {
  4246. $icon = '../' . substr($icon, strlen(PATH_site));
  4247. }
  4248. // Add help text
  4249. $helpText = array(
  4250. 'title' => $GLOBALS['LANG']->moduleLabels['labels'][$theMod . '_tablabel'],
  4251. 'description' => $GLOBALS['LANG']->moduleLabels['labels'][$theMod . '_tabdescr']
  4252. );
  4253. // Item configuration:
  4254. $items[] = array(
  4255. $this->addSelectOptionsToItemArray_makeModuleData($theMod),
  4256. $theMod,
  4257. $icon,
  4258. $helpText
  4259. );
  4260. }
  4261. }
  4262. break;
  4263. }
  4264. }
  4265. // Return the items:
  4266. return $items;
  4267. }
  4268. /**
  4269. * Creates value/label pair for a backend module (main and sub)
  4270. *
  4271. * @param string The module key
  4272. * @return string The rawurlencoded 2-part string to transfer to interface
  4273. * @access private
  4274. * @see addSelectOptionsToItemArray()
  4275. */
  4276. function addSelectOptionsToItemArray_makeModuleData($value) {
  4277. $label = '';
  4278. // Add label for main module:
  4279. $pp = explode('_', $value);
  4280. if (count($pp) > 1) {
  4281. $label .= $GLOBALS['LANG']->moduleLabels['tabs'][$pp[0] . '_tab'] . '>';
  4282. }
  4283. // Add modules own label now:
  4284. $label .= $GLOBALS['LANG']->moduleLabels['tabs'][$value . '_tab'];
  4285. return $label;
  4286. }
  4287. /**
  4288. * Adds records from a foreign table (for selector boxes)
  4289. *
  4290. * @param array The array of items (label,value,icon)
  4291. * @param array The 'columns' array for the field (from TCA)
  4292. * @param array TSconfig for the table/row
  4293. * @param string The fieldname
  4294. * @param boolean If set, then we are fetching the 'neg_' foreign tables.
  4295. * @return array The $items array modified.
  4296. * @see addSelectOptionsToItemArray(), t3lib_BEfunc::exec_foreign_table_where_query()
  4297. */
  4298. function foreignTable($items, $fieldValue, $TSconfig, $field, $pFFlag = 0) {
  4299. global $TCA;
  4300. // Init:
  4301. $pF = $pFFlag ? 'neg_' : '';
  4302. $f_table = $fieldValue['config'][$pF . 'foreign_table'];
  4303. $uidPre = $pFFlag ? '-' : '';
  4304. // Get query:
  4305. $res = t3lib_BEfunc::exec_foreign_table_where_query($fieldValue, $field, $TSconfig, $pF);
  4306. // Perform lookup
  4307. if ($GLOBALS['TYPO3_DB']->sql_error()) {
  4308. echo($GLOBALS['TYPO3_DB']->sql_error() . "\n\nThis may indicate a table defined in tables.php is not existing in the database!");
  4309. return array();
  4310. }
  4311. // Get label prefix.
  4312. $lPrefix = $this->sL($fieldValue['config'][$pF . 'foreign_table_prefix']);
  4313. // Get icon field + path if any:
  4314. $iField = $TCA[$f_table]['ctrl']['selicon_field'];
  4315. $iPath = trim($TCA[$f_table]['ctrl']['selicon_field_path']);
  4316. // Traverse the selected rows to add them:
  4317. while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
  4318. t3lib_BEfunc::workspaceOL($f_table, $row);
  4319. if (is_array($row)) {
  4320. // Prepare the icon if available:
  4321. if ($iField && $iPath && $row[$iField]) {
  4322. $iParts = t3lib_div::trimExplode(',', $row[$iField], 1);
  4323. $icon = '../' . $iPath . '/' . trim($iParts[0]);
  4324. } elseif (t3lib_div::inList('singlebox,checkbox', $fieldValue['config']['renderMode'])) {
  4325. $icon = t3lib_iconWorks::mapRecordTypeToSpriteIconName($f_table, $row);
  4326. } else {
  4327. $icon = 'empty-empty';
  4328. }
  4329. // Add the item:
  4330. $items[] = array(
  4331. $lPrefix . htmlspecialchars(t3lib_BEfunc::getRecordTitle($f_table, $row)),
  4332. $uidPre . $row['uid'],
  4333. $icon
  4334. );
  4335. }
  4336. }
  4337. return $items;
  4338. }
  4339. /********************************************
  4340. *
  4341. * Template functions
  4342. *
  4343. ********************************************/
  4344. /**
  4345. * Sets the design to the backend design.
  4346. * Backend
  4347. *
  4348. * @return void
  4349. */
  4350. function setNewBEDesign() {
  4351. $template = t3lib_div::getURL(PATH_typo3 . $this->templateFile);
  4352. // Wrapping all table rows for a particular record being edited:
  4353. $this->totalWrap = t3lib_parsehtml::getSubpart($template, '###TOTALWRAP###');
  4354. // Wrapping a single field:
  4355. $this->fieldTemplate = t3lib_parsehtml::getSubpart($template, '###FIELDTEMPLATE###');
  4356. $this->palFieldTemplate = t3lib_parsehtml::getSubpart($template, '###PALETTE_FIELDTEMPLATE###');
  4357. $this->palFieldTemplateHeader = t3lib_parsehtml::getSubpart($template, '###PALETTE_FIELDTEMPLATE_HEADER###');
  4358. $this->sectionWrap = t3lib_parsehtml::getSubpart($template, '###SECTION_WRAP###');
  4359. }
  4360. /**
  4361. * This inserts the content of $inArr into the field-template
  4362. *
  4363. * @param array Array with key/value pairs to insert in the template.
  4364. * @param string Alternative template to use instead of the default.
  4365. * @return string
  4366. */
  4367. function intoTemplate($inArr, $altTemplate = '') {
  4368. // Put into template_
  4369. $fieldTemplateParts = explode('###FIELD_', $this->rplColorScheme($altTemplate ? $altTemplate : $this->fieldTemplate));
  4370. $out = current($fieldTemplateParts);
  4371. foreach ($fieldTemplateParts as $part) {
  4372. list($key, $val) = explode('###', $part, 2);
  4373. $out .= $inArr[$key];
  4374. $out .= $val;
  4375. }
  4376. return $out;
  4377. }
  4378. /**
  4379. * Overwrite this function in own extended class to add own markers for output
  4380. *
  4381. * @param array Array with key/value pairs to insert in the template.
  4382. * @param string The table name of the record
  4383. * @param string The field name which this element is supposed to edit
  4384. * @param array The record data array where the value(s) for the field can be found
  4385. * @param array An array with additional configuration options.
  4386. * @return array marker array for template output
  4387. * @see function intoTemplate()
  4388. */
  4389. function addUserTemplateMarkers($marker, $table, $field, $row, &$PA) {
  4390. return $marker;
  4391. }
  4392. /**
  4393. * Wrapping labels
  4394. * Currently not implemented - just returns input value.
  4395. *
  4396. * @param string Input string.
  4397. * @return string Output string.
  4398. */
  4399. function wrapLabels($str) {
  4400. return $str;
  4401. }
  4402. /**
  4403. * Wraps all the table rows into a single table.
  4404. * Used externally from scripts like alt_doc.php and db_layout.php (which uses TCEforms...)
  4405. *
  4406. * @param string Code to output between table-parts; table rows
  4407. * @param array The record
  4408. * @param string The table name
  4409. * @return string
  4410. */
  4411. function wrapTotal($c, $rec, $table) {
  4412. $parts = $this->replaceTableWrap(explode('|', $this->totalWrap, 2), $rec, $table);
  4413. return $parts[0] . $c . $parts[1] . implode('', $this->hiddenFieldAccum);
  4414. }
  4415. /**
  4416. * Generates a token and returns an input field with it
  4417. *
  4418. * @param string $formName Context of the token
  4419. * @param string $tokenName The name of the token GET/POST variable
  4420. * @return string a complete input field
  4421. */
  4422. public static function getHiddenTokenField($formName = 'securityToken', $tokenName = 'formToken') {
  4423. $formprotection = t3lib_formprotection_Factory::get();
  4424. return '<input type="hidden" name="' .$tokenName . '" value="' . $formprotection->generateToken($formName) . '-' . $formName . '" />';
  4425. }
  4426. /**
  4427. * This replaces markers in the total wrap
  4428. *
  4429. * @param array An array of template parts containing some markers.
  4430. * @param array The record
  4431. * @param string The table name
  4432. * @return string
  4433. */
  4434. function replaceTableWrap($arr, $rec, $table) {
  4435. global $TCA;
  4436. // Make "new"-label
  4437. if (strstr($rec['uid'], 'NEW')) {
  4438. $newLabel = ' <span class="typo3-TCEforms-newToken">' .
  4439. $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.new', 1) .
  4440. '</span>';
  4441. // Kasper: Should not be used here because NEW records are not offline workspace versions...
  4442. #t3lib_BEfunc::fixVersioningPid($table,$rec);
  4443. $truePid = t3lib_BEfunc::getTSconfig_pidValue($table, $rec['uid'], $rec['pid']);
  4444. $prec = t3lib_BEfunc::getRecordWSOL('pages', $truePid, 'title');
  4445. $pageTitle = t3lib_BEfunc::getRecordTitle('pages', $prec, TRUE, FALSE);
  4446. $rLabel = '<em>[PID: ' . $truePid . '] ' . $pageTitle . '</em>';
  4447. // Fetch translated title of the table
  4448. $tableTitle = $GLOBALS['LANG']->sL($GLOBALS['TCA'][$table]['ctrl']['title']);
  4449. if ($table === 'pages') {
  4450. $label = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.createNewPage', TRUE);
  4451. $pageTitle = sprintf($label, $tableTitle);
  4452. } else {
  4453. $label = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.createNewRecord', TRUE);
  4454. if ($rec['pid'] == 0) {
  4455. $label = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.createNewRecordRootLevel', TRUE);
  4456. }
  4457. $pageTitle = sprintf($label, $tableTitle, $pageTitle);
  4458. }
  4459. } else {
  4460. $newLabel = ' <span class="typo3-TCEforms-recUid">[' . $rec['uid'] . ']</span>';
  4461. $rLabel = t3lib_BEfunc::getRecordTitle($table, $rec, TRUE, FALSE);
  4462. $prec = t3lib_BEfunc::getRecordWSOL('pages', $rec['pid'], 'uid,title');
  4463. // Fetch translated title of the table
  4464. $tableTitle = $GLOBALS['LANG']->sL($GLOBALS['TCA'][$table]['ctrl']['title']);
  4465. if ($table === 'pages') {
  4466. $label = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.editPage', TRUE);
  4467. // Just take the record title and prepend an edit label.
  4468. $pageTitle = sprintf($label, $tableTitle, $rLabel);
  4469. } else {
  4470. $label = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.editRecord', TRUE);
  4471. $pageTitle = t3lib_BEfunc::getRecordTitle('pages', $prec, TRUE, FALSE);
  4472. if ($rLabel === t3lib_BEfunc::getNoRecordTitle(TRUE)) {
  4473. $label = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.editRecordNoTitle', TRUE);
  4474. }
  4475. if ($rec['pid'] == 0) {
  4476. $label = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.editRecordRootLevel', TRUE);
  4477. }
  4478. if ($rLabel !== t3lib_BEfunc::getNoRecordTitle(TRUE)) {
  4479. // Just take the record title and prepend an edit label.
  4480. $pageTitle = sprintf($label, $tableTitle, $rLabel, $pageTitle);
  4481. } else {
  4482. // Leave out the record title since it is not set.
  4483. $pageTitle = sprintf($label, $tableTitle, $pageTitle);
  4484. }
  4485. }
  4486. }
  4487. foreach ($arr as $k => $v) {
  4488. // Make substitutions:
  4489. $arr[$k] = str_replace('###PAGE_TITLE###', $pageTitle, $arr[$k]);
  4490. $arr[$k] = str_replace('###ID_NEW_INDICATOR###', $newLabel, $arr[$k]);
  4491. $arr[$k] = str_replace('###RECORD_LABEL###', $rLabel, $arr[$k]);
  4492. $arr[$k] = str_replace('###TABLE_TITLE###', htmlspecialchars($this->sL($TCA[$table]['ctrl']['title'])), $arr[$k]);
  4493. $arr[$k] = str_replace('###RECORD_ICON###', t3lib_iconWorks::getSpriteIconForRecord($table, $rec, array('title' => $this->getRecordPath($table, $rec))), $arr[$k]);
  4494. }
  4495. return $arr;
  4496. }
  4497. /**
  4498. * Wraps an element in the $out_array with the template row for a "section" ($this->sectionWrap)
  4499. *
  4500. * @param array The array with form elements stored in (passed by reference and changed!)
  4501. * @param integer The pointer to the entry in the $out_array (passed by reference and incremented!)
  4502. * @return void
  4503. */
  4504. function wrapBorder(&$out_array, &$out_pointer) {
  4505. if ($this->sectionWrap && $out_array[$out_pointer]) {
  4506. $tableAttribs = '';
  4507. $tableAttribs .= $this->borderStyle[0] ? ' style="' . htmlspecialchars($this->borderStyle[0]) . '"' : '';
  4508. $tableAttribs .= $this->borderStyle[2] ? ' background="' . htmlspecialchars($this->backPath . $this->borderStyle[2]) . '"' : '';
  4509. $tableAttribs .= $this->borderStyle[3] ? ' class="' . htmlspecialchars($this->borderStyle[3]) . '"' : '';
  4510. if ($tableAttribs) {
  4511. $tableAttribs = 'border="0" cellspacing="0" cellpadding="0" width="100%"' . $tableAttribs;
  4512. $out_array[$out_pointer] = str_replace('###CONTENT###', $out_array[$out_pointer],
  4513. str_replace('###TABLE_ATTRIBS###', $tableAttribs, $this->sectionWrap));
  4514. }
  4515. $out_pointer++;
  4516. }
  4517. }
  4518. /**
  4519. * Replaces colorscheme markers in the template string
  4520. *
  4521. * @param string Template string with markers to be substituted.
  4522. * @return string
  4523. */
  4524. function rplColorScheme($inTemplate) {
  4525. // Colors:
  4526. $inTemplate = str_replace('###BGCOLOR###', $this->colorScheme[0] ? ' bgcolor="' . $this->colorScheme[0] . '"' : '', $inTemplate);
  4527. $inTemplate = str_replace('###BGCOLOR_HEAD###', $this->colorScheme[1] ? ' bgcolor="' . $this->colorScheme[1] . '"' : '', $inTemplate);
  4528. $inTemplate = str_replace('###FONTCOLOR_HEAD###', $this->colorScheme[3], $inTemplate);
  4529. // Classes:
  4530. $inTemplate = str_replace('###CLASSATTR_1###', $this->classScheme[0] ? ' class="' . $this->classScheme[0] . '"' : '', $inTemplate);
  4531. $inTemplate = str_replace('###CLASSATTR_2###', $this->classScheme[1] ? ' class="' . $this->classScheme[1] . '"' : '', $inTemplate);
  4532. $inTemplate = str_replace('###CLASSATTR_4###', $this->classScheme[3] ? ' class="' . $this->classScheme[3] . '"' : '', $inTemplate);
  4533. return $inTemplate;
  4534. }
  4535. /**
  4536. * Returns divider.
  4537. * Currently not implemented and returns only blank value.
  4538. *
  4539. * @return string Empty string
  4540. */
  4541. function getDivider() {
  4542. return '';
  4543. }
  4544. /**
  4545. * Creates HTML output for a palette
  4546. *
  4547. * @param array The palette array to print
  4548. * @return string HTML output
  4549. */
  4550. function printPalette($palArr) {
  4551. $fieldAttributes = $labelAttributes = '';
  4552. // Init color/class attributes:
  4553. if ($this->colorScheme[2]) {
  4554. $labelAttributes .= ' bgcolor="' . $this->colorScheme[2] . '"';
  4555. }
  4556. if ($this->classScheme[2]) {
  4557. $labelAttributes .= ' class="t3-form-palette-field-label ' . $this->classScheme[2] . '"';
  4558. } else {
  4559. $labelAttributes .= ' class="t3-form-palette-field-label"';
  4560. }
  4561. if ($this->colorScheme[4]) {
  4562. $fieldAttributes .= ' style="color: ' . $this->colorScheme[4] . '"';
  4563. }
  4564. if ($this->classScheme[4]) {
  4565. $fieldAttributes .= ' class="t3-form-palette-field ' . $this->classScheme[4] . '"';
  4566. }
  4567. $row = 0;
  4568. $hRow = $iRow = array();
  4569. $lastLineWasLinebreak = FALSE;
  4570. // Traverse palette fields and render them into containers:
  4571. foreach ($palArr as $content) {
  4572. if ($content['NAME'] === '--linebreak--') {
  4573. if (!$lastLineWasLinebreak) {
  4574. $row++;
  4575. $lastLineWasLinebreak = TRUE;
  4576. }
  4577. } else {
  4578. $lastLineWasLinebreak = FALSE;
  4579. $fieldIdentifierForJs = $content['TABLE'] . '_' . $content['ID'] . '_' . $content['FIELD'];
  4580. $iRow[$row][] = '<span class="t3-form-palette-field-container">' .
  4581. '<label' . $labelAttributes . '>' .
  4582. $content['NAME'] .
  4583. '</label>' .
  4584. '<span' . $fieldAttributes . '>' .
  4585. '<img name="cm_' . $fieldIdentifierForJs . '" src="clear.gif" class="t3-form-palette-icon-contentchanged" alt="" />' .
  4586. '<img name="req_' . $fieldIdentifierForJs . '" src="clear.gif" class="t3-form-palette-icon-required" alt="" />' .
  4587. $content['ITEM'] .
  4588. '</span>' .
  4589. '</span>';
  4590. }
  4591. }
  4592. // Final wrapping into the fieldset:
  4593. $out = '<fieldset class="t3-form-palette-fieldset">';
  4594. for ($i = 0; $i <= $row; $i++) {
  4595. if (isset($iRow[$i])) {
  4596. $out .= implode('', $iRow[$i]);
  4597. $out .= ($i < $row ? '<br />' : '');
  4598. }
  4599. }
  4600. $out .= '</fieldset>';
  4601. return $out;
  4602. }
  4603. /**
  4604. * Returns help-text ICON if configured for.
  4605. *
  4606. * @param string The table name
  4607. * @param string The field name
  4608. * @param boolean Force the return of the help-text icon.
  4609. * @return string HTML, <a>-tag with
  4610. * @deprecated since TYPO3 4.5, will be removed in TYPO3 4.7
  4611. */
  4612. function helpTextIcon($table, $field, $force = 0) {
  4613. t3lib_div::logDeprecatedFunction();
  4614. if ($this->globalShowHelp && $GLOBALS['TCA_DESCR'][$table]['columns'][$field] && (($this->edit_showFieldHelp == 'icon' && !$this->doLoadTableDescr($table)) || $force)) {
  4615. return t3lib_BEfunc::helpTextIcon($table, $field, $this->backPath, $force);
  4616. } else {
  4617. // Detects fields with no CSH and outputs dummy line to insert into CSH locallang file:
  4618. return '<span class="nbsp">&nbsp;</span>';
  4619. }
  4620. }
  4621. /**
  4622. * Returns help text DESCRIPTION, if configured for.
  4623. *
  4624. * @param string The table name
  4625. * @param string The field name
  4626. * @return string
  4627. * @deprecated since TYPO3 4.5, will be removed in TYPO3 4.7
  4628. */
  4629. function helpText($table, $field) {
  4630. t3lib_div::logDeprecatedFunction();
  4631. if ($this->globalShowHelp && $GLOBALS['TCA_DESCR'][$table]['columns'][$field] && ($this->edit_showFieldHelp == 'text' || $this->doLoadTableDescr($table))) {
  4632. $fDat = $GLOBALS['TCA_DESCR'][$table]['columns'][$field];
  4633. return '<table border="0" cellpadding="2" cellspacing="0" width="90%"><tr><td valign="top" width="14">' .
  4634. $this->helpTextIcon(
  4635. $table,
  4636. $field,
  4637. $fDat['details'] || $fDat['syntax'] || $fDat['image_descr'] || $fDat['image'] || $fDat['seeAlso']
  4638. ) .
  4639. '</td><td valign="top"><span class="typo3-TCEforms-helpText">' .
  4640. $GLOBALS['LANG']->hscAndCharConv(strip_tags($fDat['description']), 1) .
  4641. '</span></td></tr></table>';
  4642. }
  4643. }
  4644. /**
  4645. * Returns help-text ICON if configured for.
  4646. *
  4647. * @param string Field name
  4648. * @param string Field title
  4649. * @param string File name with CSH labels
  4650. * @return string HTML, <a>-tag with
  4651. * @deprecated since TYPO3 4.5, this function will be removed in TYPO3 4.7. Use t3lib_BEfunc::wrapInHelp() instead.
  4652. */
  4653. function helpTextIcon_typeFlex($field, $fieldTitle, $cshFile) {
  4654. t3lib_div::logDeprecatedFunction();
  4655. if ($this->globalShowHelp && $cshFile) {
  4656. $value = $GLOBALS['LANG']->sL($cshFile . ':' . $field . '.description');
  4657. if (trim($value)) {
  4658. if (substr($fieldTitle, -1, 1) == ':') {
  4659. $fieldTitle = substr($fieldTitle, 0, strlen($fieldTitle) - 1);
  4660. }
  4661. // Hover popup textbox with alttitle and description
  4662. if ($this->edit_showFieldHelp == 'icon') {
  4663. $arrow = t3lib_iconWorks::getSpriteIcon('actions-view-go-forward');
  4664. // add description text
  4665. $hoverText = '<span class="paragraph">' . nl2br(htmlspecialchars($value)) . $arrow . '</span>';
  4666. // put header before the rest of the text
  4667. $alttitle = $GLOBALS['LANG']->sL($cshFile . ':' . $field . '.alttitle');
  4668. if ($alttitle) {
  4669. $hoverText = '<span class="header">' . $alttitle . '</span><br />' . $hoverText;
  4670. }
  4671. $hoverText = '<span class="typo3-csh-inline">' . $GLOBALS['LANG']->hscAndCharConv($hoverText, FALSE) . '</span>';
  4672. }
  4673. // CSH exists
  4674. $params = base64_encode(serialize(array(
  4675. 'cshFile' => $cshFile,
  4676. 'field' => $field,
  4677. 'title' => $fieldTitle
  4678. )));
  4679. $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;';
  4680. return '<a href="#" class="typo3-csh-link" onclick="' . htmlspecialchars($aOnClick) . '">' .
  4681. t3lib_iconWorks::getSpriteIcon('actions-system-help-open') . $hoverText .
  4682. '</a>';
  4683. }
  4684. }
  4685. return '';
  4686. }
  4687. /**
  4688. * Returns help text DESCRIPTION, if configured for.
  4689. *
  4690. * @param string Field name
  4691. * @param string CSH file name
  4692. * @return string Description for the field with cion or empty string
  4693. * @deprecated since TYPO3 4.5, this function will be removed in TYPO3 4.7. Use t3lib_BEfunc::wrapInHelp() instead.
  4694. */
  4695. function helpText_typeFlex($field, $fieldTitle, $cshFile) {
  4696. t3lib_div::logDeprecatedFunction();
  4697. if ($this->globalShowHelp && $cshFile && $this->edit_showFieldHelp == 'text') {
  4698. $value = $GLOBALS['LANG']->sL($cshFile . ':' . $field . '.description');
  4699. if (trim($value)) {
  4700. return '<table border="0" cellpadding="2" cellspacing="0" width="90%"><tr><td valign="top" width="14">' .
  4701. $this->helpTextIcon_typeFlex(
  4702. $field,
  4703. $fieldTitle,
  4704. $cshFile
  4705. ) .
  4706. '</td><td valign="top"><span class="typo3-TCEforms-helpText-flexform">' .
  4707. $GLOBALS['LANG']->hscAndCharConv(strip_tags($value), 1) .
  4708. '</span></td></tr></table>';
  4709. }
  4710. }
  4711. return '';
  4712. }
  4713. /**
  4714. * Setting the current color scheme ($this->colorScheme) based on $this->defColorScheme plus input string.
  4715. *
  4716. * @param string A color scheme string.
  4717. * @return void
  4718. */
  4719. function setColorScheme($scheme) {
  4720. $this->colorScheme = $this->defColorScheme;
  4721. $this->classScheme = $this->defClassScheme;
  4722. $parts = t3lib_div::trimExplode(',', $scheme);
  4723. foreach ($parts as $key => $col) {
  4724. // Split for color|class:
  4725. list($color, $class) = t3lib_div::trimExplode('|', $col);
  4726. // Handle color values:
  4727. if ($color) {
  4728. $this->colorScheme[$key] = $color;
  4729. }
  4730. if ($color == '-') {
  4731. $this->colorScheme[$key] = '';
  4732. }
  4733. // Handle class values:
  4734. if ($class) {
  4735. $this->classScheme[$key] = $class;
  4736. }
  4737. if ($class == '-') {
  4738. $this->classScheme[$key] = '';
  4739. }
  4740. }
  4741. }
  4742. /**
  4743. * Reset color schemes.
  4744. *
  4745. * @return void
  4746. */
  4747. function resetSchemes() {
  4748. $this->setColorScheme($GLOBALS['TBE_STYLES']['colorschemes'][0]);
  4749. $this->fieldStyle = $GLOBALS['TBE_STYLES']['styleschemes'][0];
  4750. $this->borderStyle = $GLOBALS['TBE_STYLES']['borderschemes'][0];
  4751. }
  4752. /**
  4753. * Store current color scheme
  4754. *
  4755. * @return void
  4756. */
  4757. function storeSchemes() {
  4758. $this->savedSchemes['classScheme'] = $this->classScheme;
  4759. $this->savedSchemes['colorScheme'] = $this->colorScheme;
  4760. $this->savedSchemes['fieldStyle'] = $this->fieldStyle;
  4761. $this->savedSchemes['borderStyle'] = $this->borderStyle;
  4762. }
  4763. /**
  4764. * Restore the saved color scheme
  4765. *
  4766. * @return void
  4767. */
  4768. function restoreSchemes() {
  4769. $this->classScheme = $this->savedSchemes['classScheme'];
  4770. $this->colorScheme = $this->savedSchemes['colorScheme'];
  4771. $this->fieldStyle = $this->savedSchemes['fieldStyle'];
  4772. $this->borderStyle = $this->savedSchemes['borderStyle'];
  4773. }
  4774. /********************************************
  4775. *
  4776. * JavaScript related functions
  4777. *
  4778. ********************************************/
  4779. /**
  4780. * JavaScript code added BEFORE the form is drawn:
  4781. *
  4782. * @return string A <script></script> section with JavaScript.
  4783. */
  4784. function JStop() {
  4785. $out = '';
  4786. // Additional top HTML:
  4787. if (count($this->additionalCode_pre)) {
  4788. $out .= implode('
  4789. <!-- NEXT: -->
  4790. ', $this->additionalCode_pre);
  4791. }
  4792. // Additional top JavaScript
  4793. if (count($this->additionalJS_pre)) {
  4794. $out .= '
  4795. <!--
  4796. JavaScript in top of page (before form):
  4797. -->
  4798. <script type="text/javascript">
  4799. /*<![CDATA[*/
  4800. ' . implode('
  4801. // NEXT:
  4802. ', $this->additionalJS_pre) . '
  4803. /*]]>*/
  4804. </script>
  4805. ';
  4806. }
  4807. // Return result:
  4808. return $out;
  4809. }
  4810. /**
  4811. * JavaScript code used for input-field evaluation.
  4812. *
  4813. * Example use:
  4814. *
  4815. * $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 />';
  4816. * $this->extJSCODE.='typo3form.fieldSet("send_mail_datetime", "datetime", "", 0,0);';
  4817. *
  4818. * ... and then include the result of this function after the form
  4819. *
  4820. * @param string $formname: The identification of the form on the page.
  4821. * @param boolean $update: Just extend/update existing settings, e.g. for AJAX call
  4822. * @return string A section with JavaScript - if $update is false, embedded in <script></script>
  4823. */
  4824. function JSbottom($formname = 'forms[0]', $update = FALSE) {
  4825. $jsFile = array();
  4826. $elements = array();
  4827. // required:
  4828. foreach ($this->requiredFields as $itemImgName => $itemName) {
  4829. $match = array();
  4830. if (preg_match('/^(.+)\[((\w|\d|_)+)\]$/', $itemName, $match)) {
  4831. $record = $match[1];
  4832. $field = $match[2];
  4833. $elements[$record][$field]['required'] = 1;
  4834. $elements[$record][$field]['requiredImg'] = $itemImgName;
  4835. if (isset($this->requiredAdditional[$itemName]) && is_array($this->requiredAdditional[$itemName])) {
  4836. $elements[$record][$field]['additional'] = $this->requiredAdditional[$itemName];
  4837. }
  4838. }
  4839. }
  4840. // range:
  4841. foreach ($this->requiredElements as $itemName => $range) {
  4842. if (preg_match('/^(.+)\[((\w|\d|_)+)\]$/', $itemName, $match)) {
  4843. $record = $match[1];
  4844. $field = $match[2];
  4845. $elements[$record][$field]['range'] = array($range[0], $range[1]);
  4846. $elements[$record][$field]['rangeImg'] = $range['imgName'];
  4847. }
  4848. }
  4849. $this->TBE_EDITOR_fieldChanged_func = 'TBE_EDITOR.fieldChanged_fName(fName,formObj[fName+"_list"]);';
  4850. if (!$update) {
  4851. if ($this->loadMD5_JS) {
  4852. $this->loadJavascriptLib('md5.js');
  4853. }
  4854. /** @var $pageRenderer t3lib_PageRenderer */
  4855. $pageRenderer = $GLOBALS['SOBE']->doc->getPageRenderer();
  4856. $pageRenderer->loadPrototype();
  4857. $pageRenderer->loadExtJS();
  4858. // make textareas resizable and flexible
  4859. if (!($GLOBALS['BE_USER']->uc['resizeTextareas'] == '0' && $GLOBALS['BE_USER']->uc['resizeTextareas_Flexible'] == '0')) {
  4860. $pageRenderer->addCssFile($this->backPath . '../t3lib/js/extjs/ux/resize.css');
  4861. $this->loadJavascriptLib('../t3lib/js/extjs/ux/ext.resizable.js');
  4862. }
  4863. $resizableSettings = array(
  4864. 'textareaMaxHeight' => $GLOBALS['BE_USER']->uc['resizeTextareas_MaxHeight'] > 0 ? $GLOBALS['BE_USER']->uc['resizeTextareas_MaxHeight'] : '600',
  4865. 'textareaFlexible' => (!$GLOBALS['BE_USER']->uc['resizeTextareas_Flexible'] == '0'),
  4866. 'textareaResize' => (!$GLOBALS['BE_USER']->uc['resizeTextareas'] == '0'),
  4867. );
  4868. $pageRenderer->addInlineSettingArray('', $resizableSettings);
  4869. $this->loadJavascriptLib('../t3lib/jsfunc.evalfield.js');
  4870. $this->loadJavascriptLib('jsfunc.tbe_editor.js');
  4871. // needed for tceform manipulation (date picker)
  4872. $typo3Settings = array(
  4873. 'datePickerUSmode' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? 1 : 0,
  4874. 'dateFormat' => array('j-n-Y', 'G:i j-n-Y'),
  4875. 'dateFormatUS' => array('n-j-Y', 'G:i n-j-Y'),
  4876. );
  4877. $pageRenderer->addInlineSettingArray('', $typo3Settings);
  4878. $this->loadJavascriptLib('../t3lib/js/extjs/tceforms.js');
  4879. // if IRRE fields were processed, add the JavaScript functions:
  4880. if ($this->inline->inlineCount) {
  4881. $GLOBALS['SOBE']->doc->getPageRenderer()->loadScriptaculous();
  4882. $this->loadJavascriptLib('../t3lib/jsfunc.inline.js');
  4883. $out .= '
  4884. inline.setPrependFormFieldNames("' . $this->inline->prependNaming . '");
  4885. inline.setNoTitleString("' . addslashes(t3lib_BEfunc::getNoRecordTitle(TRUE)) . '");
  4886. ';
  4887. }
  4888. // if Suggest fields were processed, add the JS functions
  4889. if ($this->suggest->suggestCount > 0) {
  4890. $pageRenderer->loadScriptaculous();
  4891. $this->loadJavascriptLib('../t3lib/js/jsfunc.tceforms_suggest.js');
  4892. }
  4893. // Toggle icons:
  4894. $toggleIcon_open = t3lib_iconWorks::getSpriteIcon('actions-move-down', array('title' => 'Open'));
  4895. $toggleIcon_close = t3lib_iconWorks::getSpriteIcon('actions-move-right', array('title' => 'Close'));
  4896. $out .= '
  4897. function getOuterHTML(idTagPrefix) { // Function getting the outerHTML of an element with id
  4898. var str=($(idTagPrefix).inspect()+$(idTagPrefix).innerHTML+"</"+$(idTagPrefix).tagName.toLowerCase()+">");
  4899. return str;
  4900. }
  4901. function flexFormToggle(id) { // Toggling flexform elements on/off:
  4902. Element.toggle(""+id+"-content");
  4903. if (Element.visible(id+"-content")) {
  4904. $(id+"-toggle").update(\'' . $toggleIcon_open . '\');
  4905. $(id+"-toggleClosed").value = 0;
  4906. } else {
  4907. $(id+"-toggle").update(\'' . $toggleIcon_close . '\');
  4908. $(id+"-toggleClosed").value = 1;
  4909. }
  4910. var previewContent = "";
  4911. var children = $(id+"-content").getElementsByTagName("input");
  4912. for (var i = 0, length = children.length; i < length; i++) {
  4913. if (children[i].type=="text" && children[i].value) previewContent+= (previewContent?" / ":"")+children[i].value;
  4914. }
  4915. if (previewContent.length>80) {
  4916. previewContent = previewContent.substring(0,67)+"...";
  4917. }
  4918. $(id+"-preview").update(previewContent);
  4919. }
  4920. function flexFormToggleSubs(id) { // Toggling sub flexform elements on/off:
  4921. var descendants = $(id).immediateDescendants();
  4922. var isOpen=0;
  4923. var isClosed=0;
  4924. // Traverse and find how many are open or closed:
  4925. for (var i = 0, length = descendants.length; i < length; i++) {
  4926. if (descendants[i].id) {
  4927. if (Element.visible(descendants[i].id+"-content")) {isOpen++;} else {isClosed++;}
  4928. }
  4929. }
  4930. // Traverse and toggle
  4931. for (var i = 0, length = descendants.length; i < length; i++) {
  4932. if (descendants[i].id) {
  4933. if (isOpen!=0 && isClosed!=0) {
  4934. if (Element.visible(descendants[i].id+"-content")) {flexFormToggle(descendants[i].id);}
  4935. } else {
  4936. flexFormToggle(descendants[i].id);
  4937. }
  4938. }
  4939. }
  4940. }
  4941. function flexFormSortable(id) { // Create sortables for flexform sections
  4942. Position.includeScrollOffsets = true;
  4943. Sortable.create(id, {tag:\'div\',constraint: false, onChange:function(){
  4944. setActionStatus(id);
  4945. } });
  4946. }
  4947. function setActionStatus(id) { // Updates the "action"-status for a section. This is used to move and delete elements.
  4948. var descendants = $(id).immediateDescendants();
  4949. // Traverse and find how many are open or closed:
  4950. for (var i = 0, length = descendants.length; i < length; i++) {
  4951. if (descendants[i].id) {
  4952. $(descendants[i].id+"-action").value = descendants[i].visible() ? i : "DELETE";
  4953. }
  4954. }
  4955. }
  4956. TBE_EDITOR.images.req.src = "' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/required_h.gif', '', 1) . '";
  4957. TBE_EDITOR.images.cm.src = "' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/content_client.gif', '', 1) . '";
  4958. TBE_EDITOR.images.sel.src = "' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/content_selected.gif', '', 1) . '";
  4959. TBE_EDITOR.images.clear.src = "' . $this->backPath . 'clear.gif";
  4960. TBE_EDITOR.auth_timeout_field = ' . intval($GLOBALS['BE_USER']->auth_timeout_field) . ';
  4961. TBE_EDITOR.formname = "' . $formname . '";
  4962. TBE_EDITOR.formnameUENC = "' . rawurlencode($formname) . '";
  4963. TBE_EDITOR.backPath = "' . addslashes($this->backPath) . '";
  4964. TBE_EDITOR.prependFormFieldNames = "' . $this->prependFormFieldNames . '";
  4965. TBE_EDITOR.prependFormFieldNamesUENC = "' . rawurlencode($this->prependFormFieldNames) . '";
  4966. TBE_EDITOR.prependFormFieldNamesCnt = ' . substr_count($this->prependFormFieldNames, '[') . ';
  4967. TBE_EDITOR.isPalettedoc = ' . ($this->isPalettedoc ? addslashes($this->isPalettedoc) : 'null') . ';
  4968. TBE_EDITOR.doSaveFieldName = "' . ($this->doSaveFieldName ? addslashes($this->doSaveFieldName) : '') . '";
  4969. TBE_EDITOR.labels.fieldsChanged = ' . $GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.fieldsChanged')) . ';
  4970. TBE_EDITOR.labels.fieldsMissing = ' . $GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.fieldsMissing')) . ';
  4971. TBE_EDITOR.labels.refresh_login = ' . $GLOBALS['LANG']->JScharCode($this->getLL('m_refresh_login')) . ';
  4972. TBE_EDITOR.labels.onChangeAlert = ' . $GLOBALS['LANG']->JScharCode($this->getLL('m_onChangeAlert')) . ';
  4973. evalFunc.USmode = ' . ($GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? '1' : '0') . ';
  4974. TBE_EDITOR.backend_interface = "' . $GLOBALS['BE_USER']->uc['interfaceSetup'] . '";
  4975. ';
  4976. }
  4977. // add JS required for inline fields
  4978. if (count($this->inline->inlineData)) {
  4979. $out .= '
  4980. inline.addToDataArray(' . json_encode($this->inline->inlineData) . ');
  4981. ';
  4982. }
  4983. // Registered nested elements for tabs or inline levels:
  4984. if (count($this->requiredNested)) {
  4985. $out .= '
  4986. TBE_EDITOR.addNested(' . json_encode($this->requiredNested) . ');
  4987. ';
  4988. }
  4989. // elements which are required or have a range definition:
  4990. if (count($elements)) {
  4991. $out .= '
  4992. TBE_EDITOR.addElements(' . json_encode($elements) . ');
  4993. TBE_EDITOR.initRequired();
  4994. ';
  4995. }
  4996. // $this->additionalJS_submit:
  4997. if ($this->additionalJS_submit) {
  4998. $additionalJS_submit = implode('', $this->additionalJS_submit);
  4999. $additionalJS_submit = str_replace(CR, '', $additionalJS_submit);
  5000. $additionalJS_submit = str_replace(LF, '', $additionalJS_submit);
  5001. $out .= '
  5002. TBE_EDITOR.addActionChecks("submit", "' . addslashes($additionalJS_submit) . '");
  5003. ';
  5004. }
  5005. $out .= LF . implode(LF, $this->additionalJS_post) . LF . $this->extJSCODE;
  5006. $out .= '
  5007. TBE_EDITOR.loginRefreshed();
  5008. ';
  5009. // Regular direct output:
  5010. if (!$update) {
  5011. $spacer = LF . TAB;
  5012. $out = $spacer . implode($spacer, $jsFile) . t3lib_div::wrapJS($out);
  5013. }
  5014. return $out;
  5015. }
  5016. /**
  5017. * Used to connect the db/file browser with this document and the formfields on it!
  5018. *
  5019. * @param string Form object reference (including "document.")
  5020. * @return string JavaScript functions/code (NOT contained in a <script>-element)
  5021. */
  5022. function dbFileCon($formObj = 'document.forms[0]') {
  5023. // @TODO: Export this to an own file, it is more static than dynamic JavaScript -- olly
  5024. $str = '
  5025. // ***************
  5026. // Used to connect the db/file browser with this document and the formfields on it!
  5027. // ***************
  5028. var browserWin="";
  5029. function setFormValueOpenBrowser(mode,params) { //
  5030. var url = "' . $this->backPath . 'browser.php?mode="+mode+"&bparams="+params;
  5031. browserWin = window.open(url,"Typo3WinBrowser","height=650,width="+(mode=="db"?650:600)+",status=0,menubar=0,resizable=1,scrollbars=1");
  5032. browserWin.focus();
  5033. }
  5034. function setFormValueFromBrowseWin(fName,value,label,exclusiveValues) {
  5035. var formObj = setFormValue_getFObj(fName);
  5036. if (formObj && value !== "--div--") {
  5037. // Check if the form object has a "_list" element or not
  5038. // The "_list" element exists for multiple selection select types
  5039. var isMultiple = true;
  5040. if (formObj[fName + "_list"]) {
  5041. fObj = formObj[fName + "_list"];
  5042. } else {
  5043. fObj = formObj[fName];
  5044. var isMultiple = false;
  5045. }
  5046. var len = fObj.length;
  5047. if (isMultiple) {
  5048. // Clear elements if exclusive values are found
  5049. if (exclusiveValues) {
  5050. var m = new RegExp("(^|,)" + value + "($|,)");
  5051. if (exclusiveValues.match(m)) {
  5052. // the new value is exclusive
  5053. for (a = len - 1; a >= 0; a--) {
  5054. fObj[a] = null;
  5055. }
  5056. len = 0;
  5057. } else if (len == 1) {
  5058. m = new RegExp("(^|,)" + fObj.options[0].value + "($|,)");
  5059. if (exclusiveValues.match(m)) {
  5060. // the old value is exclusive
  5061. fObj[0] = null;
  5062. len = 0;
  5063. }
  5064. }
  5065. }
  5066. // Inserting element
  5067. var setOK = 1;
  5068. if (!formObj[fName + "_mul"] || formObj[fName + "_mul"].value == 0) {
  5069. for (a = 0; a < len; a++) {
  5070. if (fObj.options[a].value == value) {
  5071. setOK = 0;
  5072. }
  5073. }
  5074. }
  5075. if (setOK) {
  5076. fObj.length++;
  5077. fObj.options[len].value = value;
  5078. fObj.options[len].text = unescape(label);
  5079. // Traversing list and set the hidden-field
  5080. setHiddenFromList(fObj,formObj[fName]);
  5081. ' . $this->TBE_EDITOR_fieldChanged_func . '
  5082. }
  5083. } else {
  5084. // The incoming value consists of the table name, an underscore and the uid
  5085. // For a single selection field we need only the uid, so we extract it
  5086. var uidValue = value;
  5087. var pattern = /_(\d+)$/;
  5088. var result = value.match(pattern);
  5089. if (result != null) {
  5090. uidValue = result[1];
  5091. }
  5092. // Change the selected value
  5093. fObj.value = uidValue;
  5094. }
  5095. }
  5096. }
  5097. function setHiddenFromList(fObjSel,fObjHid) { //
  5098. l=fObjSel.length;
  5099. fObjHid.value="";
  5100. for (a=0;a<l;a++) {
  5101. fObjHid.value+=fObjSel.options[a].value+",";
  5102. }
  5103. }
  5104. function setFormValueManipulate(fName,type) { //
  5105. var formObj = setFormValue_getFObj(fName);
  5106. if (formObj) {
  5107. var localArray_V = new Array();
  5108. var localArray_L = new Array();
  5109. var localArray_S = new Array();
  5110. var fObjSel = formObj[fName+"_list"];
  5111. var l=fObjSel.length;
  5112. var c=0;
  5113. if ((type=="Remove" && fObjSel.size > 1) || type=="Top" || type=="Bottom") {
  5114. if (type=="Top") {
  5115. for (a=0;a<l;a++) {
  5116. if (fObjSel.options[a].selected==1) {
  5117. localArray_V[c]=fObjSel.options[a].value;
  5118. localArray_L[c]=fObjSel.options[a].text;
  5119. localArray_S[c]=1;
  5120. c++;
  5121. }
  5122. }
  5123. }
  5124. for (a=0;a<l;a++) {
  5125. if (fObjSel.options[a].selected!=1) {
  5126. localArray_V[c]=fObjSel.options[a].value;
  5127. localArray_L[c]=fObjSel.options[a].text;
  5128. localArray_S[c]=0;
  5129. c++;
  5130. }
  5131. }
  5132. if (type=="Bottom") {
  5133. for (a=0;a<l;a++) {
  5134. if (fObjSel.options[a].selected==1) {
  5135. localArray_V[c]=fObjSel.options[a].value;
  5136. localArray_L[c]=fObjSel.options[a].text;
  5137. localArray_S[c]=1;
  5138. c++;
  5139. }
  5140. }
  5141. }
  5142. }
  5143. if (type=="Down") {
  5144. var tC = 0;
  5145. var tA = new Array();
  5146. for (a=0;a<l;a++) {
  5147. if (fObjSel.options[a].selected!=1) {
  5148. // Add non-selected element:
  5149. localArray_V[c]=fObjSel.options[a].value;
  5150. localArray_L[c]=fObjSel.options[a].text;
  5151. localArray_S[c]=0;
  5152. c++;
  5153. // Transfer any accumulated and reset:
  5154. if (tA.length > 0) {
  5155. for (aa=0;aa<tA.length;aa++) {
  5156. localArray_V[c]=fObjSel.options[tA[aa]].value;
  5157. localArray_L[c]=fObjSel.options[tA[aa]].text;
  5158. localArray_S[c]=1;
  5159. c++;
  5160. }
  5161. var tC = 0;
  5162. var tA = new Array();
  5163. }
  5164. } else {
  5165. tA[tC] = a;
  5166. tC++;
  5167. }
  5168. }
  5169. // Transfer any remaining:
  5170. if (tA.length > 0) {
  5171. for (aa=0;aa<tA.length;aa++) {
  5172. localArray_V[c]=fObjSel.options[tA[aa]].value;
  5173. localArray_L[c]=fObjSel.options[tA[aa]].text;
  5174. localArray_S[c]=1;
  5175. c++;
  5176. }
  5177. }
  5178. }
  5179. if (type=="Up") {
  5180. var tC = 0;
  5181. var tA = new Array();
  5182. var c = l-1;
  5183. for (a=l-1;a>=0;a--) {
  5184. if (fObjSel.options[a].selected!=1) {
  5185. // Add non-selected element:
  5186. localArray_V[c]=fObjSel.options[a].value;
  5187. localArray_L[c]=fObjSel.options[a].text;
  5188. localArray_S[c]=0;
  5189. c--;
  5190. // Transfer any accumulated and reset:
  5191. if (tA.length > 0) {
  5192. for (aa=0;aa<tA.length;aa++) {
  5193. localArray_V[c]=fObjSel.options[tA[aa]].value;
  5194. localArray_L[c]=fObjSel.options[tA[aa]].text;
  5195. localArray_S[c]=1;
  5196. c--;
  5197. }
  5198. var tC = 0;
  5199. var tA = new Array();
  5200. }
  5201. } else {
  5202. tA[tC] = a;
  5203. tC++;
  5204. }
  5205. }
  5206. // Transfer any remaining:
  5207. if (tA.length > 0) {
  5208. for (aa=0;aa<tA.length;aa++) {
  5209. localArray_V[c]=fObjSel.options[tA[aa]].value;
  5210. localArray_L[c]=fObjSel.options[tA[aa]].text;
  5211. localArray_S[c]=1;
  5212. c--;
  5213. }
  5214. }
  5215. c=l; // Restore length value in "c"
  5216. }
  5217. // Transfer items in temporary storage to list object:
  5218. fObjSel.length = c;
  5219. for (a=0;a<c;a++) {
  5220. fObjSel.options[a].value = localArray_V[a];
  5221. fObjSel.options[a].text = localArray_L[a];
  5222. fObjSel.options[a].selected = localArray_S[a];
  5223. }
  5224. setHiddenFromList(fObjSel,formObj[fName]);
  5225. ' . $this->TBE_EDITOR_fieldChanged_func . '
  5226. }
  5227. }
  5228. function setFormValue_getFObj(fName) { //
  5229. var formObj = ' . $formObj . ';
  5230. if (formObj) {
  5231. // Take the form object if it is either of type select-one or of type-multiple and it has a "_list" element
  5232. if (formObj[fName] && ((formObj[fName].type == "select-one") || (formObj[fName + "_list"] && formObj[fName + "_list"].type == "select-multiple"))) {
  5233. return formObj;
  5234. } else {
  5235. alert("Formfields missing:\n fName: " + formObj[fName] + "\n fName_list:" + formObj[fName + "_list"] + "\n type:" + formObj[fName + "_list"].type + "\n fName:" + fName);
  5236. }
  5237. }
  5238. return "";
  5239. }
  5240. // END: dbFileCon parts.
  5241. ';
  5242. return $str;
  5243. }
  5244. /**
  5245. * Prints necessary JavaScript for TCEforms (after the form HTML).
  5246. *
  5247. * @return void
  5248. */
  5249. function printNeededJSFunctions() {
  5250. // JS evaluation:
  5251. $out = $this->JSbottom($this->formName);
  5252. // Integrate JS functions for the element browser if such fields or IRRE fields were processed:
  5253. if ($this->printNeededJS['dbFileIcons'] || $this->inline->inlineCount) {
  5254. $out .= '
  5255. <!--
  5256. JavaScript after the form has been drawn:
  5257. -->
  5258. <script type="text/javascript">
  5259. /*<![CDATA[*/
  5260. ' . $this->dbFileCon('document.' . $this->formName) . '
  5261. /*]]>*/
  5262. </script>';
  5263. }
  5264. return $out;
  5265. }
  5266. /**
  5267. * Returns necessary JavaScript for the top
  5268. *
  5269. * @return void
  5270. */
  5271. function printNeededJSFunctions_top() {
  5272. // JS evaluation:
  5273. $out = $this->JStop($this->formName);
  5274. return $out;
  5275. }
  5276. /**
  5277. * Includes a javascript library that exists in the core /typo3/ directory. The
  5278. * backpath is automatically applied.
  5279. * This method acts as wrapper for $GLOBALS['SOBE']->doc->loadJavascriptLib($lib).
  5280. *
  5281. * @param string $lib: Library name. Call it with the full path like "contrib/prototype/prototype.js" to load it
  5282. * @return void
  5283. */
  5284. public function loadJavascriptLib($lib) {
  5285. $GLOBALS['SOBE']->doc->loadJavascriptLib($lib);
  5286. }
  5287. /********************************************
  5288. *
  5289. * Various helper functions
  5290. *
  5291. ********************************************/
  5292. /**
  5293. * Gets default record. Maybe not used anymore. FE-editor?
  5294. *
  5295. * @param string Database Tablename
  5296. * @param integer PID value (positive / negative)
  5297. * @return array "default" row.
  5298. */
  5299. function getDefaultRecord($table, $pid = 0) {
  5300. global $TCA;
  5301. if ($TCA[$table]) {
  5302. t3lib_div::loadTCA($table);
  5303. $row = array();
  5304. if ($pid < 0 && $TCA[$table]['ctrl']['useColumnsForDefaultValues']) {
  5305. // Fetches the previous record:
  5306. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, 'uid=' . abs($pid) . t3lib_BEfunc::deleteClause($table));
  5307. if ($drow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
  5308. // Gets the list of fields to copy from the previous record.
  5309. $fArr = explode(',', $TCA[$table]['ctrl']['useColumnsForDefaultValues']);
  5310. foreach ($fArr as $theF) {
  5311. if ($TCA[$table]['columns'][$theF]) {
  5312. $row[$theF] = $drow[$theF];
  5313. }
  5314. }
  5315. }
  5316. $GLOBALS['TYPO3_DB']->sql_free_result($res);
  5317. }
  5318. foreach ($TCA[$table]['columns'] as $field => $info) {
  5319. if (isset($info['config']['default'])) {
  5320. $row[$field] = $info['config']['default'];
  5321. }
  5322. }
  5323. return $row;
  5324. }
  5325. }
  5326. /**
  5327. * Return record path (visually formatted, using t3lib_BEfunc::getRecordPath() )
  5328. *
  5329. * @param string Table name
  5330. * @param array Record array
  5331. * @return string The record path.
  5332. * @see t3lib_BEfunc::getRecordPath()
  5333. */
  5334. function getRecordPath($table, $rec) {
  5335. t3lib_BEfunc::fixVersioningPid($table, $rec);
  5336. list($tscPID, $thePidValue) = $this->getTSCpid($table, $rec['uid'], $rec['pid']);
  5337. if ($thePidValue >= 0) {
  5338. return t3lib_BEfunc::getRecordPath($tscPID, $this->readPerms(), 15);
  5339. }
  5340. }
  5341. /**
  5342. * Returns the select-page read-access SQL clause.
  5343. * Returns cached string, so you can call this function as much as you like without performance loss.
  5344. *
  5345. * @return string
  5346. */
  5347. function readPerms() {
  5348. if (!$this->perms_clause_set) {
  5349. $this->perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
  5350. $this->perms_clause_set = 1;
  5351. }
  5352. return $this->perms_clause;
  5353. }
  5354. /**
  5355. * Fetches language label for key
  5356. *
  5357. * @param string Language label reference, eg. 'LLL:EXT:lang/locallang_core.php:labels.blablabla'
  5358. * @return string The value of the label, fetched for the current backend language.
  5359. */
  5360. function sL($str) {
  5361. return $GLOBALS['LANG']->sL($str);
  5362. }
  5363. /**
  5364. * Returns language label from locallang_core.php
  5365. * Labels must be prefixed with either "l_" or "m_".
  5366. * The prefix "l_" maps to the prefix "labels." inside locallang_core.php
  5367. * The prefix "m_" maps to the prefix "mess." inside locallang_core.php
  5368. *
  5369. * @param string The label key
  5370. * @return string The value of the label, fetched for the current backend language.
  5371. */
  5372. function getLL($str) {
  5373. $content = '';
  5374. switch (substr($str, 0, 2)) {
  5375. case 'l_':
  5376. $content = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.' . substr($str, 2));
  5377. break;
  5378. case 'm_':
  5379. $content = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:mess.' . substr($str, 2));
  5380. break;
  5381. }
  5382. return $content;
  5383. }
  5384. /**
  5385. * Returns true, if the palette, $palette, is collapsed (not shown, but found in top-frame) for the table.
  5386. *
  5387. * @param string The table name
  5388. * @param integer The palette pointer/number
  5389. * @return boolean
  5390. */
  5391. function isPalettesCollapsed($table, $palette) {
  5392. global $TCA;
  5393. if ($TCA[$table]['ctrl']['canNotCollapse']) {
  5394. return 0;
  5395. }
  5396. if (is_array($TCA[$table]['palettes'][$palette]) && $TCA[$table]['palettes'][$palette]['canNotCollapse']) {
  5397. return 0;
  5398. }
  5399. return $this->palettesCollapsed;
  5400. }
  5401. /**
  5402. * Returns true, if the evaluation of the required-field code is OK.
  5403. *
  5404. * @param string The required-field code
  5405. * @param array The record to evaluate
  5406. * @param string FlexForm value key, eg. vDEF
  5407. * @return boolean
  5408. */
  5409. function isDisplayCondition($displayCond, $row, $ffValueKey = '') {
  5410. $output = FALSE;
  5411. $parts = explode(':', $displayCond);
  5412. switch ((string) $parts[0]) { // Type of condition:
  5413. case 'FIELD':
  5414. if ($ffValueKey) {
  5415. if (strpos($parts[1], 'parentRec.') !== FALSE) {
  5416. $fParts = explode('.', $parts[1]);
  5417. $theFieldValue = $row['parentRec'][$fParts[1]];
  5418. } else {
  5419. $theFieldValue = $row[$parts[1]][$ffValueKey];
  5420. }
  5421. } else {
  5422. $theFieldValue = $row[$parts[1]];
  5423. }
  5424. switch ((string) $parts[2]) {
  5425. case 'REQ':
  5426. if (strtolower($parts[3]) == 'true') {
  5427. $output = $theFieldValue ? TRUE : FALSE;
  5428. } elseif (strtolower($parts[3]) == 'false') {
  5429. $output = !$theFieldValue ? TRUE : FALSE;
  5430. }
  5431. break;
  5432. case '>':
  5433. $output = $theFieldValue > $parts[3];
  5434. break;
  5435. case '<':
  5436. $output = $theFieldValue < $parts[3];
  5437. break;
  5438. case '>=':
  5439. $output = $theFieldValue >= $parts[3];
  5440. break;
  5441. case '<=':
  5442. $output = $theFieldValue <= $parts[3];
  5443. break;
  5444. case '-':
  5445. case '!-':
  5446. $cmpParts = explode('-', $parts[3]);
  5447. $output = $theFieldValue >= $cmpParts[0] && $theFieldValue <= $cmpParts[1];
  5448. if ($parts[2]{0} == '!') {
  5449. $output = !$output;
  5450. }
  5451. break;
  5452. case 'IN':
  5453. case '!IN':
  5454. $output = t3lib_div::inList($parts[3], $theFieldValue);
  5455. if ($parts[2]{0} == '!') {
  5456. $output = !$output;
  5457. }
  5458. break;
  5459. case '=':
  5460. case '!=':
  5461. $output = t3lib_div::inList($parts[3], $theFieldValue);
  5462. if ($parts[2]{0} == '!') {
  5463. $output = !$output;
  5464. }
  5465. break;
  5466. }
  5467. break;
  5468. case 'EXT':
  5469. switch ((string) $parts[2]) {
  5470. case 'LOADED':
  5471. if (strtolower($parts[3]) == 'true') {
  5472. $output = t3lib_extMgm::isLoaded($parts[1]) ? TRUE : FALSE;
  5473. } elseif (strtolower($parts[3]) == 'false') {
  5474. $output = !t3lib_extMgm::isLoaded($parts[1]) ? TRUE : FALSE;
  5475. }
  5476. break;
  5477. }
  5478. break;
  5479. case 'REC':
  5480. switch ((string) $parts[1]) {
  5481. case 'NEW':
  5482. if (strtolower($parts[2]) == 'true') {
  5483. $output = !(intval($row['uid']) > 0) ? TRUE : FALSE;
  5484. } elseif (strtolower($parts[2]) == 'false') {
  5485. $output = (intval($row['uid']) > 0) ? TRUE : FALSE;
  5486. }
  5487. break;
  5488. }
  5489. break;
  5490. case 'HIDE_L10N_SIBLINGS':
  5491. if ($ffValueKey === 'vDEF') {
  5492. $output = TRUE;
  5493. } elseif ($parts[1] === 'except_admin' && $GLOBALS['BE_USER']->isAdmin()) {
  5494. $output = TRUE;
  5495. }
  5496. break;
  5497. case 'HIDE_FOR_NON_ADMINS':
  5498. $output = $GLOBALS['BE_USER']->isAdmin() ? TRUE : FALSE;
  5499. break;
  5500. case 'VERSION':
  5501. switch ((string) $parts[1]) {
  5502. case 'IS':
  5503. $isNewRecord = (intval($row['uid']) > 0 ? FALSE : TRUE);
  5504. // detection of version can be done be detecting the workspace of the user
  5505. $isUserInWorkspace = ($GLOBALS['BE_USER']->workspace > 0 ? TRUE : FALSE);
  5506. if (intval($row['pid']) == -1 || intval($row['_ORIG_pid']) == -1) {
  5507. $isRecordDetectedAsVersion = TRUE;
  5508. } else {
  5509. $isRecordDetectedAsVersion = FALSE;
  5510. }
  5511. // New records in a workspace are not handled as a version record
  5512. // if it's no new version, we detect versions like this:
  5513. // -- if user is in workspace: always true
  5514. // -- if editor is in live ws: only true if pid == -1
  5515. $isVersion = ($isUserInWorkspace || $isRecordDetectedAsVersion) && !$isNewRecord;
  5516. if (strtolower($parts[2]) == 'true') {
  5517. $output = $isVersion;
  5518. } else {
  5519. if (strtolower($parts[2]) == 'false') {
  5520. $output = !$isVersion;
  5521. }
  5522. }
  5523. break;
  5524. }
  5525. break;
  5526. }
  5527. return $output;
  5528. }
  5529. /**
  5530. * Return TSCpid (cached)
  5531. * Using t3lib_BEfunc::getTSCpid()
  5532. *
  5533. * @param string Tablename
  5534. * @param string UID value
  5535. * @param string PID value
  5536. * @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.
  5537. * @see t3lib_BEfunc::getTSCpid()
  5538. */
  5539. function getTSCpid($table, $uid, $pid) {
  5540. $key = $table . ':' . $uid . ':' . $pid;
  5541. if (!isset($this->cache_getTSCpid[$key])) {
  5542. $this->cache_getTSCpid[$key] = t3lib_BEfunc::getTSCpid($table, $uid, $pid);
  5543. }
  5544. return $this->cache_getTSCpid[$key];
  5545. }
  5546. /**
  5547. * Returns true if descriptions should be loaded always
  5548. *
  5549. * @param string Table for which to check
  5550. * @return boolean
  5551. */
  5552. function doLoadTableDescr($table) {
  5553. global $TCA;
  5554. return $TCA[$table]['interface']['always_description'];
  5555. }
  5556. /**
  5557. * Returns an array of available languages (to use for FlexForms)
  5558. *
  5559. * @param boolean If set, only languages which are paired with a static_info_table / static_language record will be returned.
  5560. * @param boolean If set, an array entry for a default language is set.
  5561. * @return array
  5562. */
  5563. function getAvailableLanguages($onlyIsoCoded = 1, $setDefault = 1) {
  5564. $isL = t3lib_extMgm::isLoaded('static_info_tables');
  5565. // Find all language records in the system:
  5566. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('static_lang_isocode,title,uid', 'sys_language', 'pid=0 AND hidden=0' . t3lib_BEfunc::deleteClause('sys_language'), '', 'title');
  5567. // Traverse them:
  5568. $output = array();
  5569. if ($setDefault) {
  5570. $output[0] = array(
  5571. 'uid' => 0,
  5572. 'title' => 'Default language',
  5573. 'ISOcode' => 'DEF'
  5574. );
  5575. }
  5576. while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
  5577. $output[$row['uid']] = $row;
  5578. if ($isL && $row['static_lang_isocode']) {
  5579. $rr = t3lib_BEfunc::getRecord('static_languages', $row['static_lang_isocode'], 'lg_iso_2');
  5580. if ($rr['lg_iso_2']) {
  5581. $output[$row['uid']]['ISOcode'] = $rr['lg_iso_2'];
  5582. }
  5583. }
  5584. if ($onlyIsoCoded && !$output[$row['uid']]['ISOcode']) {
  5585. unset($output[$row['uid']]);
  5586. }
  5587. }
  5588. return $output;
  5589. }
  5590. /**
  5591. * Initializes language icons etc.
  5592. *
  5593. * param string Table name
  5594. * param array Record
  5595. * param string Sys language uid OR ISO language code prefixed with "v", eg. "vDA"
  5596. * @return void
  5597. */
  5598. function getLanguageIcon($table, $row, $sys_language_uid) {
  5599. global $TCA, $LANG;
  5600. $mainKey = $table . ':' . $row['uid'];
  5601. if (!isset($this->cachedLanguageFlag[$mainKey])) {
  5602. t3lib_BEfunc::fixVersioningPid($table, $row);
  5603. list($tscPID, $thePidValue) = $this->getTSCpid($table, $row['uid'], $row['pid']);
  5604. $t8Tools = t3lib_div::makeInstance('t3lib_transl8tools');
  5605. $this->cachedLanguageFlag[$mainKey] = $t8Tools->getSystemLanguages($tscPID, $this->backPath);
  5606. }
  5607. // Convert sys_language_uid to sys_language_uid if input was in fact a string (ISO code expected then)
  5608. if (!t3lib_div::testInt($sys_language_uid)) {
  5609. foreach ($this->cachedLanguageFlag[$mainKey] as $rUid => $cD) {
  5610. if ('v' . $cD['ISOcode'] === $sys_language_uid) {
  5611. $sys_language_uid = $rUid;
  5612. }
  5613. }
  5614. }
  5615. $out = '';
  5616. if ($this->cachedLanguageFlag[$mainKey][$sys_language_uid]['flagIcon']) {
  5617. $out .= t3lib_iconWorks::getSpriteIcon($this->cachedLanguageFlag[$mainKey][$sys_language_uid]['flagIcon']);
  5618. $out .= '&nbsp;';
  5619. } else if ($this->cachedLanguageFlag[$mainKey][$sys_language_uid]['title']) {
  5620. $out .= '[' . $this->cachedLanguageFlag[$mainKey][$sys_language_uid]['title'] . ']';
  5621. $out .= '&nbsp;';
  5622. }
  5623. return $out;
  5624. }
  5625. /**
  5626. * Rendering preview output of a field value which is not shown as a form field but just outputted.
  5627. *
  5628. * @param string The value to output
  5629. * @param array Configuration for field.
  5630. * @param string Name of field.
  5631. * @return string HTML formatted output
  5632. */
  5633. function previewFieldValue($value, $config, $field = '') {
  5634. if ($config['config']['type'] === 'group' &&
  5635. ($config['config']['internal_type'] === 'file' ||
  5636. $config['config']['internal_type'] === 'file_reference')) {
  5637. // Ignore uploadfolder if internal_type is file_reference
  5638. if ($config['config']['internal_type'] === 'file_reference') {
  5639. $config['config']['uploadfolder'] = '';
  5640. }
  5641. $show_thumbs = TRUE;
  5642. $table = 'tt_content';
  5643. // Making the array of file items:
  5644. $itemArray = t3lib_div::trimExplode(',', $value, 1);
  5645. // Showing thumbnails:
  5646. $thumbsnail = '';
  5647. if ($show_thumbs) {
  5648. $imgs = array();
  5649. foreach ($itemArray as $imgRead) {
  5650. $imgP = explode('|', $imgRead);
  5651. $imgPath = rawurldecode($imgP[0]);
  5652. $rowCopy = array();
  5653. $rowCopy[$field] = $imgPath;
  5654. // Icon + clickmenu:
  5655. $absFilePath = t3lib_div::getFileAbsFileName($config['config']['uploadfolder'] ? $config['config']['uploadfolder'] . '/' . $imgPath : $imgPath);
  5656. $fileInformation = pathinfo($imgPath);
  5657. $fileIcon = t3lib_iconWorks::getSpriteIconForFile($imgPath,
  5658. array('title' =>
  5659. htmlspecialchars($fileInformation['basename'] .
  5660. ($absFilePath && @is_file($absFilePath) ?
  5661. ' (' . t3lib_div::formatSize(filesize($absFilePath)) . 'bytes)' :
  5662. ' - FILE NOT FOUND!')
  5663. )
  5664. )
  5665. );
  5666. $imgs[] = '<span class="nobr">' . t3lib_BEfunc::thumbCode($rowCopy, $table, $field, $this->backPath, 'thumbs.php', $config['config']['uploadfolder'], 0, ' align="middle"') .
  5667. ($absFilePath ? $this->getClickMenu($fileIcon, $absFilePath) : $fileIcon) .
  5668. $imgPath .
  5669. '</span>';
  5670. }
  5671. $thumbsnail = implode('<br />', $imgs);
  5672. }
  5673. return $thumbsnail;
  5674. } else {
  5675. return nl2br(htmlspecialchars($value));
  5676. }
  5677. }
  5678. /**
  5679. * Generates and return information about which languages the current user should see in preview, configured by options.additionalPreviewLanguages
  5680. *
  5681. * return array Array of additional languages to preview
  5682. */
  5683. function getAdditionalPreviewLanguages() {
  5684. if (!isset($this->cachedAdditionalPreviewLanguages)) {
  5685. if ($GLOBALS['BE_USER']->getTSConfigVal('options.additionalPreviewLanguages')) {
  5686. $uids = t3lib_div::intExplode(',', $GLOBALS['BE_USER']->getTSConfigVal('options.additionalPreviewLanguages'));
  5687. foreach ($uids as $uid) {
  5688. if ($sys_language_rec = t3lib_BEfunc::getRecord('sys_language', $uid)) {
  5689. $this->cachedAdditionalPreviewLanguages[$uid] = array('uid' => $uid);
  5690. if ($sys_language_rec['static_lang_isocode'] && t3lib_extMgm::isLoaded('static_info_tables')) {
  5691. $staticLangRow = t3lib_BEfunc::getRecord('static_languages', $sys_language_rec['static_lang_isocode'], 'lg_iso_2');
  5692. if ($staticLangRow['lg_iso_2']) {
  5693. $this->cachedAdditionalPreviewLanguages[$uid]['uid'] = $uid;
  5694. $this->cachedAdditionalPreviewLanguages[$uid]['ISOcode'] = $staticLangRow['lg_iso_2'];
  5695. }
  5696. }
  5697. }
  5698. }
  5699. } else {
  5700. // None:
  5701. $this->cachedAdditionalPreviewLanguages = array();
  5702. }
  5703. }
  5704. return $this->cachedAdditionalPreviewLanguages;
  5705. }
  5706. /**
  5707. * Push a new element to the dynNestedStack. Thus, every object know, if it's
  5708. * nested in a tab or IRRE level and in which order this was processed.
  5709. *
  5710. * @param string $type: Type of the level, e.g. "tab" or "inline"
  5711. * @param string $ident: Identifier of the level
  5712. * @return void
  5713. */
  5714. function pushToDynNestedStack($type, $ident) {
  5715. $this->dynNestedStack[] = array($type, $ident);
  5716. }
  5717. /**
  5718. * Remove an element from the dynNestedStack. If $type and $ident
  5719. * are set, the last element will only be removed, if it matches
  5720. * what is expected to be removed.
  5721. *
  5722. * @param string $type: Type of the level, e.g. "tab" or "inline"
  5723. * @param string $ident: Identifier of the level
  5724. * @return void
  5725. */
  5726. function popFromDynNestedStack($type = NULL, $ident = NULL) {
  5727. if ($type != NULL && $ident != NULL) {
  5728. $last = end($this->dynNestedStack);
  5729. if ($type == $last[0] && $ident == $last[1]) {
  5730. array_pop($this->dynNestedStack);
  5731. }
  5732. } else {
  5733. array_pop($this->dynNestedStack);
  5734. }
  5735. }
  5736. /**
  5737. * Get the dynNestedStack as associative array.
  5738. * The result is e.g. ['tab','DTM-ABCD-1'], ['inline','data[13][table][uid][field]'], ['tab','DTM-DEFG-2'], ...
  5739. *
  5740. * @param boolean $json: Return a JSON string instead of an array - default: false
  5741. * @param boolean $skipFirst: Skip the first element in the dynNestedStack - default: false
  5742. * @return mixed Returns an associative array by default. If $json is true, it will be returned as JSON string.
  5743. */
  5744. function getDynNestedStack($json = FALSE, $skipFirst = FALSE) {
  5745. $result = $this->dynNestedStack;
  5746. if ($skipFirst) {
  5747. array_shift($result);
  5748. }
  5749. return ($json ? json_encode($result) : $result);
  5750. }
  5751. /**
  5752. * Takes care of registering properties in requiredFields and requiredElements.
  5753. * The current hierarchy of IRRE and/or Tabs is stored. Thus, it is possible to determine,
  5754. * which required field/element was filled incorrectly and show it, even if the Tab or IRRE
  5755. * level is hidden.
  5756. *
  5757. * @param string $type: Type of requirement ('field' or 'range')
  5758. * @param string $name: The name of the form field
  5759. * @param mixed $value: For type 'field' string, for type 'range' array
  5760. * @return void
  5761. */
  5762. protected function registerRequiredProperty($type, $name, $value) {
  5763. if ($type == 'field' && is_string($value)) {
  5764. $this->requiredFields[$name] = $value;
  5765. // requiredFields have name/value swapped! For backward compatibility we keep this:
  5766. $itemName = $value;
  5767. } elseif ($type == 'range' && is_array($value)) {
  5768. $this->requiredElements[$name] = $value;
  5769. $itemName = $name;
  5770. }
  5771. // Set the situation of nesting for the current field:
  5772. $this->registerNestedElement($itemName);
  5773. }
  5774. /**
  5775. * Sets the current situation of nested tabs and inline levels for a given element.
  5776. *
  5777. * @param string $itemName: The element the nesting should be stored for
  5778. * @param boolean $setLevel: Set the reverse level lookup - default: true
  5779. * @return void
  5780. */
  5781. protected function registerNestedElement($itemName, $setLevel = TRUE) {
  5782. $dynNestedStack = $this->getDynNestedStack();
  5783. if (count($dynNestedStack) && preg_match('/^(.+\])\[(\w+)\]$/', $itemName, $match)) {
  5784. array_shift($match);
  5785. $this->requiredNested[$itemName] = array(
  5786. 'parts' => $match,
  5787. 'level' => $dynNestedStack,
  5788. );
  5789. }
  5790. }
  5791. /**
  5792. * Insert additional style sheet link
  5793. *
  5794. * @param string $key: some key identifying the style sheet
  5795. * @param string $href: uri to the style sheet file
  5796. * @param string $title: value for the title attribute of the link element
  5797. * @return string $relation: value for the rel attribute of the link element
  5798. * @return void
  5799. */
  5800. public function addStyleSheet($key, $href, $title = '', $relation = 'stylesheet') {
  5801. $GLOBALS['SOBE']->doc->addStyleSheet($key, $href, $title, $relation);
  5802. }
  5803. }
  5804. if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tceforms.php'])) {
  5805. include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tceforms.php']);
  5806. }
  5807. ?>