[BUGFIX] Extension Manager doesn't care about configuration sorting
[Packages/TYPO3.CMS.git] / typo3 / sysext / extensionmanager / Classes / Domain / Repository / ConfigurationItemRepository.php
1 <?php
2 namespace TYPO3\CMS\Extensionmanager\Domain\Repository;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2012 Susanne Moog, <typo3@susannemoog.de>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26 /**
27 * A repository for extension configuration items
28 *
29 * @author Susanne Moog <typo3@susannemoog.de>
30 */
31 class ConfigurationItemRepository {
32
33 /**
34 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
35 */
36 protected $objectManager;
37
38 /**
39 * @var \TYPO3\CMS\Core\Configuration\ConfigurationManager
40 */
41 protected $configurationManager;
42
43 /**
44 * Injects the object manager
45 *
46 * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
47 * @return void
48 */
49 public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager) {
50 $this->objectManager = $objectManager;
51 }
52
53 /**
54 * Inject configuration manager
55 *
56 * @param \TYPO3\CMS\Core\Configuration\ConfigurationManager $configurationManager
57 * @return void
58 */
59 public function injectConfigurationManager(\TYPO3\CMS\Core\Configuration\ConfigurationManager $configurationManager) {
60 $this->configurationManager = $configurationManager;
61 }
62
63 /**
64 * Find configuration options by extension
65 *
66 * @param array $extension array with extension information
67 * @return null|\SplObjectStorage
68 */
69 public function findByExtension(array $extension) {
70 $configRaw = \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl(PATH_site . $extension['siteRelPath'] . '/ext_conf_template.txt');
71 $configurationObjectStorage = NULL;
72 if ($configRaw) {
73 $configurationArray = $this->convertRawConfigurationToArray($configRaw, $extension);
74 $configurationObjectStorage = $this->convertHierarchicArrayToObject($configurationArray);
75 }
76 return $configurationObjectStorage;
77 }
78
79 /**
80 * Converts the raw configuration file content to an configuration object storage
81 *
82 * @param string $configRaw
83 * @param array $extension array with extension information
84 * @return array
85 */
86 protected function convertRawConfigurationToArray($configRaw, array $extension) {
87 $defaultConfiguration = $this->createArrayFromConstants($configRaw, $extension);
88 $metaInformation = $this->addMetaInformation($defaultConfiguration);
89 $configuration = $this->mergeWithExistingConfiguration($defaultConfiguration, $extension);
90 $hierarchicConfiguration = array();
91 foreach ($configuration as $configurationOption) {
92 $hierarchicConfiguration = \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule($this->buildConfigurationArray($configurationOption, $extension), $hierarchicConfiguration);
93 }
94
95 // Flip category array as it was merged the other way around
96 $hierarchicConfiguration = array_reverse($hierarchicConfiguration);
97
98 // Sort configurations of each subcategory
99 foreach ($hierarchicConfiguration as &$catConfigurationArray) {
100 foreach ($catConfigurationArray as &$subcatConfigurationArray) {
101 uasort($subcatConfigurationArray, function ($a, $b) {
102 return strnatcmp($a['subcat'], $b['subcat']);
103 });
104 }
105 unset($subcatConfigurationArray);
106 }
107 unset($tempConfiguration);
108
109 return \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule($hierarchicConfiguration, $metaInformation);
110 }
111
112 /**
113 * Builds a configuration array from each line (option) of the config file
114 *
115 * @param string $configurationOption config file line representing one setting
116 * @param array $extension
117 * @return array
118 */
119 protected function buildConfigurationArray($configurationOption, $extension) {
120 $hierarchicConfiguration = array();
121 if (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($configurationOption['type'], 'user')) {
122 $configurationOption = $this->extractInformationForConfigFieldsOfTypeUser($configurationOption);
123 } elseif (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($configurationOption['type'], 'options')) {
124 $configurationOption = $this->extractInformationForConfigFieldsOfTypeOptions($configurationOption);
125 }
126 if (\TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($configurationOption['label'], $extension['key'])) {
127 $configurationOption['label'] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($configurationOption['label'], $extension['key']);
128 }
129 $configurationOption['labels'] = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(':', $configurationOption['label'], FALSE, 2);
130 $configurationOption['subcat_name'] = $configurationOption['subcat_name'] ? $configurationOption['subcat_name'] : '__default';
131 $hierarchicConfiguration[$configurationOption['cat']][$configurationOption['subcat_name']][$configurationOption['name']] = $configurationOption;
132 return $hierarchicConfiguration;
133 }
134
135 /**
136 * Extracts additional information for fields of type "options"
137 * Extracts "type", "label" and values information
138 *
139 * @param array $configurationOption
140 * @return array
141 */
142 protected function extractInformationForConfigFieldsOfTypeOptions(array $configurationOption) {
143 preg_match('/options\[(.*)\]/is', $configurationOption['type'], $typeMatches);
144 $optionItems = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $typeMatches[1]);
145 foreach ($optionItems as $optionItem) {
146 $optionPair = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode('=', $optionItem);
147 if (count($optionPair) === 2) {
148 $configurationOption['generic'][$optionPair[0]] = $optionPair[1];
149 } else {
150 $configurationOption['generic'][$optionPair[0]] = $optionPair[0];
151 }
152 }
153 $configurationOption['type'] = 'options';
154 return $configurationOption;
155 }
156
157 /**
158 * Extract additional information for fields of type "user"
159 * Extracts "type" and the function to be called
160 *
161 * @param array $configurationOption
162 * @return array
163 */
164 protected function extractInformationForConfigFieldsOfTypeUser(array $configurationOption) {
165 preg_match('/user\\[(.*)\\]/is', $configurationOption['type'], $matches);
166 $configurationOption['generic'] = $matches[1];
167 $configurationOption['type'] = 'user';
168 return $configurationOption;
169 }
170
171 /**
172 * Gets meta information from configuration array and
173 * returns only the meta information
174 *
175 * @param array $configuration
176 * @return array
177 */
178 protected function addMetaInformation(&$configuration) {
179 $metaInformation = $configuration['__meta__'] ? $configuration['__meta__'] : array();
180 unset($configuration['__meta__']);
181 return $metaInformation;
182 }
183
184 /**
185 * Generate an array from the typoscript style constants
186 * Add meta data like TSConstantEditor comments
187 *
188 * @param string $configRaw
189 * @param array $extension
190 * @return array
191 */
192 public function createArrayFromConstants($configRaw, array $extension) {
193 $tsStyleConfig = $this->getT3libTsStyleConfig();
194 $tsStyleConfig->doNotSortCategoriesBeforeMakingForm = TRUE;
195 $theConstants = $tsStyleConfig->ext_initTSstyleConfig($configRaw, $extension['siteRelPath'], PATH_site . $extension['siteRelPath'], $GLOBALS['BACK_PATH']);
196 if (isset($tsStyleConfig->setup['constants']['TSConstantEditor.'])) {
197 foreach ($tsStyleConfig->setup['constants']['TSConstantEditor.'] as $category => $highlights) {
198 $theConstants['__meta__'][rtrim($category, '.')]['highlightText'] = $highlights['description'];
199 foreach ($highlights as $highlightNumber => $value) {
200 if (rtrim($category, '.') == $theConstants[$value]['cat']) {
201 $theConstants[$value]['highlight'] = $highlightNumber;
202 }
203 }
204 }
205 }
206 return $theConstants;
207 }
208
209 /**
210 * Wrapper for makeInstance to make it possible to mock
211 * the class
212 *
213 * @return \TYPO3\CMS\Core\TypoScript\ConfigurationForm
214 */
215 protected function getT3libTsStyleConfig() {
216 return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\ConfigurationForm');
217 }
218
219 /**
220 * Merge new configuration with existing configuration
221 *
222 * @param array $configuration the new configuration array
223 * @param array $extension the extension information
224 * @return array
225 */
226 protected function mergeWithExistingConfiguration(array $configuration, array $extension) {
227 try {
228 $currentExtensionConfig = unserialize(
229 $this->configurationManager->getConfigurationValueByPath(
230 'EXT/extConf/' . $extension['key']
231 )
232 );
233 } catch (\RuntimeException $e) {
234 $currentExtensionConfig = array();
235 }
236 $flatExtensionConfig = \TYPO3\CMS\Core\Utility\ArrayUtility::flatten($currentExtensionConfig);
237 $valuedCurrentExtensionConfig = array();
238 foreach ($flatExtensionConfig as $key => $value) {
239 $valuedCurrentExtensionConfig[$key]['value'] = $value;
240 }
241 $configuration = \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule($configuration, $valuedCurrentExtensionConfig);
242 return $configuration;
243 }
244
245 /**
246 * Converts a hierarchic configuration array to an
247 * hierarchic object storage structure
248 *
249 * @param array $configuration
250 * @return \SplObjectStorage
251 */
252 protected function convertHierarchicArrayToObject(array $configuration) {
253 $configurationObjectStorage = new \SplObjectStorage();
254 foreach ($configuration as $category => $subcategory) {
255 /** @var $configurationCategoryObject \TYPO3\CMS\Extensionmanager\Domain\Model\ConfigurationCategory */
256 $configurationCategoryObject = $this->objectManager->get('TYPO3\\CMS\\Extensionmanager\\Domain\\Model\\ConfigurationCategory');
257 $configurationCategoryObject->setName($category);
258 if ($subcategory['highlightText']) {
259 $configurationCategoryObject->setHighlightText($subcategory['highlightText']);
260 unset($subcategory['highlightText']);
261 }
262 foreach ($subcategory as $subcatName => $configurationItems) {
263 /** @var $configurationSubcategoryObject \TYPO3\CMS\Extensionmanager\Domain\Model\ConfigurationSubcategory */
264 $configurationSubcategoryObject = $this->objectManager->get('TYPO3\\CMS\\Extensionmanager\\Domain\\Model\\ConfigurationSubcategory');
265 $configurationSubcategoryObject->setName($subcatName);
266 foreach ($configurationItems as $configurationItem) {
267 /** @var $configurationObject \TYPO3\CMS\Extensionmanager\Domain\Model\ConfigurationItem */
268 $configurationObject = $this->objectManager->get('TYPO3\\CMS\\Extensionmanager\\Domain\\Model\\ConfigurationItem');
269 if (isset($configurationItem['generic'])) {
270 $configurationObject->setGeneric($configurationItem['generic']);
271 }
272 if (isset($configurationItem['cat'])) {
273 $configurationObject->setCategory($configurationItem['cat']);
274 }
275 if (isset($configurationItem['subcat_name'])) {
276 $configurationObject->setSubCategory($configurationItem['subcat_name']);
277 }
278 if (isset($configurationItem['labels']) && isset($configurationItem['labels'][0])) {
279 $configurationObject->setLabelHeadline($configurationItem['labels'][0]);
280 }
281 if (isset($configurationItem['labels']) && isset($configurationItem['labels'][1])) {
282 $configurationObject->setLabelText($configurationItem['labels'][1]);
283 }
284 if (isset($configurationItem['type'])) {
285 $configurationObject->setType($configurationItem['type']);
286 }
287 if (isset($configurationItem['name'])) {
288 $configurationObject->setName($configurationItem['name']);
289 }
290 if (isset($configurationItem['value'])) {
291 $configurationObject->setValue($configurationItem['value']);
292 }
293 if (isset($configurationItem['highlight'])) {
294 $configurationObject->setHighlight($configurationItem['highlight']);
295 }
296 $configurationSubcategoryObject->addItem($configurationObject);
297 }
298 $configurationCategoryObject->addSubcategory($configurationSubcategoryObject);
299 }
300 $configurationObjectStorage->attach($configurationCategoryObject);
301 }
302 return $configurationObjectStorage;
303 }
304
305 }
306
307
308 ?>