1<?php 2 3namespace Drupal\KernelTests\Core\Config\Entity; 4 5use Drupal\Core\Config\Entity\ConfigEntityUpdater; 6use Drupal\Core\Site\Settings; 7use Drupal\KernelTests\KernelTestBase; 8 9/** 10 * Tests \Drupal\Core\Config\Entity\ConfigEntityUpdater. 11 * 12 * @coversDefaultClass \Drupal\Core\Config\Entity\ConfigEntityUpdater 13 * @group config 14 */ 15class ConfigEntityUpdaterTest extends KernelTestBase { 16 17 /** 18 * Modules to enable. 19 * 20 * @var array 21 */ 22 protected static $modules = ['config_test']; 23 24 /** 25 * @covers ::update 26 */ 27 public function testUpdate() { 28 // Create some entities to update. 29 $storage = $this->container->get('entity_type.manager')->getStorage('config_test'); 30 for ($i = 0; $i < 15; $i++) { 31 $entity_id = 'config_test_' . $i; 32 $storage->create(['id' => $entity_id, 'label' => $entity_id])->save(); 33 } 34 35 // Set up the updater. 36 $sandbox = []; 37 $settings = Settings::getInstance() ? Settings::getAll() : []; 38 $settings['entity_update_batch_size'] = 10; 39 new Settings($settings); 40 $updater = $this->container->get('class_resolver')->getInstanceFromDefinition(ConfigEntityUpdater::class); 41 42 $callback = function ($config_entity) { 43 /** @var \Drupal\config_test\Entity\ConfigTest $config_entity */ 44 $number = (int) str_replace('config_test_', '', $config_entity->id()); 45 // Only update even numbered entities. 46 if ($number % 2 == 0) { 47 $config_entity->set('label', $config_entity->label . ' (updated)'); 48 return TRUE; 49 } 50 return FALSE; 51 }; 52 53 // This should run against the first 10 entities. The even numbered labels 54 // will have been updated. 55 $updater->update($sandbox, 'config_test', $callback); 56 $entities = $storage->loadMultiple(); 57 $this->assertEquals('config_test_8 (updated)', $entities['config_test_8']->label()); 58 $this->assertEquals('config_test_9', $entities['config_test_9']->label()); 59 $this->assertEquals('config_test_10', $entities['config_test_10']->label()); 60 $this->assertEquals('config_test_14', $entities['config_test_14']->label()); 61 $this->assertEquals(15, $sandbox['config_entity_updater']['count']); 62 $this->assertEquals('config_test', $sandbox['config_entity_updater']['entity_type']); 63 $this->assertCount(5, $sandbox['config_entity_updater']['entities']); 64 $this->assertEquals(10 / 15, $sandbox['#finished']); 65 66 // Update the rest. 67 $updater->update($sandbox, 'config_test', $callback); 68 $entities = $storage->loadMultiple(); 69 $this->assertEquals('config_test_8 (updated)', $entities['config_test_8']->label()); 70 $this->assertEquals('config_test_9', $entities['config_test_9']->label()); 71 $this->assertEquals('config_test_10 (updated)', $entities['config_test_10']->label()); 72 $this->assertEquals('config_test_14 (updated)', $entities['config_test_14']->label()); 73 $this->assertEquals(1, $sandbox['#finished']); 74 $this->assertCount(0, $sandbox['config_entity_updater']['entities']); 75 } 76 77 /** 78 * @covers ::update 79 */ 80 public function testUpdateDefaultCallback() { 81 // Create some entities to update. 82 $storage = $this->container->get('entity_type.manager')->getStorage('config_test'); 83 for ($i = 0; $i < 15; $i++) { 84 $entity_id = 'config_test_' . $i; 85 $storage->create(['id' => $entity_id, 'label' => $entity_id])->save(); 86 } 87 88 // Set up the updater. 89 $sandbox = []; 90 $settings = Settings::getInstance() ? Settings::getAll() : []; 91 $settings['entity_update_batch_size'] = 9; 92 new Settings($settings); 93 $updater = $this->container->get('class_resolver')->getInstanceFromDefinition(ConfigEntityUpdater::class); 94 // Cause a dependency to be added during an update. 95 \Drupal::state()->set('config_test_new_dependency', 'added_dependency'); 96 97 // This should run against the first 10 entities. 98 $updater->update($sandbox, 'config_test'); 99 $entities = $storage->loadMultiple(); 100 $this->assertEquals(['added_dependency'], $entities['config_test_7']->getDependencies()['module']); 101 $this->assertEquals(['added_dependency'], $entities['config_test_8']->getDependencies()['module']); 102 $this->assertEquals([], $entities['config_test_9']->getDependencies()); 103 $this->assertEquals([], $entities['config_test_14']->getDependencies()); 104 $this->assertEquals(15, $sandbox['config_entity_updater']['count']); 105 $this->assertCount(6, $sandbox['config_entity_updater']['entities']); 106 $this->assertEquals(9 / 15, $sandbox['#finished']); 107 108 // Update the rest. 109 $updater->update($sandbox, 'config_test'); 110 $entities = $storage->loadMultiple(); 111 $this->assertEquals(['added_dependency'], $entities['config_test_9']->getDependencies()['module']); 112 $this->assertEquals(['added_dependency'], $entities['config_test_14']->getDependencies()['module']); 113 $this->assertEquals(1, $sandbox['#finished']); 114 $this->assertCount(0, $sandbox['config_entity_updater']['entities']); 115 } 116 117 /** 118 * @covers ::update 119 */ 120 public function testUpdateException() { 121 $this->enableModules(['entity_test']); 122 $this->expectException(\InvalidArgumentException::class); 123 $this->expectExceptionMessage('The provided entity type ID \'entity_test_mul_changed\' is not a configuration entity type'); 124 $updater = $this->container->get('class_resolver')->getInstanceFromDefinition(ConfigEntityUpdater::class); 125 $sandbox = []; 126 $updater->update($sandbox, 'entity_test_mul_changed'); 127 } 128 129 /** 130 * @covers ::update 131 */ 132 public function testUpdateOncePerUpdateException() { 133 $this->expectException(\RuntimeException::class); 134 $this->expectExceptionMessage('Updating multiple entity types in the same update function is not supported'); 135 $updater = $this->container->get('class_resolver')->getInstanceFromDefinition(ConfigEntityUpdater::class); 136 $sandbox = []; 137 $updater->update($sandbox, 'config_test'); 138 $updater->update($sandbox, 'config_query_test'); 139 } 140 141} 142