ConfigReverter.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <?php
  2. namespace Drupal\config_update;
  3. use Drupal\Core\Config\StorageInterface;
  4. use Drupal\Core\Config\ConfigFactoryInterface;
  5. use Drupal\Core\Entity\EntityTypeManagerInterface;
  6. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  7. /**
  8. * Provides methods related to config reverting, deleting, and importing.
  9. *
  10. * In this class, when any import or revert operation is requested, the
  11. * configuration that is being reverted or imported is searched for in both the
  12. * config/install repository and config/optional. This happens automatically.
  13. */
  14. class ConfigReverter implements ConfigRevertInterface, ConfigDeleteInterface {
  15. /**
  16. * The entity manager.
  17. *
  18. * @var \Drupal\Core\Entity\EntityManagerInterface
  19. */
  20. protected $entityManager;
  21. /**
  22. * The active config storage.
  23. *
  24. * @var \Drupal\Core\Config\StorageInterface
  25. */
  26. protected $activeConfigStorage;
  27. /**
  28. * The extension config storage for config/install config items.
  29. *
  30. * @var \Drupal\Core\Config\StorageInterface
  31. */
  32. protected $extensionConfigStorage;
  33. /**
  34. * The extension config storage for config/optional config items.
  35. *
  36. * @var \Drupal\Core\Config\ExtensionInstallStorage
  37. */
  38. protected $extensionOptionalConfigStorage;
  39. /**
  40. * The config factory.
  41. *
  42. * @var \Drupal\Core\Config\ConfigFactoryInterface
  43. */
  44. protected $configFactory;
  45. /**
  46. * The event dispatcher.
  47. *
  48. * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
  49. */
  50. protected $dispatcher;
  51. /**
  52. * Constructs a ConfigReverter.
  53. *
  54. * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_manager
  55. * The entity manager.
  56. * @param \Drupal\Core\Config\StorageInterface $active_config_storage
  57. * The active config storage.
  58. * @param \Drupal\Core\Config\StorageInterface $extension_config_storage
  59. * The extension config storage.
  60. * @param \Drupal\Core\Config\StorageInterface $extension_optional_config_storage
  61. * The extension config storage for optional config items.
  62. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
  63. * The config factory.
  64. * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher
  65. * The event dispatcher.
  66. */
  67. public function __construct(EntityTypeManagerInterface $entity_manager, StorageInterface $active_config_storage, StorageInterface $extension_config_storage, StorageInterface $extension_optional_config_storage, ConfigFactoryInterface $config_factory, EventDispatcherInterface $dispatcher) {
  68. $this->entityManager = $entity_manager;
  69. $this->activeConfigStorage = $active_config_storage;
  70. $this->extensionConfigStorage = $extension_config_storage;
  71. $this->extensionOptionalConfigStorage = $extension_optional_config_storage;
  72. $this->configFactory = $config_factory;
  73. $this->dispatcher = $dispatcher;
  74. }
  75. /**
  76. * {@inheritdoc}
  77. */
  78. public function import($type, $name) {
  79. // Read the config from the file. Note: Do not call getFromExtension() here
  80. // because we need $full_name below.
  81. $full_name = $this->getFullName($type, $name);
  82. $value = FALSE;
  83. if ($full_name) {
  84. $value = $this->extensionConfigStorage->read($full_name);
  85. if (!$value) {
  86. $value = $this->extensionOptionalConfigStorage->read($full_name);
  87. }
  88. }
  89. if (!$value) {
  90. return FALSE;
  91. }
  92. // Save it as a new config entity or simple config.
  93. if ($type == 'system.simple') {
  94. $this->configFactory->getEditable($full_name)->setData($value)->save();
  95. }
  96. else {
  97. $entity_storage = $this->entityManager->getStorage($type);
  98. $entity = $entity_storage->createFromStorageRecord($value);
  99. $entity->save();
  100. }
  101. // Trigger an event notifying of this change.
  102. $event = new ConfigRevertEvent($type, $name);
  103. $this->dispatcher->dispatch(ConfigRevertInterface::IMPORT, $event);
  104. return TRUE;
  105. }
  106. /**
  107. * {@inheritdoc}
  108. */
  109. public function revert($type, $name) {
  110. // Read the config from the file. Note: Do not call getFromExtension() here
  111. // because we need $full_name below.
  112. $value = FALSE;
  113. $full_name = $this->getFullName($type, $name);
  114. if ($full_name) {
  115. $value = $this->extensionConfigStorage->read($full_name);
  116. if (!$value) {
  117. $value = $this->extensionOptionalConfigStorage->read($full_name);
  118. }
  119. }
  120. if (!$value) {
  121. return FALSE;
  122. }
  123. // Make sure the configuration exists currently in active storage.
  124. if (!$this->activeConfigStorage->read($full_name)) {
  125. return FALSE;
  126. }
  127. // Load the current config and replace the value, retaining the config
  128. // hash (which is part of the _core config key's value).
  129. if ($type == 'system.simple') {
  130. $config = $this->configFactory->getEditable($full_name);
  131. $core = $config->get('_core');
  132. $config
  133. ->setData($value)
  134. ->set('_core', $core)
  135. ->save();
  136. }
  137. else {
  138. $definition = $this->entityManager->getDefinition($type);
  139. $id_key = $definition->getKey('id');
  140. $id = $value[$id_key];
  141. $entity_storage = $this->entityManager->getStorage($type);
  142. $entity = $entity_storage->load($id);
  143. $core = $entity->get('_core');
  144. $entity = $entity_storage->updateFromStorageRecord($entity, $value);
  145. $entity->set('_core', $core);
  146. $entity->save();
  147. }
  148. // Trigger an event notifying of this change.
  149. $event = new ConfigRevertEvent($type, $name);
  150. $this->dispatcher->dispatch(ConfigRevertInterface::REVERT, $event);
  151. return TRUE;
  152. }
  153. /**
  154. * {@inheritdoc}
  155. */
  156. public function delete($type, $name) {
  157. $config = FALSE;
  158. $full_name = $this->getFullName($type, $name);
  159. if ($full_name) {
  160. // Make sure the configuration exists currently in active storage.
  161. if (!$this->activeConfigStorage->read($full_name)) {
  162. return FALSE;
  163. }
  164. $config = $this->configFactory->getEditable($full_name);
  165. }
  166. if (!$config) {
  167. return FALSE;
  168. }
  169. $config->delete();
  170. // Trigger an event notifying of this change.
  171. $event = new ConfigRevertEvent($type, $name);
  172. $this->dispatcher->dispatch(ConfigDeleteInterface::DELETE, $event);
  173. return TRUE;
  174. }
  175. /**
  176. * {@inheritdoc}
  177. */
  178. public function getFromActive($type, $name) {
  179. $full_name = $this->getFullName($type, $name);
  180. if ($full_name) {
  181. return $this->activeConfigStorage->read($full_name);
  182. }
  183. return FALSE;
  184. }
  185. /**
  186. * {@inheritdoc}
  187. */
  188. public function getFromExtension($type, $name) {
  189. $value = FALSE;
  190. $full_name = $this->getFullName($type, $name);
  191. if ($full_name) {
  192. $value = $this->extensionConfigStorage->read($full_name);
  193. if (!$value) {
  194. $value = $this->extensionOptionalConfigStorage->read($full_name);
  195. }
  196. }
  197. return $value;
  198. }
  199. /**
  200. * Returns the full name of a config item.
  201. *
  202. * @param string $type
  203. * The config type, or '' to indicate $name is already prefixed.
  204. * @param string $name
  205. * The config name, without prefix.
  206. *
  207. * @return string
  208. * The config item's full name, or FALSE if there is an error.
  209. */
  210. protected function getFullName($type, $name) {
  211. if ($type == 'system.simple' || !$type) {
  212. return $name;
  213. }
  214. $definition = $this->entityManager->getDefinition($type);
  215. if ($definition) {
  216. $prefix = $definition->getConfigPrefix() . '.';
  217. return $prefix . $name;
  218. }
  219. else {
  220. return FALSE;
  221. }
  222. }
  223. }