‪TYPO3CMS  ‪main
TcaSelectTreeItems.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
20 use TYPO3\CMS\Core\Imaging\IconSize;
26 
39 {
46  public function ‪addData(array $result)
47  {
48  $table = $result['tableName'];
49 
50  foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfig) {
51  if (empty($fieldConfig['config']['type']) || $fieldConfig['config']['type'] !== 'select') {
52  continue;
53  }
54 
55  // Make sure we are only processing supported renderTypes
56  if (!$this->‪isTargetRenderType($fieldConfig)) {
57  continue;
58  }
59 
60  $fieldConfig['config']['maxitems'] = ‪MathUtility::forceIntegerInRange($fieldConfig['config']['maxitems'] ?? 0, 0, 99999);
61  if ($fieldConfig['config']['maxitems'] === 0) {
62  $fieldConfig['config']['maxitems'] = 99999;
63  }
64 
65  $fieldConfig = $this->‪parseStartingPointsFromSiteConfiguration($result, $fieldConfig);
66 
67  // A couple of tree specific config parameters can be overwritten via page TS.
68  // Pick those that influence the data fetching and write them into the config
69  // given to the tree data provider. This is additionally used in SelectTreeElement, so always do that.
70  if (isset($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['config.']['treeConfig.'])) {
71  $pageTsConfig = $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['config.']['treeConfig.'];
72  if (isset($pageTsConfig['startingPoints'])) {
73  $fieldConfig['config']['treeConfig']['startingPoints']
74  = implode(',', array_unique(‪GeneralUtility::intExplode(',', (string)$pageTsConfig['startingPoints'])));
75  }
76  if (isset($pageTsConfig['appearance.']['expandAll'])) {
77  $fieldConfig['config']['treeConfig']['appearance']['expandAll'] = (bool)$pageTsConfig['appearance.']['expandAll'];
78  }
79  if (isset($pageTsConfig['appearance.']['maxLevels'])) {
80  $fieldConfig['config']['treeConfig']['appearance']['maxLevels'] = (int)$pageTsConfig['appearance.']['maxLevels'];
81  }
82  if (isset($pageTsConfig['appearance.']['nonSelectableLevels'])) {
83  $fieldConfig['config']['treeConfig']['appearance']['nonSelectableLevels'] = $pageTsConfig['appearance.']['nonSelectableLevels'];
84  }
85  }
86 
87  // Prepare the list of currently selected nodes using RelationHandler
88  // This is needed to ensure a correct value initialization before the actual tree is loaded
89  $result['databaseRow'][$fieldName] = $this->‪processDatabaseFieldValue($result['databaseRow'], $fieldName);
90  $result['databaseRow'][$fieldName] = $this->‪processSelectFieldValue($result, $fieldName, []);
91 
92  if ($result['selectTreeCompileItems']) {
93  $finalItems = [];
94 
95  // Prepare the list of "static" items if there are any.
96  // "static" and "dynamic" is separated since the tree code only copes with "real" existing foreign nodes,
97  // so this "static" stuff allows defining tree items that don't really exist in the tree.
98  $itemsFromTca = $this->‪sanitizeItemArray($fieldConfig['config']['items'] ?? [], $table, $fieldName);
99 
100  // List of additional items defined by page ts config "addItems"
101  $itemsFromPageTsConfig = $this->‪addItemsFromPageTsConfig($result, $fieldName, []);
102  // Resolve pageTsConfig item icons to markup
103  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
104  $finalPageTsConfigItems = [];
105  foreach ($itemsFromPageTsConfig as $item) {
106  if ($item['icon'] !== null) {
107  $item['icon'] = $iconFactory->getIcon($item['icon'], IconSize::SMALL)->getMarkup('inline');
108  }
109  $finalPageTsConfigItems[] = $item;
110  }
111 
112  if (!empty($itemsFromTca) || !empty($finalPageTsConfigItems)) {
113  // First apply "keepItems" to $itemsFromTca, this will restrict the tca item list to only
114  // those items that are defined in page ts "keepItems" if given
115  $itemsFromTca = $this->‪removeItemsByKeepItemsPageTsConfig($result, $fieldName, $itemsFromTca);
116  // Then, merge the items from page ts "addItems" into item list, since "addItems" should
117  // add additional items even if they are not in the "keepItems" list
118  $staticItems = array_merge($itemsFromTca, $finalPageTsConfigItems);
119  // Now apply page ts config "removeItems", so this is *after* addItems, so "removeItems" could
120  // possibly remove items again that were added via "addItems"
121  $staticItems = $this->‪removeItemsByRemoveItemsPageTsConfig($result, $fieldName, $staticItems);
122  // Now, apply user and access right restrictions to this item list
123  $staticItems = $this->‪removeItemsByUserLanguageFieldRestriction($result, $fieldName, $staticItems);
124  $staticItems = $this->‪removeItemsByUserAuthMode($result, $fieldName, $staticItems);
125  $staticItems = $this->‪removeItemsByDoktypeUserRestriction($result, $fieldName, $staticItems);
126  // Call itemsProcFunc if given. Note this function does *not* see the "dynamic" list of items
127  if (!empty($fieldConfig['config']['itemsProcFunc'])) {
128  $staticItems = $this->‪resolveItemProcessorFunction($result, $fieldName, $staticItems);
129  // itemsProcFunc must not be used anymore
130  unset($fieldConfig['config']['itemsProcFunc']);
131  }
132  // translate any labels
133  $staticItems = $this->‪translateLabels($result, $staticItems, $table, $fieldName);
134  // and add icons from the static list
135  $staticItems = $this->‪addIconFromAltIcons($result, $staticItems, $table, $fieldName);
136  // Now compile the target items using the same array structure as the "dynamic" list below
137  foreach ($staticItems as $item) {
138  if ($item['value'] === '--div--') {
139  // Skip divs that may occur here for whatever reason
140  continue;
141  }
142  $finalItems[] = [
143  'identifier' => $item['value'],
144  'name' => $item['label'],
145  'icon' => $item['icon'] ?? '',
146  'iconOverlay' => '',
147  'depth' => 0,
148  'hasChildren' => false,
149  'selectable' => true,
150  'checked' => in_array($item['value'], $result['databaseRow'][$fieldName]),
151  ];
152  }
153  }
154 
155  // Fetch the list of all possible "related" items (yuk!) and apply a similar processing as with the "static" list
156  $dynamicItems = $this->‪addItemsFromForeignTable($result, $fieldName, []);
157  $dynamicItems = $this->‪removeItemsByKeepItemsPageTsConfig($result, $fieldName, $dynamicItems);
158  $dynamicItems = $this->‪removeItemsByRemoveItemsPageTsConfig($result, $fieldName, $dynamicItems);
159  $dynamicItems = $this->‪removeItemsByUserLanguageFieldRestriction($result, $fieldName, $dynamicItems);
160  $dynamicItems = $this->‪removeItemsByUserAuthMode($result, $fieldName, $dynamicItems);
161  $dynamicItems = $this->‪removeItemsByDoktypeUserRestriction($result, $fieldName, $dynamicItems);
162  // Funnily, the only data needed for the tree code are the uids of the possible records (yuk!) - get them
163  $uidListOfAllDynamicItems = [];
164  foreach ($dynamicItems as $item) {
165  if ((int)$item['value'] > 0) {
166  $uidListOfAllDynamicItems[] = (int)$item['value'];
167  }
168  }
169  // Now kick in this tree stuff
171  $fieldConfig['config'],
172  $table,
173  $fieldName,
174  $result['databaseRow']
175  );
176  $treeDataProvider->setSelectedList(implode(',', $result['databaseRow'][$fieldName]));
177  // Basically the tree foo fetches all tree nodes again (aaargs), then verifies if
178  // a given rows uid is within this "list of allowed uids". It then creates an object
179  // tree representing the nested tree, just to collapse all that to a flat array again. Yay ...
180  $treeDataProvider->setItemWhiteList($uidListOfAllDynamicItems);
181  $treeDataProvider->initializeTreeData();
182  $treeRenderer = GeneralUtility::makeInstance(ArrayTreeRenderer::class);
183  $tree = GeneralUtility::makeInstance(TableConfigurationTree::class);
184  $tree->setDataProvider($treeDataProvider);
185  $tree->setNodeRenderer($treeRenderer);
186 
187  // Merge tree nodes after calculated nodes from static items
188  $fieldConfig['config']['items'] = array_merge($finalItems, $tree->render());
189  }
190 
191  $result['processedTca']['columns'][$fieldName] = $fieldConfig;
192  }
193 
194  return $result;
195  }
196 
202  protected function ‪isTargetRenderType(array $fieldConfig)
203  {
204  return $fieldConfig['config']['renderType'] === 'selectTree';
205  }
206 }
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\sanitizeItemArray
‪array sanitizeItemArray($itemArray, $tableName, $fieldName)
Definition: AbstractItemProvider.php:1104
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\addItemsFromPageTsConfig
‪array addItemsFromPageTsConfig(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:147
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByUserLanguageFieldRestriction
‪array removeItemsByUserLanguageFieldRestriction(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:448
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\addIconFromAltIcons
‪addIconFromAltIcons(array $result, array $items, string $table, string $fieldName)
Definition: AbstractItemProvider.php:1080
‪TYPO3\CMS\Core\Tree\TableConfiguration\TableConfigurationTree
Definition: TableConfigurationTree.php:24
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\translateLabels
‪array translateLabels(array $result, array $itemArray, $table, $fieldName)
Definition: AbstractItemProvider.php:1040
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Backend\Form\FormDataProvider\TcaSelectTreeItems\addData
‪array addData(array $result)
Definition: TcaSelectTreeItems.php:46
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\addItemsFromForeignTable
‪array addItemsFromForeignTable(array $result, $fieldName, array $items, bool $includeFullRows=false)
Definition: AbstractItemProvider.php:266
‪TYPO3\CMS\Core\Tree\TableConfiguration\TreeDataProviderFactory\getDataProvider
‪static DatabaseTreeDataProvider getDataProvider(array $tcaConfiguration, $table, $field, $currentValue)
Definition: TreeDataProviderFactory.php:36
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\parseStartingPointsFromSiteConfiguration
‪parseStartingPointsFromSiteConfiguration(array $result, array $fieldConfig)
Definition: AbstractItemProvider.php:919
‪TYPO3\CMS\Backend\Form\FormDataProvider\TcaSelectTreeItems
Definition: TcaSelectTreeItems.php:39
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\resolveItemProcessorFunction
‪array resolveItemProcessorFunction(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:59
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByDoktypeUserRestriction
‪array removeItemsByDoktypeUserRestriction(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:506
‪TYPO3\CMS\Backend\Form\FormDataProvider
Definition: AbstractDatabaseRecordProvider.php:16
‪TYPO3\CMS\Backend\Form\FormDataProvider\TcaSelectTreeItems\isTargetRenderType
‪bool isTargetRenderType(array $fieldConfig)
Definition: TcaSelectTreeItems.php:202
‪TYPO3\CMS\Backend\Form\FormDataProviderInterface
Definition: FormDataProviderInterface.php:23
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByKeepItemsPageTsConfig
‪array removeItemsByKeepItemsPageTsConfig(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:381
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\processDatabaseFieldValue
‪array processDatabaseFieldValue(array $row, $fieldName)
Definition: AbstractItemProvider.php:953
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\processSelectFieldValue
‪array processSelectFieldValue(array $result, $fieldName, array $staticValues)
Definition: AbstractItemProvider.php:975
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:24
‪TYPO3\CMS\Core\Tree\TableConfiguration\ArrayTreeRenderer
Definition: ArrayTreeRenderer.php:27
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByUserAuthMode
‪array removeItemsByUserAuthMode(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:477
‪TYPO3\CMS\Core\Tree\TableConfiguration\TreeDataProviderFactory
Definition: TreeDataProviderFactory.php:26
‪TYPO3\CMS\Core\Utility\MathUtility\forceIntegerInRange
‪static int forceIntegerInRange(mixed $theInt, int $min, int $max=2000000000, int $defaultValue=0)
Definition: MathUtility.php:34
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static list< int > intExplode(string $delimiter, string $string, bool $removeEmptyValues=false)
Definition: GeneralUtility.php:756
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider
Definition: AbstractItemProvider.php:50
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByRemoveItemsPageTsConfig
‪array removeItemsByRemoveItemsPageTsConfig(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:414