ddc52fe52cd4ff261317bde01b1d7e68afa74f82
[yaffs-website] / web / core / modules / system / src / Tests / Entity / Update / UpdateApiEntityDefinitionUpdateTest.php
1 <?php
2
3 namespace Drupal\system\Tests\Entity\Update;
4
5 use Drupal\Core\Entity\Exception\FieldStorageDefinitionUpdateForbiddenException;
6 use Drupal\entity_test\Entity\EntityTest;
7 use Drupal\simpletest\WebTestBase;
8 use Drupal\system\Tests\Update\DbUpdatesTrait;
9
10 /**
11  * Tests performing entity updates through the Update API.
12  *
13  * @group Entity
14  */
15 class UpdateApiEntityDefinitionUpdateTest extends WebTestBase {
16
17   use DbUpdatesTrait;
18
19   /**
20    * {@inheritdoc}
21    */
22   protected static $modules = ['entity_test'];
23
24   /**
25    * The entity manager.
26    *
27    * @var \Drupal\Core\Entity\EntityManagerInterface
28    */
29   protected $entityManager;
30
31   /**
32    * The entity definition update manager.
33    *
34    * @var \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface
35    */
36   protected $updatesManager;
37
38
39   /**
40    * {@inheritdoc}
41    */
42   protected function setUp() {
43     parent::setUp();
44
45     $this->entityManager = $this->container->get('entity.manager');
46     $this->updatesManager = $this->container->get('entity.definition_update_manager');
47
48     $admin = $this->drupalCreateUser([], FALSE, TRUE);
49     $this->drupalLogin($admin);
50   }
51
52   /**
53    * Tests that individual updates applied sequentially work as expected.
54    */
55   public function testSingleUpdates() {
56     // Create a test entity.
57     $user_ids = [mt_rand(), mt_rand()];
58     $entity = EntityTest::create(['name' => $this->randomString(), 'user_id' => $user_ids]);
59     $entity->save();
60
61     // Check that only a single value is stored for 'user_id'.
62     $entity = $this->reloadEntity($entity);
63     $this->assertEqual(count($entity->user_id), 1);
64     $this->assertEqual($entity->user_id->target_id, $user_ids[0]);
65
66     // Make 'user_id' multiple by applying updates.
67     $this->enableUpdates('entity_test', 'entity_definition_updates', 8001);
68     $this->applyUpdates();
69
70     // Ensure the 'entity_test__user_id' table got created.
71     $this->assertTrue(\Drupal::database()->schema()->tableExists('entity_test__user_id'));
72
73     // Check that data was correctly migrated.
74     $entity = $this->reloadEntity($entity);
75     $this->assertEqual(count($entity->user_id), 1);
76     $this->assertEqual($entity->user_id->target_id, $user_ids[0]);
77
78     // Store multiple data and check it is correctly stored.
79     $entity->user_id = $user_ids;
80     $entity->save();
81     $entity = $this->reloadEntity($entity);
82     $this->assertEqual(count($entity->user_id), 2);
83     $this->assertEqual($entity->user_id[0]->target_id, $user_ids[0]);
84     $this->assertEqual($entity->user_id[1]->target_id, $user_ids[1]);
85
86     // Make 'user_id' single again by applying updates.
87     $this->enableUpdates('entity_test', 'entity_definition_updates', 8002);
88     $this->applyUpdates();
89
90     // Check that data was correctly migrated/dropped.
91     $entity = $this->reloadEntity($entity);
92     $this->assertEqual(count($entity->user_id), 1);
93     $this->assertEqual($entity->user_id->target_id, $user_ids[0]);
94
95     // Check that only a single value is stored for 'user_id' again.
96     $entity->user_id = $user_ids;
97     $entity->save();
98     $entity = $this->reloadEntity($entity);
99     $this->assertEqual(count($entity->user_id), 1);
100     $this->assertEqual($entity->user_id[0]->target_id, $user_ids[0]);
101   }
102
103   /**
104    * Tests that multiple updates applied in bulk work as expected.
105    */
106   public function testMultipleUpdates() {
107     // Create a test entity.
108     $user_ids = [mt_rand(), mt_rand()];
109     $entity = EntityTest::create(['name' => $this->randomString(), 'user_id' => $user_ids]);
110     $entity->save();
111
112     // Check that only a single value is stored for 'user_id'.
113     $entity = $this->reloadEntity($entity);
114     $this->assertEqual(count($entity->user_id), 1);
115     $this->assertEqual($entity->user_id->target_id, $user_ids[0]);
116
117     // Make 'user_id' multiple and then single again by applying updates.
118     $this->enableUpdates('entity_test', 'entity_definition_updates', 8002);
119     $this->applyUpdates();
120
121     // Check that data was correctly migrated back and forth.
122     $entity = $this->reloadEntity($entity);
123     $this->assertEqual(count($entity->user_id), 1);
124     $this->assertEqual($entity->user_id->target_id, $user_ids[0]);
125
126     // Check that only a single value is stored for 'user_id' again.
127     $entity->user_id = $user_ids;
128     $entity->save();
129     $entity = $this->reloadEntity($entity);
130     $this->assertEqual(count($entity->user_id), 1);
131     $this->assertEqual($entity->user_id[0]->target_id, $user_ids[0]);
132   }
133
134   /**
135    * Tests that entity updates are correctly reported in the status report page.
136    */
137   public function testStatusReport() {
138     // Create a test entity.
139     $entity = EntityTest::create(['name' => $this->randomString(), 'user_id' => mt_rand()]);
140     $entity->save();
141
142     // Check that the status report initially displays no error.
143     $this->drupalGet('admin/reports/status');
144     $this->assertNoRaw('Out of date');
145     $this->assertNoRaw('Mismatched entity and/or field definitions');
146
147     // Enable an entity update and check that we have a dedicated status report
148     // item.
149     $this->container->get('state')->set('entity_test.remove_name_field', TRUE);
150     $this->drupalGet('admin/reports/status');
151     $this->assertNoRaw('Out of date');
152     $this->assertRaw('Mismatched entity and/or field definitions');
153
154     // Enable a db update and check that now the entity update status report
155     // item is no longer displayed. We assume an update function will fix the
156     // mismatch.
157     $this->enableUpdates('entity_test', 'status_report', 8001);
158     $this->drupalGet('admin/reports/status');
159     $this->assertRaw('Out of date');
160     $this->assertRaw('Mismatched entity and/or field definitions');
161
162     // Apply db updates and check that entity updates were not applied.
163     $this->applyUpdates();
164     $this->drupalGet('admin/reports/status');
165     $this->assertNoRaw('Out of date');
166     $this->assertRaw('Mismatched entity and/or field definitions');
167
168     // Check that en exception would be triggered when trying to apply them with
169     // existing data.
170     $message = 'Entity updates cannot run if entity data exists.';
171     try {
172       $this->updatesManager->applyUpdates();
173       $this->fail($message);
174     }
175     catch (FieldStorageDefinitionUpdateForbiddenException $e) {
176       $this->pass($message);
177     }
178
179     // Check the status report is the same after trying to apply updates.
180     $this->drupalGet('admin/reports/status');
181     $this->assertNoRaw('Out of date');
182     $this->assertRaw('Mismatched entity and/or field definitions');
183
184     // Delete entity data, enable a new update, run updates again and check that
185     // entity updates were not applied even when no data exists.
186     $entity->delete();
187     $this->enableUpdates('entity_test', 'status_report', 8002);
188     $this->applyUpdates();
189     $this->drupalGet('admin/reports/status');
190     $this->assertNoRaw('Out of date');
191     $this->assertRaw('Mismatched entity and/or field definitions');
192   }
193
194   /**
195    * Reloads the specified entity.
196    *
197    * @param \Drupal\entity_test\Entity\EntityTest $entity
198    *   An entity object.
199    *
200    * @return \Drupal\entity_test\Entity\EntityTest
201    *   The reloaded entity object.
202    */
203   protected function reloadEntity(EntityTest $entity) {
204     $this->entityManager->useCaches(FALSE);
205     $this->entityManager->getStorage('entity_test')->resetCache([$entity->id()]);
206     return EntityTest::load($entity->id());
207   }
208
209 }