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