From 4e89e7e81bac73112743c27a0ea018ed11dd4b77 Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Mon, 6 Mar 2023 11:09:39 +0000 Subject: [PATCH] Issue #3224239 by bircher, rpayanm, smustgrave: StorageComparer does not work when storages are not in the default collection (cherry picked from commit c48da9e7a7e885a757fc24b67185b2c995736a8c) --- .../Drupal/Core/Config/StorageComparer.php | 7 +++ .../Tests/Core/Config/StorageComparerTest.php | 62 +++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/core/lib/Drupal/Core/Config/StorageComparer.php b/core/lib/Drupal/Core/Config/StorageComparer.php index c7ccc6b0fa38..51f7bec937dd 100644 --- a/core/lib/Drupal/Core/Config/StorageComparer.php +++ b/core/lib/Drupal/Core/Config/StorageComparer.php @@ -90,6 +90,13 @@ class StorageComparer implements StorageComparerInterface { * Storage object used to write configuration. */ public function __construct(StorageInterface $source_storage, StorageInterface $target_storage) { + if ($source_storage->getCollectionName() !== StorageInterface::DEFAULT_COLLECTION) { + $source_storage = $source_storage->createCollection(StorageInterface::DEFAULT_COLLECTION); + } + if ($target_storage->getCollectionName() !== StorageInterface::DEFAULT_COLLECTION) { + $target_storage = $target_storage->createCollection(StorageInterface::DEFAULT_COLLECTION); + } + // Wrap the storages in a static cache so that multiple reads of the same // raw configuration object are not costly. $this->sourceCacheStorage = new MemoryBackend(); diff --git a/core/tests/Drupal/Tests/Core/Config/StorageComparerTest.php b/core/tests/Drupal/Tests/Core/Config/StorageComparerTest.php index 6d85e64e3743..f20d9f89b109 100644 --- a/core/tests/Drupal/Tests/Core/Config/StorageComparerTest.php +++ b/core/tests/Drupal/Tests/Core/Config/StorageComparerTest.php @@ -3,7 +3,9 @@ namespace Drupal\Tests\Core\Config; use Drupal\Component\Uuid\Php; +use Drupal\Core\Config\MemoryStorage; use Drupal\Core\Config\StorageComparer; +use Drupal\Core\Config\StorageInterface; use Drupal\Tests\UnitTestCase; /** @@ -42,6 +44,14 @@ class StorageComparerTest extends UnitTestCase { protected function setUp(): void { $this->sourceStorage = $this->createMock('Drupal\Core\Config\StorageInterface'); $this->targetStorage = $this->createMock('Drupal\Core\Config\StorageInterface'); + + $this->sourceStorage->expects($this->atLeastOnce()) + ->method('getCollectionName') + ->will($this->returnValue(StorageInterface::DEFAULT_COLLECTION)); + $this->targetStorage->expects($this->atLeastOnce()) + ->method('getCollectionName') + ->will($this->returnValue(StorageInterface::DEFAULT_COLLECTION)); + $this->storageComparer = new StorageComparer($this->sourceStorage, $this->targetStorage); } @@ -241,4 +251,56 @@ public function testCreateChangelistUpdate() { $this->assertEmpty($this->storageComparer->getChangelist('delete')); } + /** + * @covers ::createChangelist + */ + public function testDifferentCollections() { + $source = new MemoryStorage(); + $target = new MemoryStorage(); + + $this->generateRandomData($source, 's'); + $this->generateRandomData($target, 't'); + + // Use random collections for source and target. + $collections = $source->getAllCollectionNames(); + $source = $source->createCollection($collections[array_rand($collections)]); + $collections = $target->getAllCollectionNames(); + $target = $target->createCollection($collections[array_rand($collections)]); + + $comparer = new StorageComparer($source, $target); + $comparer->createChangelist(); + + foreach (array_merge([StorageInterface::DEFAULT_COLLECTION], $source->getAllCollectionNames(), $target->getAllCollectionNames()) as $collection) { + $expected = [ + 'create' => $source->createCollection($collection)->listAll(), + 'update' => [], + 'delete' => $target->createCollection($collection)->listAll(), + 'rename' => [], + ]; + + $this->assertEqualsCanonicalizing($expected, $comparer->getChangelist(NULL, $collection)); + } + } + + /** + * Generate random data in a config storage. + * + * @param \Drupal\Core\Config\StorageInterface $storage + * The storage to populate with random data. + * @param string $prefix + * The prefix for random names to make sure they are unique. + */ + protected function generateRandomData(StorageInterface $storage, string $prefix = '') { + $generator = $this->getRandomGenerator(); + for ($i = 0; $i < rand(2, 10); $i++) { + $storage->write($prefix . $this->randomMachineName(), (array) $generator->object()); + } + for ($i = 0; $i < rand(1, 5); $i++) { + $collection = $storage->createCollection($prefix . $this->randomMachineName()); + for ($i = 0; $i < rand(2, 10); $i++) { + $collection->write($prefix . $this->randomMachineName(), (array) $generator->object()); + } + } + } + } -- GitLab