[TASK] FormEngine: Simplify element name resolving
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / AbstractNode.php
1 <?php
2 namespace TYPO3\CMS\Backend\Form;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Utility\ArrayUtility;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19
20 /**
21 * Base class for container and single elements - their abstracts extend from here.
22 */
23 abstract class AbstractNode {
24
25 /**
26 * A list of global options given from parent to child elements
27 *
28 * @var array
29 */
30 protected $globalOptions = array();
31
32 /**
33 * Handler for single nodes
34 *
35 * @return array As defined in initializeResultArray() of AbstractNode
36 */
37 abstract public function render();
38
39 /**
40 * Set global options from parent instance
41 *
42 * @param array $globalOptions Global options like 'readonly' for all elements
43 * @return $this
44 */
45 public function setGlobalOptions(array $globalOptions) {
46 $this->globalOptions = $globalOptions;
47 return $this;
48 }
49
50 /**
51 * Initialize the array that is returned to parent after calling. This structure
52 * is identical for *all* nodes. Parent will merge the return of a child with its
53 * own stuff and in itself return an array of the same structure.
54 *
55 * @return array
56 */
57 protected function initializeResultArray() {
58 return array(
59 'requiredElements' => array(), // name => value
60 'requiredFields' => array(), // value => name
61 'requiredAdditional' => array(), // name => array
62 'requiredNested' => array(),
63 'additionalJavaScriptPost' => array(),
64 'additionalJavaScriptSubmit' => array(),
65 'additionalHiddenFields' => array(),
66 'additionalHeadTags' => array(),
67 'extJSCODE' => '',
68 'inlineData' => array(),
69 'html' => '',
70 );
71 }
72
73 /**
74 * Merge existing data with a child return array
75 *
76 * @param array $existing Currently merged array
77 * @param array $childReturn Array returned by child
78 * @return array Result array
79 */
80 protected function mergeChildReturnIntoExistingResult(array $existing, array $childReturn) {
81 if (!empty($childReturn['html'])) {
82 $existing['html'] .= LF . $childReturn['html'];
83 }
84 if (!empty($childReturn['extJSCODE'])) {
85 $existing['extJSCODE'] .= LF . $childReturn['extJSCODE'];
86 }
87 foreach ($childReturn['requiredElements'] as $name => $value) {
88 $existing['requiredElements'][$name] = $value;
89 }
90 foreach ($childReturn['requiredFields'] as $value => $name) { // Params swapped ?!
91 $existing['requiredFields'][$value] = $name;
92 }
93 foreach ($childReturn['requiredAdditional'] as $name => $subArray) {
94 $existing['requiredAdditional'][$name] = $subArray;
95 }
96 foreach ($childReturn['requiredNested'] as $value => $name) {
97 $existing['requiredNested'][$value] = $name;
98 }
99 foreach ($childReturn['additionalJavaScriptPost'] as $value) {
100 $existing['additionalJavaScriptPost'][] = $value;
101 }
102 foreach ($childReturn['additionalJavaScriptSubmit'] as $value) {
103 $existing['additionalJavaScriptSubmit'][] = $value;
104 }
105 foreach ($childReturn['additionalHiddenFields'] as $value) {
106 $existing['additionalHiddenFields'][] = $value;
107 }
108 foreach ($childReturn['additionalHeadTags'] as $value) {
109 $existing['additionalHeadTags'][] = $value;
110 }
111 if (!empty($childReturn['inlineData'])) {
112 $existingInlineData = $existing['inlineData'];
113 $childInlineData = $childReturn['inlineData'];
114 ArrayUtility::mergeRecursiveWithOverrule($existingInlineData, $childInlineData);
115 $existing['inlineData'] = $existingInlineData;
116 }
117 return $existing;
118 }
119
120 /**
121 * Determine and get the value for the placeholder for an input field.
122 * Typically used in an inline relation where values from fields down the record chain
123 * are used as "default" values for fields.
124 *
125 * @param string $table
126 * @param array $config
127 * @param array $row
128 * @return mixed
129 */
130 protected function getPlaceholderValue($table, array $config, array $row) {
131 $value = trim($config['placeholder']);
132 if (!$value) {
133 return '';
134 }
135 // Check if we have a reference to another field value from the current record
136 if (substr($value, 0, 6) === '__row|') {
137 /** @var FormDataTraverser $traverser */
138 $traverseFields = GeneralUtility::trimExplode('|', substr($value, 6));
139 $traverser = GeneralUtility::makeInstance(FormDataTraverser::class);
140 $value = $traverser->getTraversedFieldValue($traverseFields, $table, $row, $this->globalOptions['inlineFirstPid']);
141 }
142
143 return $value;
144 }
145
146 }