[TASK] Correct isTargetRenderType for FormDataProviders
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / FormDataProvider / TcaSelectTreeItems.php
1 <?php
2 namespace TYPO3\CMS\Backend\Form\FormDataProvider;
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\Backend\Form\FormDataProviderInterface;
18 use TYPO3\CMS\Core\Tree\TableConfiguration\ExtJsArrayTreeRenderer;
19 use TYPO3\CMS\Core\Tree\TableConfiguration\TableConfigurationTree;
20 use TYPO3\CMS\Core\Tree\TableConfiguration\TreeDataProviderFactory;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22
23 /**
24 * Resolve select items, set processed item list in processedTca, sanitize and resolve database field
25 */
26 class TcaSelectTreeItems extends AbstractItemProvider implements FormDataProviderInterface
27 {
28 /**
29 * Resolve select items
30 *
31 * @param array $result
32 * @return array
33 * @throws \UnexpectedValueException
34 */
35 public function addData(array $result)
36 {
37 $table = $result['tableName'];
38
39 foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfig) {
40 if (empty($fieldConfig['config']['type']) || $fieldConfig['config']['type'] !== 'select') {
41 continue;
42 }
43
44 // Make sure we are only processing supported renderTypes
45 if (!$this->isTargetRenderType($fieldConfig)) {
46 continue;
47 }
48
49 $fieldConfig['config']['items'] = $this->sanitizeItemArray($fieldConfig['config']['items'], $table, $fieldName);
50 $fieldConfig['config']['maxitems'] = $this->sanitizeMaxItems($fieldConfig['config']['maxitems']);
51
52 $fieldConfig['config']['items'] = $this->addItemsFromPageTsConfig($result, $fieldName, $fieldConfig['config']['items']);
53 $fieldConfig['config']['items'] = $this->addItemsFromSpecial($result, $fieldName, $fieldConfig['config']['items']);
54 $fieldConfig['config']['items'] = $this->addItemsFromFolder($result, $fieldName, $fieldConfig['config']['items']);
55 $staticItems = $fieldConfig['config']['items'];
56
57 $fieldConfig['config']['items'] = $this->addItemsFromForeignTable($result, $fieldName, $fieldConfig['config']['items']);
58 $dynamicItems = array_diff_key($fieldConfig['config']['items'], $staticItems);
59
60 $fieldConfig['config']['items'] = $this->removeItemsByKeepItemsPageTsConfig($result, $fieldName, $fieldConfig['config']['items']);
61 $fieldConfig['config']['items'] = $this->removeItemsByRemoveItemsPageTsConfig($result, $fieldName, $fieldConfig['config']['items']);
62 $fieldConfig['config']['items'] = $this->removeItemsByUserLanguageFieldRestriction($result, $fieldName, $fieldConfig['config']['items']);
63 $fieldConfig['config']['items'] = $this->removeItemsByUserAuthMode($result, $fieldName, $fieldConfig['config']['items']);
64 $fieldConfig['config']['items'] = $this->removeItemsByDoktypeUserRestriction($result, $fieldName, $fieldConfig['config']['items']);
65
66 // Resolve "itemsProcFunc"
67 if (!empty($fieldConfig['config']['itemsProcFunc'])) {
68 $fieldConfig['config']['items'] = $this->resolveItemProcessorFunction($result, $fieldName, $fieldConfig['config']['items']);
69 // itemsProcFunc must not be used anymore
70 unset($fieldConfig['config']['itemsProcFunc']);
71 }
72
73 // Translate labels
74 $fieldConfig['config']['items'] = $this->translateLabels($result, $fieldConfig['config']['items'], $table, $fieldName);
75
76 $staticValues = $this->getStaticValues($fieldConfig['config']['items'], $dynamicItems);
77 $result['databaseRow'][$fieldName] = $this->processSelectFieldValue($result, $fieldName, $staticValues);
78
79 // Keys may contain table names, so a numeric array is created
80 $fieldConfig['config']['items'] = array_values($fieldConfig['config']['items']);
81
82 $fieldConfig['config']['treeData'] = $this->renderTree($result, $fieldConfig, $fieldName, $staticItems);
83
84 $result['processedTca']['columns'][$fieldName] = $fieldConfig;
85 }
86
87 return $result;
88 }
89
90 /**
91 * Renders the Ext JS tree.
92 *
93 * @param array $result The current result array.
94 * @param array $fieldConfig The configuration of the current field.
95 * @param string $fieldName The name of the current field.
96 * @param array $staticItems The static items from the field config.
97 * @return array The tree data configuration
98 */
99 protected function renderTree(array $result, array $fieldConfig, $fieldName, array $staticItems)
100 {
101 $allowedUids = [];
102 foreach ($fieldConfig['config']['items'] as $item) {
103 if ((int)$item[1] > 0) {
104 $allowedUids[] = $item[1];
105 }
106 }
107
108 $treeDataProvider = TreeDataProviderFactory::getDataProvider(
109 $fieldConfig['config'],
110 $result['tableName'],
111 $fieldName,
112 $result['databaseRow']
113 );
114 $treeDataProvider->setSelectedList(implode(',', $result['databaseRow'][$fieldName]));
115 $treeDataProvider->setItemWhiteList($allowedUids);
116 $treeDataProvider->initializeTreeData();
117
118 /** @var ExtJsArrayTreeRenderer $treeRenderer */
119 $treeRenderer = GeneralUtility::makeInstance(ExtJsArrayTreeRenderer::class);
120
121 /** @var TableConfigurationTree $tree */
122 $tree = GeneralUtility::makeInstance(TableConfigurationTree::class);
123 $tree->setDataProvider($treeDataProvider);
124 $tree->setNodeRenderer($treeRenderer);
125
126 $treeItems = $this->prepareAdditionalItems($staticItems, $result['databaseRow'][$fieldName]);
127 $treeItems[] = $tree->render();
128
129 $treeConfig = [
130 'items' => $treeItems,
131 'selectedNodes' => $this->prepareSelectedNodes($fieldConfig['config']['items'], $result['databaseRow'][$fieldName])
132 ];
133
134 return $treeConfig;
135 }
136
137 /**
138 * Prepare the additional items that get prepended to the tree as leaves
139 *
140 * @param array $itemArray
141 * @param array $selectedNodes
142 * @return array
143 */
144 protected function prepareAdditionalItems(array $itemArray, array $selectedNodes)
145 {
146 $additionalItems = [];
147
148 foreach ($itemArray as $item) {
149 if ($item[1] === '--div--') {
150 continue;
151 }
152
153 $additionalItems[] = [
154 'uid' => $item[1],
155 'text' => $item[0],
156 'selectable' => true,
157 'leaf' => true,
158 'checked' => in_array($item[1], $selectedNodes),
159 'icon' => $item[3]
160 ];
161 }
162
163 return $additionalItems;
164 }
165
166 /**
167 * Re-create the old pipe based syntax of selected nodes for the ExtJS rendering part
168 *
169 * @param array $itemArray
170 * @param array $databaseValues
171 * @return array
172 * @todo: this is ugly - should be removed with the tree rewrite
173 */
174 protected function prepareSelectedNodes(array $itemArray, array $databaseValues)
175 {
176 $selectedNodes = [];
177 if (!empty($databaseValues)) {
178 foreach ($databaseValues as $selectedNode) {
179 foreach ($itemArray as $possibleSelectBoxItem) {
180 if ((string)$possibleSelectBoxItem[1] === (string)$selectedNode) {
181 $selectedNodes[] = $selectedNode . '|' . rawurlencode($possibleSelectBoxItem[0]);
182 }
183 }
184 }
185 }
186
187 return $selectedNodes;
188 }
189
190 /**
191 * Determines whether the current field is a valid target for this DataProvider
192 *
193 * @param array $fieldConfig
194 * @return bool
195 */
196 protected function isTargetRenderType(array $fieldConfig)
197 {
198 return $fieldConfig['config']['renderType'] === 'selectTree';
199 }
200 }