ExportStorageManager.php 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. <?php
  2. namespace Drupal\Core\Config;
  3. use Drupal\Core\Database\Connection;
  4. use Drupal\Core\Lock\LockBackendInterface;
  5. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  6. /**
  7. * The export storage manager dispatches an event for the export storage.
  8. *
  9. * This class is not meant to be extended and is final to make sure the
  10. * constructor and the getStorage method are both changed when this pattern is
  11. * used in other circumstances.
  12. */
  13. final class ExportStorageManager implements StorageManagerInterface {
  14. use StorageCopyTrait;
  15. /**
  16. * The name used to identify the lock.
  17. */
  18. const LOCK_NAME = 'config_storage_export_manager';
  19. /**
  20. * The active configuration storage.
  21. *
  22. * @var \Drupal\Core\Config\StorageInterface
  23. */
  24. protected $active;
  25. /**
  26. * The database storage.
  27. *
  28. * @var \Drupal\Core\Config\DatabaseStorage
  29. */
  30. protected $storage;
  31. /**
  32. * The event dispatcher.
  33. *
  34. * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
  35. */
  36. protected $eventDispatcher;
  37. /**
  38. * The used lock backend instance.
  39. *
  40. * @var \Drupal\Core\Lock\LockBackendInterface
  41. */
  42. protected $lock;
  43. /**
  44. * ExportStorageManager constructor.
  45. *
  46. * @param \Drupal\Core\Config\StorageInterface $active
  47. * The active config storage to prime the export storage.
  48. * @param \Drupal\Core\Database\Connection $connection
  49. * The database connection.
  50. * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
  51. * The event dispatcher.
  52. * @param \Drupal\Core\Lock\LockBackendInterface $lock
  53. * The used lock backend instance.
  54. */
  55. public function __construct(StorageInterface $active, Connection $connection, EventDispatcherInterface $event_dispatcher, LockBackendInterface $lock) {
  56. $this->active = $active;
  57. $this->eventDispatcher = $event_dispatcher;
  58. $this->lock = $lock;
  59. // The point of this service is to provide the storage and dispatch the
  60. // event when needed, so the storage itself can not be a service.
  61. $this->storage = new DatabaseStorage($connection, 'config_export');
  62. }
  63. /**
  64. * {@inheritdoc}
  65. */
  66. public function getStorage() {
  67. // Acquire a lock for the request to assert that the storage does not change
  68. // when a concurrent request transforms the storage.
  69. if (!$this->lock->acquire(self::LOCK_NAME)) {
  70. $this->lock->wait(self::LOCK_NAME);
  71. if (!$this->lock->acquire(self::LOCK_NAME)) {
  72. throw new StorageTransformerException("Cannot acquire config export transformer lock.");
  73. }
  74. }
  75. self::replaceStorageContents($this->active, $this->storage);
  76. $this->eventDispatcher->dispatch(ConfigEvents::STORAGE_TRANSFORM_EXPORT, new StorageTransformEvent($this->storage));
  77. return new ReadOnlyStorage($this->storage);
  78. }
  79. }