‪TYPO3CMS  ‪main
ConstantConfigurationParser.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 
23 
36 {
42  protected ‪$subCategories = [
43  // Standard categories:
44  'enable' => ['Enable features', 'a'],
45  'dims' => ['Dimensions, widths, heights, pixels', 'b'],
46  'file' => ['Files', 'c'],
47  'typo' => ['Typography', 'd'],
48  'color' => ['Colors', 'e'],
49  'links' => ['Links and targets', 'f'],
50  'language' => ['Language specific constants', 'g'],
51  // subcategories based on the default content elements
52  'cheader' => ['Content: \'Header\'', 'ma'],
53  'cheader_g' => ['Content: \'Header\', Graphical', 'ma'],
54  'ctext' => ['Content: \'Text\'', 'mb'],
55  'cimage' => ['Content: \'Image\'', 'md'],
56  'ctextmedia' => ['Content: \'Textmedia\'', 'ml'],
57  'cbullets' => ['Content: \'Bullet list\'', 'me'],
58  'ctable' => ['Content: \'Table\'', 'mf'],
59  'cuploads' => ['Content: \'Filelinks\'', 'mg'],
60  'cmultimedia' => ['Content: \'Multimedia\'', 'mh'],
61  'cmedia' => ['Content: \'Media\'', 'mr'],
62  'cmailform' => ['Content: \'Form\'', 'mi'],
63  'csearch' => ['Content: \'Search\'', 'mj'],
64  'clogin' => ['Content: \'Login\'', 'mk'],
65  'cmenu' => ['Content: \'Menu/Sitemap\'', 'mm'],
66  'cshortcut' => ['Content: \'Insert records\'', 'mn'],
67  'clist' => ['Content: \'List of records\'', 'mo'],
68  'chtml' => ['Content: \'HTML\'', 'mq'],
69  ];
70 
78  public function ‪prepareConfigurationForView(array $configuration): array
79  {
80  $resultArray = [];
81  if (!empty($configuration)) {
82  $hierarchicConfiguration = [];
83  foreach ($configuration as $configurationOption) {
84  $originalConfiguration = $this->‪buildConfigurationArray($configurationOption);
85  ‪ArrayUtility::mergeRecursiveWithOverrule($originalConfiguration, $hierarchicConfiguration);
86  $hierarchicConfiguration = $originalConfiguration;
87  }
88  // Flip category array as it was merged the other way around
89  $hierarchicConfiguration = array_reverse($hierarchicConfiguration);
90  // Sort configurations of each subcategory
91  foreach ($hierarchicConfiguration as &$catConfigurationArray) {
92  foreach ($catConfigurationArray as &$subcatConfigurationArray) {
93  uasort($subcatConfigurationArray, static function ($a, $b) {
94  return strnatcmp($a['subcat'], $b['subcat']);
95  });
96  }
97  unset($subcatConfigurationArray);
98  }
99  unset($catConfigurationArray);
100  $resultArray = $hierarchicConfiguration;
101  }
102  return $resultArray;
103  }
104 
112  protected function ‪buildConfigurationArray(array $configurationOption): array
113  {
114  $hierarchicConfiguration = [];
115  if (str_starts_with((string)$configurationOption['type'], 'user')) {
116  $configurationOption = $this->‪extractInformationForConfigFieldsOfTypeUser($configurationOption);
117  } elseif (str_starts_with((string)$configurationOption['type'], 'options')) {
118  $configurationOption = $this->‪extractInformationForConfigFieldsOfTypeOptions($configurationOption);
119  }
120  $languageService = $this->‪getLanguageService();
121  if (is_string($configurationOption['label'])) {
122  $translatedLabel = $languageService->sL($configurationOption['label']);
123  if ($translatedLabel) {
124  $configurationOption['label'] = $translatedLabel;
125  }
126  }
127  $configurationOption['labels'] = ‪GeneralUtility::trimExplode(':', $configurationOption['label'], false, 2);
128  $configurationOption['subcat_name'] = ($configurationOption['subcat_name'] ?? false) ?: '__default';
129  $hierarchicConfiguration[$configurationOption['cat']][$configurationOption['subcat_name']][$configurationOption['name']] = $configurationOption;
130  return $hierarchicConfiguration;
131  }
132 
140  protected function ‪extractInformationForConfigFieldsOfTypeOptions(array $configurationOption): array
141  {
143  preg_match('/options\[(.*)\]/is', $configurationOption['type'], $typeMatches);
144  foreach (‪GeneralUtility::trimExplode(',', $typeMatches[1]) as $optionItem) {
145  $optionPair = ‪GeneralUtility::trimExplode('=', $optionItem);
146  if (count($optionPair) === 2) {
147  $configurationOption['generic'][$optionPair[0]] = $optionPair[1];
148  } else {
149  $configurationOption['generic'][$optionPair[0]] = $optionPair[0];
150  }
151  }
152  $configurationOption['type'] = 'options';
153  return $configurationOption;
154  }
155 
163  protected function ‪extractInformationForConfigFieldsOfTypeUser(array $configurationOption): array
164  {
166  preg_match('/user\\[(.*)\\]/is', $configurationOption['type'], $matches);
167  $configurationOption['generic'] = $matches[1];
168  $configurationOption['type'] = 'user';
169  return $configurationOption;
170  }
171 
197  public function ‪getConfigurationAsValuedArray(string $rawConfiguration): array
198  {
199  $typoScriptParser = new ‪TypoScriptParser();
200  $typoScriptParser->regComments = true;
201  $typoScriptParser->parse($rawConfiguration);
202  $flatSetup = ‪ArrayUtility::flatten($typoScriptParser->setup, '', true);
203  $theConstants = $this->‪parseComments($flatSetup);
204 
205  // Loop through configuration items, see if it is assigned to a sub category
206  // and add the sub category label to the item property if so.
207  foreach ($theConstants as $configurationOptionName => $configurationOption) {
208  if (
209  array_key_exists('subcat_name', $configurationOption) && isset($this->subCategories[$configurationOption['subcat_name']][0])
210  ) {
211  $theConstants[$configurationOptionName]['subcat_label'] = $this->subCategories[$configurationOption['subcat_name']][0];
212  }
213  }
214  return $theConstants;
215  }
216 
225  public function ‪parseComments($flatSetup, $default = null): array
226  {
227  $default = $default ?? $flatSetup;
228  $categoryLabels = [];
229  $editableComments = [];
230  $counter = 0;
231  foreach ($flatSetup as $const => $value) {
232  $key = $const . '..';
233  if (substr($const, -2) === '..' || !isset($flatSetup[$key])) {
234  continue;
235  }
236  $counter++;
237  $comment = trim($flatSetup[$key]);
238  foreach (explode(LF, $comment) as $k => $v) {
239  $line = trim(preg_replace('/^[#\\/]*/', '', $v) ?? '');
240  if (!$line) {
241  continue;
242  }
243  foreach (explode(';', $line) as $par) {
244  if (str_contains($par, '=')) {
245  $keyValPair = explode('=', $par, 2);
246  switch (strtolower(trim($keyValPair[0]))) {
247  case 'type':
248  // Type:
249  $editableComments[$const]['type'] = trim($keyValPair[1]);
250  break;
251  case 'cat':
252  // List of categories.
253  $catSplit = explode('/', strtolower($keyValPair[1]));
254  $catSplit[0] = trim($catSplit[0]);
255  if (isset($categoryLabels[$catSplit[0]])) {
256  $catSplit[0] = $categoryLabels[$catSplit[0]];
257  }
258  $editableComments[$const]['cat'] = $catSplit[0];
259  // This is the subcategory. Must be a key in $this->subCategories[].
260  // catSplit[2] represents the search-order within the subcat.
261  $catSplit[1] = !empty($catSplit[1]) ? trim($catSplit[1]) : '';
262  if ($catSplit[1] && isset($this->subCategories[$catSplit[1]])) {
263  $editableComments[$const]['subcat_name'] = $catSplit[1];
264  $orderIdentifier = isset($catSplit[2]) ? trim($catSplit[2]) : $counter;
265  $editableComments[$const]['subcat'] = ($this->subCategories[$catSplit[1]][1] ?? '')
266  . '/' . $catSplit[1] . '/' . $orderIdentifier . 'z';
267  } elseif (isset($catSplit[2])) {
268  $editableComments[$const]['subcat'] = 'x/' . trim($catSplit[2]) . 'z';
269  } else {
270  $editableComments[$const]['subcat'] = 'x/' . $counter . 'z';
271  }
272  break;
273  case 'label':
274  // Label
275  $editableComments[$const]['label'] = trim($keyValPair[1]);
276  break;
277  case 'customcategory':
278  // Custom category label
279  $customCategory = explode('=', $keyValPair[1], 2);
280  if (trim($customCategory[0])) {
281  $categoryKey = strtolower($customCategory[0]);
282  $categoryLabels[$categoryKey] = $this->‪getLanguageService()->sL($customCategory[1]);
283  }
284  break;
285  case 'customsubcategory':
286  // Custom subCategory label
287  $customSubcategory = explode('=', $keyValPair[1], 2);
288  if (trim($customSubcategory[0])) {
289  $subCategoryKey = strtolower($customSubcategory[0]);
290  $this->subCategories[$subCategoryKey][0] = $this->‪getLanguageService()->sL($customSubcategory[1]);
291  }
292  break;
293  }
294  }
295  }
296  }
297  if (isset($editableComments[$const])) {
298  $editableComments[$const]['name'] = $const;
299  $editableComments[$const]['value'] = trim($value);
300  $editableComments[$const]['default_value'] = trim((string)($default[$const] ?? ''));
301  // If type was not provided, initialize with default value "string".
302  $editableComments[$const]['type'] ??= 'string';
303  }
304  }
305  return $editableComments;
306  }
307 
308  protected function ‪getLanguageService(): ‪LanguageService
309  {
310  return ‪$GLOBALS['LANG'];
311  }
312 
324  public function ‪getSubCategories(): array
325  {
327  }
328 }
‪TYPO3\CMS\Core\TypoScript\Parser\ConstantConfigurationParser\prepareConfigurationForView
‪array prepareConfigurationForView(array $configuration)
Definition: ConstantConfigurationParser.php:77
‪TYPO3\CMS\Core\TypoScript\Parser\ConstantConfigurationParser\$subCategories
‪array $subCategories
Definition: ConstantConfigurationParser.php:41
‪TYPO3\CMS\Core\TypoScript\Parser\ConstantConfigurationParser\getConfigurationAsValuedArray
‪array getConfigurationAsValuedArray(string $rawConfiguration)
Definition: ConstantConfigurationParser.php:196
‪TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser
Definition: TypoScriptParser.php:36
‪TYPO3\CMS\Core\TypoScript\Parser
Definition: ConstantConfigurationParser.php:18
‪TYPO3\CMS\Core\TypoScript\Parser\ConstantConfigurationParser\parseComments
‪array parseComments($flatSetup, $default=null)
Definition: ConstantConfigurationParser.php:224
‪TYPO3\CMS\Core\TypoScript\Parser\ConstantConfigurationParser\getLanguageService
‪getLanguageService()
Definition: ConstantConfigurationParser.php:307
‪TYPO3\CMS\Core\TypoScript\Parser\ConstantConfigurationParser\extractInformationForConfigFieldsOfTypeOptions
‪array extractInformationForConfigFieldsOfTypeOptions(array $configurationOption)
Definition: ConstantConfigurationParser.php:139
‪TYPO3\CMS\Core\TypoScript\Parser\ConstantConfigurationParser\getSubCategories
‪array getSubCategories()
Definition: ConstantConfigurationParser.php:323
‪TYPO3\CMS\Core\TypoScript\Parser\ConstantConfigurationParser\buildConfigurationArray
‪array buildConfigurationArray(array $configurationOption)
Definition: ConstantConfigurationParser.php:111
‪TYPO3\CMS\Core\Utility\ArrayUtility\flatten
‪static array flatten(array $array, string $prefix='', bool $keepDots=false)
Definition: ArrayUtility.php:471
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static string[] trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:919
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:26
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\TypoScript\Parser\ConstantConfigurationParser
Definition: ConstantConfigurationParser.php:36
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:39
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Core\Utility\ArrayUtility\mergeRecursiveWithOverrule
‪static mergeRecursiveWithOverrule(array &$original, array $overrule, bool $addKeys=true, bool $includeEmptyValues=true, bool $enableUnsetFeature=true)
Definition: ArrayUtility.php:637
‪TYPO3\CMS\Core\TypoScript\Parser\ConstantConfigurationParser\extractInformationForConfigFieldsOfTypeUser
‪array extractInformationForConfigFieldsOfTypeUser(array $configurationOption)
Definition: ConstantConfigurationParser.php:162