‪TYPO3CMS  9.5
ExtensionConfigurationService.php
Go to the documentation of this file.
1 <?php
2 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 
21 use TYPO3\CMS\Core\Package\PackageManager;
24 
36 {
43  protected ‪$subCategories = [
44  // Standard categories:
45  'enable' => ['Enable features', 'a'],
46  'dims' => ['Dimensions, widths, heights, pixels', 'b'],
47  'file' => ['Files', 'c'],
48  'typo' => ['Typography', 'd'],
49  'color' => ['Colors', 'e'],
50  'links' => ['Links and targets', 'f'],
51  'language' => ['Language specific constants', 'g'],
52  // subcategories based on the default content elements
53  'cheader' => ['Content: \'Header\'', 'ma'],
54  'cheader_g' => ['Content: \'Header\', Graphical', 'ma'],
55  'ctext' => ['Content: \'Text\'', 'mb'],
56  'cimage' => ['Content: \'Image\'', 'md'],
57  'ctextmedia' => ['Content: \'Textmedia\'', 'ml'],
58  'cbullets' => ['Content: \'Bullet list\'', 'me'],
59  'ctable' => ['Content: \'Table\'', 'mf'],
60  'cuploads' => ['Content: \'Filelinks\'', 'mg'],
61  'cmultimedia' => ['Content: \'Multimedia\'', 'mh'],
62  'cmedia' => ['Content: \'Media\'', 'mr'],
63  'cmailform' => ['Content: \'Form\'', 'mi'],
64  'csearch' => ['Content: \'Search\'', 'mj'],
65  'clogin' => ['Content: \'Login\'', 'mk'],
66  'cmenu' => ['Content: \'Menu/Sitemap\'', 'mm'],
67  'cshortcut' => ['Content: \'Insert records\'', 'mn'],
68  'clist' => ['Content: \'List of records\'', 'mo'],
69  'chtml' => ['Content: \'HTML\'', 'mq']
70  ];
71 
79  public function ‪getConfigurationPreparedForView(string $extensionKey): array
80  {
81  $package = GeneralUtility::makeInstance(PackageManager::class)->getPackage($extensionKey);
82  if (!@is_file($package->getPackagePath() . 'ext_conf_template.txt')) {
83  return [];
84  }
85  $extensionConfiguration = new ‪ExtensionConfiguration();
86  $configuration = $this->‪getDefaultConfigurationFromExtConfTemplateAsValuedArray($extensionKey);
87  foreach ($configuration as $configurationPath => &$details) {
88  try {
89  $valueFromLocalConfiguration = $extensionConfiguration->get($extensionKey, str_replace('.', '/', $configurationPath));
90  $details['value'] = $valueFromLocalConfiguration;
92  // Deliberately empty - it can happen at runtime that a written config does not return
93  // back all values (eg. saltedpassword with its userFuncs), which then miss in the written
94  // configuration and are only synced after next install tool run. This edge case is
95  // taken care off here.
96  }
97  }
98  $resultArray = [];
99  if (!empty($configuration)) {
100  $hierarchicConfiguration = [];
101  foreach ($configuration as $configurationOption) {
102  $originalConfiguration = $this->‪buildConfigurationArray($configurationOption);
103  ‪ArrayUtility::mergeRecursiveWithOverrule($originalConfiguration, $hierarchicConfiguration);
104  $hierarchicConfiguration = $originalConfiguration;
105  }
106  // Flip category array as it was merged the other way around
107  $hierarchicConfiguration = array_reverse($hierarchicConfiguration);
108  // Sort configurations of each subcategory
109  foreach ($hierarchicConfiguration as &$catConfigurationArray) {
110  foreach ($catConfigurationArray as &$subcatConfigurationArray) {
111  uasort($subcatConfigurationArray, function ($a, $b) {
112  return strnatcmp($a['subcat'], $b['subcat']);
113  });
114  }
115  unset($subcatConfigurationArray);
116  }
117  unset($tempConfiguration);
118  $resultArray = $hierarchicConfiguration;
119  }
120  return $resultArray;
121  }
122 
130  protected function ‪buildConfigurationArray(array $configurationOption): array
131  {
132  $hierarchicConfiguration = [];
133  if (GeneralUtility::isFirstPartOfStr($configurationOption['type'], 'user')) {
134  $configurationOption = $this->‪extractInformationForConfigFieldsOfTypeUser($configurationOption);
135  } elseif (GeneralUtility::isFirstPartOfStr($configurationOption['type'], 'options')) {
136  $configurationOption = $this->‪extractInformationForConfigFieldsOfTypeOptions($configurationOption);
137  }
138  $languageService = $this->‪getLanguageService();
139  if (is_string($configurationOption['label'])) {
140  $translatedLabel = $languageService->sL($configurationOption['label']);
141  if ($translatedLabel) {
142  $configurationOption['label'] = $translatedLabel;
143  }
144  }
145  $configurationOption['labels'] = GeneralUtility::trimExplode(':', $configurationOption['label'], false, 2);
146  $configurationOption['subcat_name'] = $configurationOption['subcat_name'] ?: '__default';
147  $hierarchicConfiguration[$configurationOption['cat']][$configurationOption['subcat_name']][$configurationOption['name']] = $configurationOption;
148  return $hierarchicConfiguration;
149  }
150 
158  protected function ‪extractInformationForConfigFieldsOfTypeOptions(array $configurationOption): array
159  {
160  preg_match('/options\[(.*)\]/is', $configurationOption['type'], $typeMatches);
161  $optionItems = GeneralUtility::trimExplode(',', $typeMatches[1]);
162  foreach ($optionItems as $optionItem) {
163  $optionPair = GeneralUtility::trimExplode('=', $optionItem);
164  if (count($optionPair) === 2) {
165  $configurationOption['generic'][$optionPair[0]] = $optionPair[1];
166  } else {
167  $configurationOption['generic'][$optionPair[0]] = $optionPair[0];
168  }
169  }
170  $configurationOption['type'] = 'options';
171  return $configurationOption;
172  }
173 
181  protected function ‪extractInformationForConfigFieldsOfTypeUser(array $configurationOption): array
182  {
183  preg_match('/user\\[(.*)\\]/is', $configurationOption['type'], $matches);
184  $configurationOption['generic'] = $matches[1];
185  $configurationOption['type'] = 'user';
186  return $configurationOption;
187  }
188 
213  protected function ‪getDefaultConfigurationFromExtConfTemplateAsValuedArray(string $extensionKey): array
214  {
215  $parsedConstants = (new ‪ExtensionConfiguration())->getParsedExtConfTemplate($extensionKey);
216  $flatSetup = $this->‪flattenSetup($parsedConstants);
217  $theConstants = $this->‪parseComments($flatSetup);
218 
219  // Loop through configuration items, see if it is assigned to a sub category
220  // and add the sub category label to the item property if so.
221  foreach ($theConstants as $configurationOptionName => $configurationOption) {
222  if (
223  array_key_exists('subcat_name', $configurationOption)
224  && isset($this->subCategories[$configurationOption['subcat_name']])
225  && isset($this->subCategories[$configurationOption['subcat_name']][0])
226  ) {
227  $theConstants[$configurationOptionName]['subcat_label'] = $this->subCategories[$configurationOption['subcat_name']][0];
228  }
229  $theConstants[$configurationOptionName]['extensionKey'] = $extensionKey;
230  }
231  return $theConstants;
232  }
233 
241  protected function ‪parseComments($flatSetup)
242  {
243  $categoryLabels = [];
244  $editableComments = [];
245  $counter = 0;
246  foreach ($flatSetup as $const => $value) {
247  if (substr($const, -2) === '..' || !isset($flatSetup[$const . '..'])) {
248  continue;
249  }
250  $counter++;
251  $comment = trim($flatSetup[$const . '..']);
252  $c_arr = explode(LF, $comment);
253  foreach ($c_arr as $k => $v) {
254  $line = trim(preg_replace('/^[#\\/]*/', '', $v));
255  if (!$line) {
256  continue;
257  }
258  $parts = explode(';', $line);
259  foreach ($parts as $par) {
260  if (strstr($par, '=')) {
261  $keyValPair = explode('=', $par, 2);
262  switch (trim(strtolower($keyValPair[0]))) {
263  case 'type':
264  // Type:
265  $editableComments[$const]['type'] = trim($keyValPair[1]);
266  break;
267  case 'cat':
268  // List of categories.
269  $catSplit = explode('/', strtolower($keyValPair[1]));
270  $catSplit[0] = trim($catSplit[0]);
271  if (isset($categoryLabels[$catSplit[0]])) {
272  $catSplit[0] = $categoryLabels[$catSplit[0]];
273  }
274  $editableComments[$const]['cat'] = $catSplit[0];
275  // This is the subcategory. Must be a key in $this->subCategories[].
276  // catSplit[2] represents the search-order within the subcat.
277  $catSplit[1] = !empty($catSplit[1]) ? trim($catSplit[1]) : '';
278  if ($catSplit[1] && isset($this->subCategories[$catSplit[1]])) {
279  $editableComments[$const]['subcat_name'] = $catSplit[1];
280  $orderIdentifier = isset($catSplit[2]) ? trim($catSplit[2]) : $counter;
281  $editableComments[$const]['subcat'] = $this->subCategories[$catSplit[1]][1]
282  . '/' . $catSplit[1] . '/' . $orderIdentifier . 'z';
283  } elseif (isset($catSplit[2])) {
284  $editableComments[$const]['subcat'] = 'x' . '/' . trim($catSplit[2]) . 'z';
285  } else {
286  $editableComments[$const]['subcat'] = 'x' . '/' . $counter . 'z';
287  }
288  break;
289  case 'label':
290  // Label
291  $editableComments[$const]['label'] = trim($keyValPair[1]);
292  break;
293  case 'customcategory':
294  // Custom category label
295  $customCategory = explode('=', $keyValPair[1], 2);
296  if (trim($customCategory[0])) {
297  $categoryKey = strtolower($customCategory[0]);
298  $categoryLabels[$categoryKey] = $this->‪getLanguageService()->‪sL($customCategory[1]);
299  }
300  break;
301  case 'customsubcategory':
302  // Custom subCategory label
303  $customSubcategory = explode('=', $keyValPair[1], 2);
304  if (trim($customSubcategory[0])) {
305  $subCategoryKey = strtolower($customSubcategory[0]);
306  $this->subCategories[$subCategoryKey][0] = $this->‪getLanguageService()->‪sL($customSubcategory[1]);
307  }
308  break;
309  }
310  }
311  }
312  }
313  if (isset($editableComments[$const])) {
314  $editableComments[$const]['name'] = $const;
315  $editableComments[$const]['value'] = trim($value);
316  $editableComments[$const]['default_value'] = trim($value);
317  }
318  }
319  return $editableComments;
320  }
321 
329  protected function ‪flattenSetup($setupArray, $prefix = '')
330  {
331  $flatSetup = [];
332  if (is_array($setupArray)) {
333  foreach ($setupArray as $key => $val) {
334  if (is_array($val)) {
335  $flatSetup = array_merge($flatSetup, $this->‪flattenSetup($val, $prefix . $key));
336  } else {
337  $flatSetup[$prefix . $key] = $val;
338  }
339  }
340  }
341  return $flatSetup;
342  }
343 
347  protected function ‪getLanguageService()
348  {
349  return ‪$GLOBALS['LANG'];
350  }
351 }
‪TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException
Definition: ExtensionConfigurationPathDoesNotExistException.php:26
‪TYPO3\CMS\Core\Configuration\ExtensionConfiguration
Definition: ExtensionConfiguration.php:42
‪TYPO3\CMS\Install\Service\ExtensionConfigurationService
Definition: ExtensionConfigurationService.php:36
‪TYPO3\CMS\Install\Service\ExtensionConfigurationService\$subCategories
‪array $subCategories
Definition: ExtensionConfigurationService.php:42
‪TYPO3\CMS\Core\Utility\ArrayUtility\mergeRecursiveWithOverrule
‪static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
Definition: ArrayUtility.php:614
‪TYPO3\CMS\Core\Localization\LanguageService\sL
‪string sL($input)
Definition: LanguageService.php:158
‪TYPO3\CMS\Install\Service\ExtensionConfigurationService\parseComments
‪array parseComments($flatSetup)
Definition: ExtensionConfigurationService.php:240
‪TYPO3\CMS\Install\Service\ExtensionConfigurationService\extractInformationForConfigFieldsOfTypeUser
‪array extractInformationForConfigFieldsOfTypeUser(array $configurationOption)
Definition: ExtensionConfigurationService.php:180
‪TYPO3\CMS\Install\Service\ExtensionConfigurationService\getConfigurationPreparedForView
‪array getConfigurationPreparedForView(string $extensionKey)
Definition: ExtensionConfigurationService.php:78
‪TYPO3\CMS\Install\Service\ExtensionConfigurationService\getDefaultConfigurationFromExtConfTemplateAsValuedArray
‪array getDefaultConfigurationFromExtConfTemplateAsValuedArray(string $extensionKey)
Definition: ExtensionConfigurationService.php:212
‪TYPO3\CMS\Install\Service\ExtensionConfigurationService\getLanguageService
‪LanguageService getLanguageService()
Definition: ExtensionConfigurationService.php:346
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:23
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Install\Service\ExtensionConfigurationService\extractInformationForConfigFieldsOfTypeOptions
‪array extractInformationForConfigFieldsOfTypeOptions(array $configurationOption)
Definition: ExtensionConfigurationService.php:157
‪TYPO3\CMS\Install\Service\ExtensionConfigurationService\buildConfigurationArray
‪array buildConfigurationArray(array $configurationOption)
Definition: ExtensionConfigurationService.php:129
‪TYPO3\CMS\Install\Service\ExtensionConfigurationService\flattenSetup
‪array flattenSetup($setupArray, $prefix='')
Definition: ExtensionConfigurationService.php:328
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:29
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Install\Service
Definition: ClearCacheService.php:2