vendor/pimcore/pimcore/lib/Extension/Bundle/Config/StateConfig.php line 91

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * Pimcore
  5. *
  6. * This source file is available under two different licenses:
  7. * - GNU General Public License version 3 (GPLv3)
  8. * - Pimcore Commercial License (PCL)
  9. * Full copyright and license information is available in
  10. * LICENSE.md which is distributed with this source code.
  11. *
  12. * @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  13. * @license http://www.pimcore.org/license GPLv3 and PCL
  14. */
  15. namespace Pimcore\Extension\Bundle\Config;
  16. use Pimcore\Config as PimcoreConfig;
  17. use Pimcore\Extension\Config;
  18. use Symfony\Component\OptionsResolver\Options;
  19. use Symfony\Component\OptionsResolver\OptionsResolver;
  20. /**
  21. * @internal
  22. */
  23. final class StateConfig
  24. {
  25. /**
  26. * @var OptionsResolver
  27. */
  28. private static $optionsResolver;
  29. /**
  30. * @var array
  31. */
  32. private static $optionDefaults = [
  33. 'enabled' => false,
  34. 'priority' => 10,
  35. 'environments' => [],
  36. ];
  37. /**
  38. * @var Config
  39. */
  40. private $config;
  41. /**
  42. * @param Config $config
  43. */
  44. public function __construct(Config $config)
  45. {
  46. $this->config = $config;
  47. }
  48. /**
  49. * Lists enabled bundles from config
  50. *
  51. * @return array
  52. */
  53. public function getEnabledBundles(): array
  54. {
  55. $result = [];
  56. $bundles = $this->getBundlesFromConfig();
  57. foreach ($bundles as $bundleName => $options) {
  58. if ($options['enabled']) {
  59. $result[$bundleName] = $options;
  60. }
  61. }
  62. return $result;
  63. }
  64. /**
  65. * Lists enabled bundle names from config
  66. *
  67. * @return array
  68. */
  69. public function getEnabledBundleNames(): array
  70. {
  71. return array_keys($this->getEnabledBundles());
  72. }
  73. /**
  74. * Loads bundles which are defined in configuration
  75. *
  76. * @return array
  77. */
  78. private function getBundlesFromConfig(): array
  79. {
  80. $config = $this->config->loadConfig();
  81. if (!isset($config->bundle)) {
  82. return [];
  83. }
  84. $bundles = $config->bundle->toArray();
  85. $result = [];
  86. foreach ($bundles as $bundleName => $options) {
  87. $result[$bundleName] = $this->normalizeOptions($options);
  88. }
  89. return $result;
  90. }
  91. /**
  92. * Returns the normalized bundle state from the extension manager config
  93. *
  94. * @param string $bundle
  95. *
  96. * @return array
  97. */
  98. public function getState(string $bundle): array
  99. {
  100. $bundles = $this->getBundlesFromConfig();
  101. if (isset($bundles[$bundle])) {
  102. return $bundles[$bundle];
  103. }
  104. return $this->normalizeOptions([]);
  105. }
  106. /**
  107. * Sets the normalized bundle state on the extension manager config
  108. *
  109. * @param string $bundle
  110. * @param array $options
  111. */
  112. public function setState(string $bundle, array $options)
  113. {
  114. $config = $this->config->loadConfig();
  115. $this->updateBundleState($config, $bundle, $options);
  116. $this->config->saveConfig($config);
  117. }
  118. /**
  119. * Batch update bundle states
  120. *
  121. * @param array $states
  122. */
  123. public function setStates(array $states)
  124. {
  125. $config = $this->config->loadConfig();
  126. foreach ($states as $bundle => $options) {
  127. $this->updateBundleState($config, $bundle, $options);
  128. }
  129. $this->config->saveConfig($config);
  130. }
  131. private function updateBundleState(PimcoreConfig\Config $config, string $bundle, array $options)
  132. {
  133. if (!isset($config->bundle)) {
  134. $config->bundle = new PimcoreConfig\Config([], true);
  135. }
  136. $state = [];
  137. if (isset($config->bundle->$bundle)) {
  138. $currentState = $config->bundle->$bundle;
  139. if ($currentState instanceof PimcoreConfig\Config) {
  140. $currentState = $currentState->toArray();
  141. }
  142. $state = $this->normalizeOptions($currentState);
  143. }
  144. $state = array_merge($state, $options);
  145. $state = $this->prepareWriteOptions($state);
  146. $config->bundle->$bundle = $state;
  147. }
  148. /**
  149. * Prepares options for writing. If all options besides enabled are the same as the default
  150. * value, just the state will be written as bool,
  151. *
  152. * @param array $options
  153. *
  154. * @return array|bool
  155. */
  156. private function prepareWriteOptions(array $options)
  157. {
  158. $options = $this->normalizeOptions($options);
  159. $isDefault = true;
  160. foreach (array_keys(self::$optionDefaults) as $option) {
  161. if ('enabled' === $option) {
  162. continue;
  163. }
  164. if ($options[$option] !== static::$optionDefaults[$option]) {
  165. $isDefault = false;
  166. break;
  167. }
  168. }
  169. if ($isDefault) {
  170. return $options['enabled'];
  171. }
  172. return $options;
  173. }
  174. /**
  175. * Normalizes options array as expected in extension manager config
  176. *
  177. * @param array|bool $options
  178. *
  179. * @return array
  180. */
  181. public function normalizeOptions($options): array
  182. {
  183. if (is_bool($options)) {
  184. $options = ['enabled' => $options];
  185. } elseif (!is_array($options)) {
  186. throw new \InvalidArgumentException(sprintf(
  187. 'Expected options as bool or as array, but got %s',
  188. get_debug_type($options)
  189. ));
  190. }
  191. $resolver = self::getOptionsResolver();
  192. $options = $resolver->resolve($options);
  193. return $options;
  194. }
  195. private static function getOptionsResolver(): OptionsResolver
  196. {
  197. if (null !== self::$optionsResolver) {
  198. return self::$optionsResolver;
  199. }
  200. $resolver = new OptionsResolver();
  201. $resolver->setDefaults(self::$optionDefaults);
  202. $resolver->setRequired(array_keys(self::$optionDefaults));
  203. $resolver->setAllowedTypes('enabled', 'bool');
  204. $resolver->setAllowedTypes('priority', 'int');
  205. $resolver->setAllowedTypes('environments', 'array');
  206. $resolver->setNormalizer('environments', function (Options $options, $value) {
  207. // normalize to string and trim
  208. $value = array_map(function ($item) {
  209. $item = (string)$item;
  210. $item = trim($item);
  211. return $item;
  212. }, $value);
  213. // remove empty values
  214. $value = array_filter($value, function ($item) {
  215. return !empty($item);
  216. });
  217. return $value;
  218. });
  219. self::$optionsResolver = $resolver;
  220. return self::$optionsResolver;
  221. }
  222. }