‪TYPO3CMS  ‪main
SelectItemProcessor.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
26 
33 #[Autoconfigure(public: true)]
35 {
36  public function ‪__construct(protected readonly ‪LanguageServiceFactory $languageServiceFactory) {}
37 
56  public function ‪groupAndSortItems(array $allItems, array $definedGroups, array $sortOrders): array
57  {
58  $allItems = $this->‪transformArrayToSelectItems($allItems);
59  $groupedItems = [];
60  // Append defined groups at first, as their order is prioritized
61  $itemGroups = ['none' => ''];
62  foreach ($definedGroups as $groupId => $groupLabel) {
63  $itemGroups[$groupId] = $this->‪getLanguageService()->sL($groupLabel);
64  }
65  $currentGroup = 'none';
66  // Extract --div-- into itemGroups
67  foreach ($allItems as $item) {
68  if ($item->isDivider()) {
69  // A divider is added as a group (existing groups will get their label overridden)
70  if ($item->hasGroup()) {
71  $currentGroup = $item->getGroup();
72  $itemGroups[$currentGroup] = $item->getLabel();
73  } else {
74  $currentGroup = 'none';
75  }
76  continue;
77  }
78  // Put the given item in the currentGroup if no group has been given already
79  if (!$item->hasGroup()) {
80  $item = $item->withGroup($currentGroup);
81  }
82  $groupIdOfItem = $item->hasGroup() ? $item->getGroup() : 'none';
83  // It is still possible to have items that have an "unassigned" group, so they are moved to the "none" group
84  if (!isset($itemGroups[$groupIdOfItem])) {
85  $itemGroups[$groupIdOfItem] = '';
86  }
87 
88  // Put the item in its corresponding group (and create it if it does not exist yet)
89  if (!is_array($groupedItems[$groupIdOfItem] ?? null)) {
90  $groupedItems[$groupIdOfItem] = [];
91  }
92  $groupedItems[$groupIdOfItem][] = $item;
93  }
94  // Only "none" = no grouping used explicitly via "itemGroups" or via "--div--"
95  if (count($itemGroups) === 1) {
96  if (!empty($sortOrders)) {
97  $allItems = $this->‪sortItems($allItems, $sortOrders);
98  }
99  return $this->‪transformSelectItemsToArray($allItems);
100  }
101 
102  // $groupedItems contains all items per group
103  // $itemGroups contains all groups in order of each group
104 
105  // Let's add the --div-- items again ("unpacking")
106  // And use the group ordering given by the itemGroups
107  $finalItems = [];
108  foreach ($itemGroups as $groupId => $groupLabel) {
109  $itemsInGroup = $groupedItems[$groupId] ?? [];
110  if (empty($itemsInGroup)) {
111  continue;
112  }
113  // If sorting is defined, sort within each group now
114  if (!empty($sortOrders)) {
115  $itemsInGroup = $this->‪sortItems($itemsInGroup, $sortOrders);
116  }
117  // Add the --div-- if it is not the "none" default item
118  if ($groupId !== 'none') {
119  // Fall back to the groupId, if there is no label for it
120  $groupLabel = $groupLabel ?: $groupId;
121  $finalItems[] = ['label' => $groupLabel, 'value' => '--div--', 'group' => $groupId];
122  }
123  $finalItems = array_merge($finalItems, $itemsInGroup);
124  }
125  return $this->‪transformSelectItemsToArray($finalItems);
126  }
127 
131  public function ‪transformArrayToSelectItems(array $items, string $type = 'select'): array
132  {
133  return array_map(static function (array|‪SelectItem $item) use ($type): ‪SelectItem {
134  if ($item instanceof ‪SelectItem) {
135  return $item;
136  }
137  return ‪SelectItem::fromTcaItemArray($item, $type);
138  }, $items);
139  }
140 
141  public function ‪transformSelectItemsToArray(array $items): array
142  {
143  return array_map(static function (array|‪SelectItem $item): array {
144  if (!$item instanceof ‪SelectItem) {
145  return $item;
146  }
147  return $item->‪toArray();
148  }, $items);
149  }
150 
159  protected function ‪sortItems(array $items, array $sortOrders): array
160  {
161  foreach ($sortOrders as $order => $direction) {
162  switch ($order) {
163  case 'label':
164  $direction = strtolower($direction);
165  @usort(
166  $items,
167  static function (‪SelectItem $item1, ‪SelectItem $item2) use ($direction) {
168  if ($direction === 'desc') {
169  return (strcasecmp($item1->‪getLabel(), $item2->‪getLabel()) <= 0) ? 1 : 0;
170  }
171  return strcasecmp($item1->‪getLabel(), $item2->‪getLabel());
172  }
173  );
174  break;
175  case 'value':
176  $direction = strtolower($direction);
177  @usort(
178  $items,
179  static function (‪SelectItem $item1, ‪SelectItem $item2) use ($direction) {
180  if ($direction === 'desc') {
181  return (strcasecmp((string)$item1->‪getValue(), (string)$item2->‪getValue()) <= 0) ? 1 : 0;
182  }
183  return strcasecmp((string)$item1->‪getValue(), (string)$item2->‪getValue());
184  }
185  );
186  break;
187  default:
188  $reference = null;
189  GeneralUtility::callUserFunction($direction, $items, $reference);
190  }
191  }
192  return $items;
193  }
194 
196  {
197  return ‪$GLOBALS['LANG'] ?? $this->languageServiceFactory->createFromUserPreferences($this->‪getBackendUser());
198  }
199 
201  {
202  return ‪$GLOBALS['BE_USER'];
203  }
204 }
‪TYPO3\CMS\Core\Localization\LanguageServiceFactory
Definition: LanguageServiceFactory.php:25
‪TYPO3\CMS\Backend\Form\Processor\SelectItemProcessor\transformSelectItemsToArray
‪transformSelectItemsToArray(array $items)
Definition: SelectItemProcessor.php:141
‪TYPO3\CMS\Core\Schema\Struct\SelectItem\toArray
‪toArray()
Definition: SelectItem.php:62
‪TYPO3\CMS\Core\Schema\Struct\SelectItem
Definition: SelectItem.php:21
‪TYPO3\CMS\Backend\Form\Processor\SelectItemProcessor\getLanguageService
‪getLanguageService()
Definition: SelectItemProcessor.php:195
‪TYPO3\CMS\Core\Schema\Struct\SelectItem\fromTcaItemArray
‪static fromTcaItemArray(array $item, string $type='select')
Definition: SelectItem.php:45
‪TYPO3\CMS\Backend\Form\Processor\SelectItemProcessor\transformArrayToSelectItems
‪SelectItem[] transformArrayToSelectItems(array $items, string $type='select')
Definition: SelectItemProcessor.php:131
‪TYPO3\CMS\Backend\Form\Processor\SelectItemProcessor\groupAndSortItems
‪groupAndSortItems(array $allItems, array $definedGroups, array $sortOrders)
Definition: SelectItemProcessor.php:56
‪TYPO3\CMS\Core\Schema\Struct\SelectItem\getValue
‪getValue()
Definition: SelectItem.php:104
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Core\Schema\Struct\SelectItem\getLabel
‪getLabel()
Definition: SelectItem.php:92
‪TYPO3\CMS\Backend\Form\Processor\SelectItemProcessor
Definition: SelectItemProcessor.php:35
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Backend\Form\Processor\SelectItemProcessor\getBackendUser
‪getBackendUser()
Definition: SelectItemProcessor.php:200
‪TYPO3\CMS\Backend\Form\Processor
Definition: SelectItemProcessor.php:18
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Backend\Form\Processor\SelectItemProcessor\sortItems
‪SelectItem[] sortItems(array $items, array $sortOrders)
Definition: SelectItemProcessor.php:159
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Backend\Form\Processor\SelectItemProcessor\__construct
‪__construct(protected readonly LanguageServiceFactory $languageServiceFactory)
Definition: SelectItemProcessor.php:36