/t3lib/tceforms/class.t3lib_tceforms_form.php

https://github.com/andreaswolf/typo3-tceforms · PHP · 1085 lines · 535 code · 180 blank · 370 comment · 48 complexity · a50e87ef35065b61c21cd3d0d7b060b0 MD5 · raw file

  1. <?php
  2. // TODO: check if docLarge is needed
  3. class t3lib_TCEforms_Form implements t3lib_TCEforms_Context {
  4. /**
  5. * All record objects belonging to this form
  6. *
  7. * @var array
  8. */
  9. protected $recordObjects = array();
  10. /**
  11. * If all palettes are collapsed (default) or expanded
  12. *
  13. * @var boolean
  14. */
  15. protected $palettesCollapsed;
  16. protected $formName;
  17. /**
  18. * Prefix for form field name
  19. *
  20. * @var string
  21. */
  22. protected $formFieldNamePrefix;
  23. protected $formFieldFileNamePrefix;
  24. protected $formFieldIdPrefix;
  25. /**
  26. * The prefix for the element identifiers. This may be used to safely generate unique identifiers for
  27. * different forms on one page.
  28. *
  29. * Only used inside the context object.
  30. *
  31. * @var string
  32. */
  33. protected $elementIdentifierPrefix;
  34. /**
  35. * The stack of element identifier parts used for creating element identifiers.
  36. *
  37. * This will usually be imploded with a separator to create an identifier.
  38. *
  39. * @var array<string>
  40. */
  41. protected $elementIdentifierStack = array();
  42. /**
  43. *
  44. *
  45. * @var array
  46. */
  47. protected $fieldList;
  48. /**
  49. * Fields on this form marked as required
  50. *
  51. * @var array
  52. */
  53. protected $requiredFields = array();
  54. /**
  55. * Fields on this form which are limited to a specific range
  56. *
  57. * @var array
  58. */
  59. protected $rangeFields = array();
  60. /**
  61. *
  62. * @var string
  63. */
  64. protected $backPath;
  65. // Internal, registers for user defined functions etc.
  66. protected $additionalCodePreForm = array(); // Additional HTML code, printed before the form.
  67. protected $additionalJSPreForm = array(); // Additional JavaScript, printed before the form
  68. protected $additionalJSPostForm = array(); // Additional JavaScript printed after the form
  69. protected $additionalJSSubmit = 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.
  70. /**
  71. * Used to indicate the mode of CSH (Context Sensitive Help), whether it should be icons-only
  72. * ('icon'), full description ('text') or not at all (blank).
  73. *
  74. * @var string
  75. */
  76. // t3lib_tceforms->edit_showFieldHelp
  77. protected $editFieldHelpMode;
  78. /**
  79. * If TRUE, upload fields are shown e.g. near group[special=file] elements
  80. *
  81. * @var boolean
  82. */
  83. protected $fileUploadEnabled = FALSE;
  84. /**
  85. * The page renderer object
  86. *
  87. * @var t3lib_PageRenderer
  88. */
  89. protected $pageRenderer;
  90. /**
  91. * Whether or not the RTE is enabled.
  92. *
  93. * @var boolean
  94. */
  95. protected $RteEnabled;
  96. /**
  97. * Counter of all RTE elements on this form
  98. *
  99. * @var integer
  100. */
  101. protected $RTEcounter = 0;
  102. protected $readOnly = FALSE;
  103. /**
  104. * @var boolean
  105. */
  106. protected $clickmenuEnabled = FALSE;
  107. protected $doSaveFieldName = '';
  108. /**
  109. * Triggers loading the Javascript file with the md5 hash algorithm implementation
  110. * @boolean
  111. */
  112. protected $loadMd5Javascript = TRUE;
  113. /**
  114. * This objects top-level context (i.e., the root of the object tree this form belongs to
  115. *
  116. * @var t3lib_TCEforms_Context
  117. */
  118. protected $contextObject;
  119. /**
  120. * The fields to hide on this form. This is a two-dimensional array, the first level are table
  121. * names, the second are the field names on this table.
  122. *
  123. * @var array
  124. */
  125. protected $hiddenFields = array();
  126. /**
  127. * Code to render into the form for hidden fields.
  128. *
  129. * @var array
  130. */
  131. protected $hiddenFieldsHtmlCode = array();
  132. protected static $cachedTSconfig;
  133. /**
  134. * The inline elements used in this form (and all subforms).
  135. *
  136. * @var array
  137. */
  138. protected $inlineElementObjects = array();
  139. /**
  140. * @var Tx_Fluid_View_StandaloneView
  141. */
  142. protected $view;
  143. // TODO implement variable defaultStyle + getter/setter (replacement for defStyle of old tceforms)
  144. public function __construct() {
  145. t3lib_div::devLog('Instantiated new TCEforms form.', 't3lib_TCEforms', t3lib_div::SYSLOG_SEVERITY_INFO);
  146. // TODO: make this adjustable!
  147. $this->formName = 'editform';
  148. $this->setFormFieldNamePrefix('data');//$this->TCEformsObject->prependFormFieldNames;
  149. $this->setFormFieldIdPrefix('data');
  150. $this->setElementIdentifierPrefix('data');
  151. $this->contextObject = $this;
  152. }
  153. /**
  154. * Sets the stack that is required for proper element identifier generation.
  155. *
  156. * @param array $elementIdentifierStack
  157. * @return t3lib_TCEforms_Form
  158. */
  159. public function setElementIdentifierStack(array $elementIdentifierStack) {
  160. $this->elementIdentifierStack = $elementIdentifierStack;
  161. return $this;
  162. }
  163. /**
  164. * Sets the prefix for all element identifiers inside this TCEforms context.
  165. *
  166. * @param string $elementIdentifierPrefix
  167. * @return t3lib_TCEforms_Form
  168. */
  169. public function setElementIdentifierPrefix($elementIdentifierPrefix) {
  170. $this->elementIdentifierPrefix = $elementIdentifierPrefix;
  171. return $this;
  172. }
  173. private function _createElementIdentifier_callback_name(array $stackEntry) {
  174. return '[' . implode('][', $stackEntry) . ']';
  175. }
  176. private function _createElementIdentifier_callback_id(array $stackEntry) {
  177. return implode('-', $stackEntry);
  178. }
  179. /**
  180. * Creates an identifier for an element from a given element identifier stack.
  181. *
  182. * @param object $object The element the identifier should be generated for
  183. * @param string $type 'name': all parts wrapped in []; 'id': elements separated by '-'
  184. * @return string
  185. */
  186. public function createElementIdentifier($object, $type) {
  187. $elementIdentifier = $this->elementIdentifierPrefix;
  188. $elementIdentifierStack = $object->getElementIdentifierStack();
  189. switch($type) {
  190. case 'name':
  191. if (count($elementIdentifierStack) > 0) {
  192. $elementIdentifier .= implode('', array_map(array($this, '_createElementIdentifier_callback_name'), $elementIdentifierStack));
  193. }
  194. break;
  195. case 'id':
  196. $elementIdentifier .= implode('', array_map(array($this, '_createElementIdentifier_callback_id'), $elementIdentifierStack));
  197. break;
  198. }
  199. return $elementIdentifier;
  200. }
  201. public function init() {
  202. $this->pageRenderer = $GLOBALS['SOBE']->doc->getPageRenderer();
  203. $this->view = t3lib_div::makeInstance('Tx_Fluid_View_StandaloneView');
  204. $this->view->setTemplatePathAndFilename(PATH_typo3 . 'templates/tceforms/backendform.html');
  205. $this->view->assign('context', $this->contextObject);
  206. }
  207. public function render() {
  208. t3lib_div::devLog('Started rendering TCEforms form.', 't3lib_TCEforms', t3lib_div::SYSLOG_SEVERITY_INFO);
  209. $this->view->assign('records', $this->recordObjects);
  210. $content = $this->view->render();
  211. return $content;
  212. }
  213. public function addRecord($table, $record) {
  214. t3lib_div::devLog('Added record ' . $table . ':' . $record['uid'] . ' to TCEforms form.', 't3lib_TCEforms', t3lib_div::SYSLOG_SEVERITY_INFO);
  215. if (!isset($GLOBALS['TCA'][$table])) {
  216. t3lib_div::loadTCA($table);
  217. }
  218. /** @var $resolver t3lib_TCA_DataStructure_TCAResolver */
  219. $resolver = t3lib_div::makeInstance('t3lib_TCA_DataStructure_TCAResolver');
  220. $dataStructure = $resolver->resolveDataStructure($table);
  221. // TODO move this to a more appropriate place
  222. $GLOBALS['LANG']->loadSingleTableDescription($table);
  223. $recordObject = new t3lib_TCEforms_Record($table, $record, $dataStructure);
  224. if (count($this->fieldList) > 0) {
  225. $recordObject->setFieldList($this->fieldList);
  226. }
  227. $recordObject->setParentFormObject($this)
  228. ->setContextObject($this->contextObject)
  229. ->setElementIdentifierStack($this->elementIdentifierStack)
  230. ->init();
  231. $this->recordObjects[] = $recordObject;
  232. return $recordObject;
  233. }
  234. /**
  235. * @deprecated
  236. */
  237. public function getFormFieldNamePrefix() {
  238. return $this->formFieldNamePrefix;
  239. }
  240. /**
  241. * @deprecated
  242. */
  243. public function setFormFieldNamePrefix($prefix) {
  244. $this->formFieldNamePrefix = $prefix;
  245. $this->formFieldFileNamePrefix = $prefix;
  246. return $this;
  247. }
  248. /**
  249. * @deprecated
  250. */
  251. public function getFormFieldIdPrefix() {
  252. return $this->formFieldIdPrefix;
  253. }
  254. /**
  255. * @deprecated
  256. */
  257. public function setFormFieldIdPrefix($prefix) {
  258. $this->formFieldIdPrefix = $prefix;
  259. }
  260. /**
  261. * Registers fields from a table to be hidden in the form. Their values will be passed via
  262. * hidden form fields.
  263. *
  264. * @param string $table
  265. * @param array $fields
  266. * @return void
  267. */
  268. public function registerHiddenFields($table, array $fields) {
  269. $this->hiddenFields[$table] = t3lib_div::array_merge((array)$this->hiddenFields[$table], $fields);
  270. }
  271. /**
  272. * Returns TRUE if the specified field will be hidden on the form. The field value will be passed
  273. * via a hidden HTML field.
  274. *
  275. * @param string $table
  276. * @param string $fieldName
  277. * @return boolean
  278. */
  279. public function isFieldHidden($table, $fieldName) {
  280. if (!isset($this->hiddenFields[$table])) {
  281. return FALSE;
  282. }
  283. return in_array($fieldName, $this->hiddenFields[$table]);
  284. }
  285. /**
  286. * Registers an IRRE object with the context object
  287. *
  288. * @param t3lib_TCEforms_IrreForm $inlineElementObject
  289. * @return void
  290. */
  291. public function registerInlineElement(t3lib_TCEforms_IrreForm $inlineElementObject) {
  292. $this->inlineElementObjects[] = $inlineElementObject;
  293. }
  294. /**
  295. * Returns TRUE if any IRRE elements have been registered for the form.
  296. *
  297. * @return boolean
  298. */
  299. public function hasInlineElements() {
  300. return (count($this->inlineElementObjects) > 0);
  301. }
  302. /**
  303. * Returns necessary JavaScript for the top
  304. *
  305. * @return string A <script></script> section with JavaScript.
  306. */
  307. public function renderJavascriptBeforeForm() {
  308. $out = '';
  309. // Additional top HTML:
  310. if (count($this->additionalCodePreForm)) {
  311. $out.= implode('
  312. <!-- NEXT: -->
  313. ',$this->additionalCodePreForm);
  314. }
  315. // Additional top JavaScript
  316. if (count($this->additionalJSPreForm)) {
  317. $out.='
  318. <!--
  319. JavaScript in top of page (before form):
  320. -->
  321. <script type="text/javascript">
  322. /*<![CDATA[*/
  323. '.implode('
  324. // NEXT:
  325. ',$this->additionalJSPreForm).'
  326. /*]]>*/
  327. </script>
  328. ';
  329. }
  330. return $out;
  331. }
  332. public function renderJavascriptAfterForm($formname='forms[0]') {
  333. $elements = array();
  334. // TODO: use $this->formName instead (as soon as there are getters/setters for it
  335. $formname = $this->formName;
  336. // required:
  337. //foreach ($this->sheetObjects as $sheet) {
  338. foreach ($this->requiredFields as $itemImgName => $itemName) {
  339. $match = array();
  340. if (preg_match('/^(.+)\[((\w|\d|_)+)\]$/', $itemName, $match)) {
  341. $record = $match[1];
  342. $field = $match[2];
  343. $elements[$record][$field]['required'] = 1;
  344. $elements[$record][$field]['requiredImg'] = $itemImgName;
  345. if (isset($this->requiredAdditional[$itemName]) && is_array($this->requiredAdditional[$itemName])) {
  346. $elements[$record][$field]['additional'] = $this->requiredAdditional[$itemName];
  347. }
  348. }
  349. }
  350. // range:
  351. foreach ($this->rangeFields as $itemName => $range) {
  352. if (preg_match('/^(.+)\[((\w|\d|_)+)\]$/', $itemName, $match)) {
  353. $record = $match[1];
  354. $field = $match[2];
  355. $elements[$record][$field]['range'] = array($range[0], $range[1]);
  356. $elements[$record][$field]['rangeImg'] = $range['imgName'];
  357. }
  358. }
  359. //}
  360. $javaScriptFiles = $this->includeJavascriptFiles();
  361. $out .= $this->javascriptForUpdate($formname);
  362. $this->addToTBE_EDITOR_fieldChanged_func('TBE_EDITOR.fieldChanged_fName(fName,formObj[fName+"_list"]);');
  363. // add JS required for inline fields
  364. if (count($this->inlineElementObjects)) {
  365. $inlineData = array();
  366. foreach ($this->inlineElementObjects as $inlineElement) {
  367. $inlineData = t3lib_div::array_merge_recursive_overrule($inlineData, $inlineElement->getInlineData());
  368. }
  369. $out .= '
  370. inline.addToDataArray(' . json_encode($inlineData) . ');
  371. ';
  372. }
  373. // Registered nested elements for tabs or inline levels:
  374. if (count($this->requiredNested)) {
  375. $out .= '
  376. TBE_EDITOR.addNested(' . json_encode($this->requiredNested) . ');
  377. ';
  378. }
  379. // elements which are required or have a range definition:
  380. if (count($elements)) {
  381. $out .= '
  382. TBE_EDITOR.addElements(' . json_encode($elements) . ');
  383. TBE_EDITOR.initRequired();
  384. ';
  385. }
  386. // $this->additionalJS_submit:
  387. if ($this->additionalJS_submit) {
  388. $additionalJS_submit = implode('', $this->additionalJS_submit);
  389. $additionalJS_submit = str_replace("\r", '', $additionalJS_submit);
  390. $additionalJS_submit = str_replace("\n", '', $additionalJS_submit);
  391. $out .= '
  392. TBE_EDITOR.addActionChecks("submit", "'.addslashes($additionalJS_submit).'");
  393. ';
  394. }
  395. $out .= chr(10) . implode(chr(10), $this->additionalJSPostForm) . chr(10) .
  396. $this->JScode['evaluation'] . $this->JScode['validation'];
  397. $out .= '
  398. TBE_EDITOR.loginRefreshed();
  399. ';
  400. // Regular direct output:
  401. if (!$update) {
  402. $out = $spacer . implode($spacer, $javaScriptFiles) . t3lib_div::wrapJS($out);
  403. }
  404. $out .= '
  405. <!--
  406. JavaScript after the form has been drawn:
  407. -->
  408. <script type="text/javascript">
  409. /*<![CDATA[*/
  410. formObj = document.forms[0]
  411. backPath = "'.$this->backPath.'";
  412. function TBE_EDITOR_fieldChanged_func(fName, formObj) {
  413. '.$this->TBE_EDITOR_fieldChanged_func.'
  414. }
  415. /*]]>*/
  416. </script>';
  417. return $out;
  418. }
  419. protected function javascriptForUpdate($formname) {
  420. // if IRRE fields were processed, add the JavaScript functions:
  421. if ($this->inline->inlineCount) {
  422. $out .= '
  423. inline.setPrependFormFieldNames("' . $this->inline->prependNaming . '");
  424. inline.setNoTitleString("' . addslashes(t3lib_BEfunc::getNoRecordTitle(true)) . '");
  425. ';
  426. }
  427. // Toggle icons:
  428. $toggleIcon_open = t3lib_iconWorks::getSpriteIcon('actions-move-down');
  429. $toggleIcon_close = t3lib_iconWorks::getSpriteIcon('actions-move-right');
  430. $out .= '
  431. var toggleIcon_open = \'' . $toggleIcon_open . '\';
  432. var toggleIcon_close = \'' . $toggleIcon_close . '\';
  433. TBE_EDITOR.images.req.src = "' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/required_h.gif', '', 1) . '";
  434. TBE_EDITOR.images.cm.src = "' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/content_client.gif', '', 1) . '";
  435. TBE_EDITOR.images.sel.src = "' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/content_selected.gif', '', 1) . '";
  436. TBE_EDITOR.images.clear.src = "' . $this->backPath . 'clear.gif";
  437. TBE_EDITOR.auth_timeout_field = ' . intval($GLOBALS['BE_USER']->auth_timeout_field) . ';
  438. TBE_EDITOR.formname = "' . $formname . '";
  439. TBE_EDITOR.formnameUENC = "' . rawurlencode($formname) . '";
  440. TBE_EDITOR.backPath = "' . addslashes($this->backPath) . '";
  441. TBE_EDITOR.prependFormFieldNames = "'.$this->formFieldNamePrefix . '";
  442. TBE_EDITOR.prependFormFieldNamesUENC = "'.rawurlencode($this->formFieldNamePrefix) . '";
  443. TBE_EDITOR.prependFormFieldNamesCnt = ' . substr_count($this->formFieldNamePrefix, '[') . ';
  444. TBE_EDITOR.isPalettedoc = ' . ($this->isPalettedoc ? addslashes($this->isPalettedoc) : 'null') . ';
  445. TBE_EDITOR.doSaveFieldName = "' . ($this->doSaveFieldName ? addslashes($this->doSaveFieldName) : '') . '";
  446. TBE_EDITOR.labels.fieldsChanged = ' . $GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.fieldsChanged')) . ';
  447. TBE_EDITOR.labels.fieldsMissing = ' . $GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.fieldsMissing')) . ';
  448. TBE_EDITOR.labels.refresh_login = ' . $GLOBALS['LANG']->JScharCode(t3lib_TCEforms_Helper::getLL('m_refresh_login')) . ';
  449. TBE_EDITOR.labels.onChangeAlert = ' . $GLOBALS['LANG']->JScharCode(t3lib_TCEforms_Helper::getLL('m_onChangeAlert')) . ';
  450. evalFunc.USmode = ' . ($GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat']?'1':'0').';
  451. TBE_EDITOR.backend_interface = "' . $GLOBALS['BE_USER']->uc['interfaceSetup'] . '";
  452. ';
  453. // needed for tceform manipulation (date picker)
  454. $typo3Settings = array(
  455. 'datePickerUSmode' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? 1 : 0,
  456. 'dateFormat' => array('j-n-Y', 'G:i j-n-Y'),
  457. 'dateFormatUS' => array('n-j-Y', 'G:i n-j-Y'),
  458. );
  459. $out .= $this->pageRenderer->addInlineSettingArray('', $typo3Settings);
  460. return $out;
  461. }
  462. protected function includeJavascriptFiles() {
  463. $jsFile = array();
  464. if ($this->loadMd5Javascript) {
  465. $jsFile[] = '<script type="text/javascript" src="' . $this->backPath . 'md5.js"></script>';
  466. }
  467. $this->pageRenderer->loadPrototype();
  468. $this->pageRenderer->loadExtJS();
  469. $this->pageRenderer->loadScriptaculous();
  470. $GLOBALS['SOBE']->doc->loadJavascriptLib('../t3lib/jsfunc.evalfield.js');
  471. if (!($GLOBALS['BE_USER']->uc['resizeTextareas'] == '0' && $GLOBALS['BE_USER']->uc['resizeTextareas_Flexible'] == '0')) {
  472. $this->pageRenderer->addCssFile($this->backPath . '../t3lib/js/extjs/ux/resize.css');
  473. $GLOBALS['SOBE']->doc->loadJavascriptLib('../t3lib/js/extjs/ux/ext.resizable.js');
  474. }
  475. $resizableSettings = array(
  476. 'textareaMaxHeight' => $GLOBALS['BE_USER']->uc['resizeTextareas_MaxHeight'] >0 ? $GLOBALS['BE_USER']->uc['resizeTextareas_MaxHeight'] : '600',
  477. 'textareaFlexible' => (!$GLOBALS['BE_USER']->uc['resizeTextareas_Flexible'] == '0'),
  478. 'textareaResize' => (!$GLOBALS['BE_USER']->uc['resizeTextareas'] == '0'),
  479. );
  480. $this->pageRenderer->addInlineSettingArray('', $resizableSettings);
  481. $GLOBALS['SOBE']->doc->loadJavascriptLib('jsfunc.tbe_editor.js');
  482. $GLOBALS['SOBE']->doc->loadJavascriptLib('js/tceforms.js');
  483. $GLOBALS['SOBE']->doc->loadJavascriptLib('../t3lib/js/extjs/tceforms.js');
  484. // if IRRE fields were processed, add the JavaScript functions:
  485. if ($this->hasInlineElements()) {
  486. $GLOBALS['SOBE']->doc->loadJavascriptLib('../t3lib/jsfunc.inline.js');
  487. }
  488. return $jsFile;
  489. }
  490. /**
  491. * Sets the global status of all palettes to collapsed/uncollapsed
  492. *
  493. * @param boolean $collapsed
  494. */
  495. public function setPalettesCollapsed($collapsed) {
  496. $this->palettesCollapsed = (bool)$collapsed;
  497. return $this;
  498. }
  499. /**
  500. * Returns whether or not the palettes are collapsed
  501. *
  502. * @return boolean
  503. */
  504. public function getPalettesCollapsed() {
  505. return $this->palettesCollapsed;
  506. }
  507. /**
  508. * Limits the display of records in this form to a list of fields.
  509. *
  510. * @param array $fieldList The list of fields to display. Either a comma separated list or an array of comma separated lists (for multiple tables)
  511. * @return void
  512. */
  513. public function setFieldList($fieldList) {
  514. if (is_array($fieldList)) {
  515. $this->fieldList = array();
  516. foreach ($fieldList as $table => $fields) {
  517. $this->fieldList[$table] = array_unique(t3lib_div::trimExplode(',', $fields, 1));
  518. }
  519. } else {
  520. $this->fieldList = array_unique(t3lib_div::trimExplode(',', $fieldList, 1));
  521. }
  522. return $this;
  523. }
  524. /**
  525. * Returns a list of fields to display for a record
  526. *
  527. * @return array
  528. *
  529. * @TODO Check if we should use the table as a parameter here
  530. */
  531. public function getFieldList() {
  532. return $this->fieldList;
  533. }
  534. public function addHtmlForHiddenField($elementName, $code) {
  535. // TODO: handle already set keys here
  536. $this->hiddenFieldsHtmlCode[$elementName] = $code;
  537. }
  538. public function getHtmlForHiddenFields() {
  539. return implode("\n", $this->hiddenFieldsHtmlCode);
  540. }
  541. /********************************************
  542. *
  543. * Template functions
  544. *
  545. ********************************************/
  546. /**
  547. * Sets the path to the template file. Also automatically loads the contents of this file.
  548. * It may be accessed via getTemplateContent()
  549. *
  550. * @param string $filePath
  551. */
  552. public function setTemplateFile($filePath) {
  553. $filePath = t3lib_div::getFileAbsFileName($filePath);
  554. if (!@file_exists($filePath)) {
  555. die('Template file <em>' . $filePath . '</em> does not exist. [1216911730]');
  556. }
  557. $this->templateContent = file_get_contents($filePath);
  558. return $this;
  559. }
  560. public function getTemplateContent() {
  561. return $this->templateContent;
  562. }
  563. /**
  564. * Create dynamic tab menu
  565. *
  566. * @param array Parts for the tab menu, fed to template::getDynTabMenu()
  567. * @param string ID string for the tab menu
  568. * @param integer If set to '1' empty tabs will be removed, If set to '2' empty tabs will be disabled
  569. * @return string HTML for the menu
  570. */
  571. protected function getDynTabMenu($parts, $idString, $dividersToTabsBehaviour = 1) {
  572. if (is_object($GLOBALS['TBE_TEMPLATE'])) {
  573. $GLOBALS['TBE_TEMPLATE']->backPath = $this->backPath;
  574. return $GLOBALS['TBE_TEMPLATE']->getDynTabMenu($parts, $idString, 0, false, 50, 1, false, 1, $dividersToTabsBehaviour);
  575. } else {
  576. $output = '';
  577. foreach($parts as $singlePad) {
  578. $output .= '
  579. <h3>' . htmlspecialchars($singlePad['label']) . '</h3>
  580. ' . ($singlePad['description'] ? '<p class="c-descr">' . nl2br(htmlspecialchars($singlePad['description'])) . '</p>' : '') . '
  581. ' . $singlePad['content'];
  582. }
  583. return '<div class="typo3-dyntabmenu-divs">' . $output . '</div>';
  584. }
  585. }
  586. /**
  587. * Renders a record object into a HTML form.
  588. *
  589. * @param t3lib_TCEforms_Record $recordObject
  590. * @return string The rendered record form, ready to be put on a page
  591. */
  592. protected function renderRecordObject(t3lib_TCEforms_Record $recordObject) {
  593. global $TCA;
  594. $recordContent = $recordObject->render();
  595. return $recordContent . implode('', $this->getHtmlForHiddenFields());
  596. }
  597. /**
  598. * Returns element reference for form element name
  599. *
  600. * @param string Form element name
  601. * @return string Form element reference (JS)
  602. */
  603. // TODO: check compatibility with nested forms
  604. public function elName($itemName) {
  605. return 'document.' . $this->formName . "['" . $itemName . "']";
  606. }
  607. /**
  608. * Returns 'this.blur();' string, if supported.
  609. *
  610. * @return string If the current browser supports styles, the string 'this.blur();' is returned.
  611. */
  612. // TODO: move to generic helper class, make static
  613. public function blur() {
  614. return $GLOBALS['CLIENT']['FORMSTYLE'] ? 'this.blur();' : '';
  615. }
  616. /**
  617. * Returns true if descriptions should be loaded always
  618. *
  619. * @param string Table for which to check
  620. * @return boolean
  621. */
  622. public function doLoadTableDescription($table) {
  623. global $TCA;
  624. return $TCA[$table]['interface']['always_description'];
  625. }
  626. /********************************************
  627. *
  628. * Localization functions
  629. *
  630. ********************************************/
  631. /**
  632. * Fetches language label for key
  633. *
  634. * @param string Language label reference, eg. 'LLL:EXT:lang/locallang_core.php:labels.blablabla'
  635. * @return string The value of the label, fetched for the current backend language.
  636. */
  637. // TODO: refactor the method name
  638. protected function sL($str) {
  639. return $GLOBALS['LANG']->sL($str);
  640. }
  641. /**
  642. * Returns the "returnUrl" of the form. Can be set externally or will be taken from "t3lib_div::linkThisScript()"
  643. *
  644. * @return string Return URL of current script
  645. */
  646. function thisReturnUrl() {
  647. return $this->returnUrl ? $this->returnUrl : t3lib_div::linkThisScript();
  648. }
  649. /********************************************
  650. *
  651. * JavaScript related functions
  652. *
  653. ********************************************/
  654. // TODO: move to context class/interface
  655. /**
  656. * Adds JavaScript code for form field evaluation. Used to be the global var extJSCode in old t3lib_TCEforms
  657. *
  658. * @param string $JScode
  659. */
  660. public function addToEvaluationJS($JScode) {
  661. $this->JScode['evaluation'] .= $JScode;
  662. }
  663. /**
  664. * Returns the Javascript code used for form evaluation
  665. *
  666. * @return string
  667. */
  668. public function getEvaluationJS() {
  669. return $this->JScode['evaluation'];
  670. }
  671. public function addToValidationJavascriptCode($JScode) {
  672. $this->JScode['validation'] .= $JScode;
  673. }
  674. public function addToTBE_EDITOR_fieldChanged_func($JScode) {
  675. $this->TBE_EDITOR_fieldChanged_func .= $JScode;
  676. }
  677. ////////////////////////////////////////////////////////
  678. /**
  679. * Takes care of registering required fields
  680. *
  681. * @param string $name: The name of the form field
  682. * @param string $value:
  683. * @return void
  684. */
  685. public function registerRequiredField($name, $value) {
  686. $this->requiredFields[$name] = $value;
  687. // requiredFields have name/value swapped! For backward compatibility we keep this:
  688. $itemName = $value;
  689. // Set the situation of nesting for the current field:
  690. //$this->registerNestedElement($itemName);
  691. }
  692. /**
  693. * Takes care of registering a required range for a field
  694. *
  695. * @param string $name: The name of the form field
  696. * @param array $value:
  697. * @return void
  698. */
  699. public function registerRequiredFieldRange($name, array $value) {
  700. $this->rangeFields[$name] = $value;
  701. $itemName = $name;
  702. // Set the situation of nesting for the current field:
  703. //$this->registerNestedElement($itemName);
  704. }
  705. public function getFormName() {
  706. return $this->formName;
  707. }
  708. public function setBackpath($backpath) {
  709. $this->backPath = $backpath;
  710. return $this;
  711. }
  712. public function getBackpath() {
  713. return $this->backPath;
  714. }
  715. /**
  716. * Sets the object this form is in context of
  717. *
  718. * @param t3lib_TCEforms_Form $contextObject The object on top of the page tree
  719. * @return t3lib_TCEforms_Form This form object
  720. */
  721. public function setContextObject(t3lib_TCEforms_Context $contextObject) {
  722. $this->contextObject = $contextObject;
  723. return $this;
  724. }
  725. public function isHelpGloballyShown() {
  726. // TODO use config option here and add setter
  727. return TRUE;
  728. }
  729. public function setEditFieldHelpMode($mode) {
  730. $this->editFieldHelpMode = $mode;
  731. return $this;
  732. }
  733. public function getEditFieldHelpMode() {
  734. return $this->editFieldHelpMode;
  735. }
  736. public function setRteEnabled($enabled) {
  737. $this->RteEnabled = $enabled;
  738. return $this;
  739. }
  740. public function isRteEnabled() {
  741. return $this->RteEnabled;
  742. }
  743. public function addToAdditionalCodePreForm($key, $code) {
  744. if ($key != '') {
  745. $this->additionalCodePreForm[$key] = $code;
  746. } else {
  747. $this->additionalCodePreForm[] = $code;
  748. }
  749. }
  750. public function addToAdditionalJSPreForm($key, $code) {
  751. if ($key != '') {
  752. $this->additionalJSPreForm[$key] = $code;
  753. } else {
  754. $this->additionalJSPreForm[] = $code;
  755. }
  756. }
  757. public function addToAdditionalJSPostForm($key, $code) {
  758. if ($key != '') {
  759. $this->additionalJSPostForm[$key] = $code;
  760. } else {
  761. $this->additionalJSPostForm[] = $code;
  762. }
  763. }
  764. public function registerRTEWindow($itemName) {
  765. //
  766. }
  767. // TODO: turn this into a proper handler for a new RTE instance
  768. public function registerRTEinstance() {
  769. ++$this->RTEcounter;
  770. }
  771. public function getRTEcounter() {
  772. return $this->RTEcounter;
  773. }
  774. /*public function __set($key, $value) {
  775. throw new Exception('Write access to protected var '.$key);
  776. }
  777. public function __get($key) {
  778. throw new Exception('Read access to protected var '.$key);
  779. }*/
  780. public function setReadOnly($readOnly) {
  781. $this->readOnly = $readOnly;
  782. return $this;
  783. }
  784. public function isReadOnly() {
  785. return $this->readOnly;
  786. }
  787. public function setDoSaveFieldName($fieldname) {
  788. $this->doSaveFieldName = $fieldname;
  789. return $this;
  790. }
  791. public function getDoSaveFieldName() {
  792. return $this->doSaveFieldName;
  793. }
  794. /**
  795. * @param boolean $clickmenuEnabled
  796. *
  797. * @TODO add to Context interface
  798. */
  799. public function setClickmenuEnabled($clickmenuEnabled) {
  800. $this->clickmenuEnabled = $clickmenuEnabled;
  801. return $this;
  802. }
  803. /**
  804. * @return boolean
  805. *
  806. * @TODO add to Context interface
  807. */
  808. public function isClickmenuEnabled() {
  809. return $this->clickmenuEnabled;
  810. }
  811. /**
  812. * Enables/disables the file upload elements at some fields
  813. *
  814. * @param boolean $fileUploadEnabled
  815. *
  816. * @TODO add to Context interface
  817. */
  818. public function setFileUploadEnabled($fileUploadEnabled) {
  819. $this->fileUploadEnabled = $fileUploadEnabled;
  820. return $this;
  821. }
  822. /**
  823. * @return boolean
  824. *
  825. * @TODO add to Context interface
  826. */
  827. public function isFileUploadEnabled() {
  828. return $this->fileUploadEnabled;
  829. }
  830. /**
  831. * Returns an array of available languages (to use for FlexForms)
  832. *
  833. * @param boolean If set, only languages which are paired with a static_info_table / static_language record will be returned.
  834. * @param boolean If set, an array entry for a default language is set.
  835. * @return array
  836. */
  837. public function getAvailableLanguages($onlyIsoCoded = TRUE, $setDefault = TRUE) {
  838. $isL = t3lib_extMgm::isLoaded('static_info_tables');
  839. // Find all language records in the system:
  840. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('static_lang_isocode, title, uid', 'sys_language', 'pid=0 AND hidden=0'.t3lib_BEfunc::deleteClause('sys_language'), '', 'title');
  841. // Traverse them:
  842. $output = array();
  843. if ($setDefault) {
  844. $output[0] = array(
  845. 'uid' => 0,
  846. 'title' => 'Default language',
  847. 'ISOcode' => 'DEF'
  848. );
  849. }
  850. while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
  851. $output[$row['uid']] = $row;
  852. if ($isL && $row['static_lang_isocode']) {
  853. $rr = t3lib_BEfunc::getRecord('static_languages',$row['static_lang_isocode'],'lg_iso_2');
  854. if ($rr['lg_iso_2']) {
  855. $output[$row['uid']]['ISOcode']=$rr['lg_iso_2'];
  856. }
  857. }
  858. if ($onlyIsoCoded && !$output[$row['uid']]['ISOcode']) {
  859. unset($output[$row['uid']]);
  860. }
  861. }
  862. return $output;
  863. }
  864. /**
  865. * Returns TSconfig for table/row
  866. * 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.
  867. *
  868. * @param string The table name
  869. * @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.)
  870. * @param string Optionally you can specify the field name as well. In that case the TSconfig for the field is returned.
  871. * @return mixed The TSconfig values (probably in an array)
  872. * @see t3lib_BEfunc::getTCEFORM_TSconfig()
  873. */
  874. public static function getTSconfig($table, $row, $field='') {
  875. $mainKey = $table.':'.$row['uid'];
  876. if (!isset(self::$cachedTSconfig[$mainKey])) {
  877. self::$cachedTSconfig[$mainKey] = t3lib_BEfunc::getTCEFORM_TSconfig($table, $row);
  878. }
  879. if ($field) {
  880. return self::$cachedTSconfig[$mainKey][$field];
  881. } else {
  882. return self::$cachedTSconfig[$mainKey];
  883. }
  884. }
  885. public function getNestedStackEntry() {
  886. return false;
  887. }
  888. }
  889. ?>