Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / web / core / modules / system / tests / src / Functional / Entity / EntityRevisionsTest.php
1 <?php
2
3 namespace Drupal\Tests\system\Functional\Entity;
4
5 use Drupal\entity_test\Entity\EntityTestMulRev;
6 use Drupal\field\Entity\FieldConfig;
7 use Drupal\field\Entity\FieldStorageConfig;
8 use Drupal\language\Entity\ConfigurableLanguage;
9 use Drupal\Tests\BrowserTestBase;
10
11 /**
12  * Create a entity with revisions and test viewing, saving, reverting, and
13  * deleting revisions.
14  *
15  * @group Entity
16  */
17 class EntityRevisionsTest extends BrowserTestBase {
18
19   /**
20    * Modules to enable.
21    *
22    * @var array
23    */
24   public static $modules = ['entity_test', 'language'];
25
26   /**
27    * A user with permission to administer entity_test content.
28    *
29    * @var \Drupal\user\UserInterface
30    */
31   protected $webUser;
32
33   protected function setUp() {
34     parent::setUp();
35
36     // Create and log in user.
37     $this->webUser = $this->drupalCreateUser([
38       'administer entity_test content',
39       'view test entity',
40     ]);
41     $this->drupalLogin($this->webUser);
42
43     // Enable an additional language.
44     ConfigurableLanguage::createFromLangcode('de')->save();
45   }
46
47   /**
48    * Check node revision related operations.
49    */
50   public function testRevisions() {
51
52     // All revisable entity variations have to have the same results.
53     foreach (entity_test_entity_types(ENTITY_TEST_TYPES_REVISABLE) as $entity_type) {
54       $this->runRevisionsTests($entity_type);
55     }
56   }
57
58   /**
59    * Executes the revision tests for the given entity type.
60    *
61    * @param string $entity_type
62    *   The entity type to run the tests with.
63    */
64   protected function runRevisionsTests($entity_type) {
65     // Create a translatable test field.
66     $field_storage = FieldStorageConfig::create([
67       'entity_type' => $entity_type,
68       'field_name' => 'translatable_test_field',
69       'type' => 'text',
70       'cardinality' => 2,
71     ]);
72     $field_storage->save();
73
74     $field = FieldConfig::create([
75       'field_storage' => $field_storage,
76       'label' => $this->randomMachineName(),
77       'bundle' => $entity_type,
78       'translatable' => TRUE,
79     ]);
80     $field->save();
81
82     entity_get_form_display($entity_type, $entity_type, 'default')
83       ->setComponent('translatable_test_field')
84       ->save();
85
86     /** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
87     $storage = \Drupal::entityTypeManager()->getStorage($entity_type);
88
89     // Create initial entity.
90     /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
91     $entity = $storage
92       ->create([
93         'name' => 'foo',
94         'user_id' => $this->webUser->id(),
95       ]);
96     $entity->translatable_test_field->value = 'bar';
97     $entity->addTranslation('de', ['name' => 'foo - de']);
98     $entity->save();
99
100     $values = [];
101     $revision_ids = [];
102
103     // Create three revisions.
104     $revision_count = 3;
105     for ($i = 0; $i < $revision_count; $i++) {
106       $legacy_revision_id = $entity->revision_id->value;
107       $legacy_name = $entity->name->value;
108       $legacy_text = $entity->translatable_test_field->value;
109
110       $entity = $storage->load($entity->id->value);
111       $entity->setNewRevision(TRUE);
112       $values['en'][$i] = [
113         'name' => $this->randomMachineName(32),
114         'translatable_test_field' => [
115           $this->randomMachineName(32),
116           $this->randomMachineName(32),
117         ],
118         'created' => time() + $i + 1,
119       ];
120       $entity->set('name', $values['en'][$i]['name']);
121       $entity->set('translatable_test_field', $values['en'][$i]['translatable_test_field']);
122       $entity->set('created', $values['en'][$i]['created']);
123       $entity->save();
124       $revision_ids[] = $entity->revision_id->value;
125
126       // Add some values for a translation of this revision.
127       if ($entity->getEntityType()->isTranslatable()) {
128         $values['de'][$i] = [
129           'name' => $this->randomMachineName(32),
130           'translatable_test_field' => [
131             $this->randomMachineName(32),
132             $this->randomMachineName(32),
133           ],
134         ];
135         $translation = $entity->getTranslation('de');
136         $translation->set('name', $values['de'][$i]['name']);
137         $translation->set('translatable_test_field', $values['de'][$i]['translatable_test_field']);
138         $translation->save();
139       }
140
141       // Check that the fields and properties contain new content.
142       $this->assertTrue($entity->revision_id->value > $legacy_revision_id, format_string('%entity_type: Revision ID changed.', ['%entity_type' => $entity_type]));
143       $this->assertNotEqual($entity->name->value, $legacy_name, format_string('%entity_type: Name changed.', ['%entity_type' => $entity_type]));
144       $this->assertNotEqual($entity->translatable_test_field->value, $legacy_text, format_string('%entity_type: Text changed.', ['%entity_type' => $entity_type]));
145     }
146
147     $revisions = $storage->loadMultipleRevisions($revision_ids);
148     for ($i = 0; $i < $revision_count; $i++) {
149       // Load specific revision.
150       $entity_revision = $revisions[$revision_ids[$i]];
151
152       // Check if properties and fields contain the revision specific content.
153       $this->assertEqual($entity_revision->revision_id->value, $revision_ids[$i], format_string('%entity_type: Revision ID matches.', ['%entity_type' => $entity_type]));
154       $this->assertEqual($entity_revision->name->value, $values['en'][$i]['name'], format_string('%entity_type: Name matches.', ['%entity_type' => $entity_type]));
155       $this->assertEqual($entity_revision->translatable_test_field[0]->value, $values['en'][$i]['translatable_test_field'][0], format_string('%entity_type: Text matches.', ['%entity_type' => $entity_type]));
156       $this->assertEqual($entity_revision->translatable_test_field[1]->value, $values['en'][$i]['translatable_test_field'][1], format_string('%entity_type: Text matches.', ['%entity_type' => $entity_type]));
157
158       // Check the translated values.
159       if ($entity->getEntityType()->isTranslatable()) {
160         $revision_translation = $entity_revision->getTranslation('de');
161         $this->assertEqual($revision_translation->name->value, $values['de'][$i]['name'], format_string('%entity_type: Name matches.', ['%entity_type' => $entity_type]));
162         $this->assertEqual($revision_translation->translatable_test_field[0]->value, $values['de'][$i]['translatable_test_field'][0], format_string('%entity_type: Text matches.', ['%entity_type' => $entity_type]));
163         $this->assertEqual($revision_translation->translatable_test_field[1]->value, $values['de'][$i]['translatable_test_field'][1], format_string('%entity_type: Text matches.', ['%entity_type' => $entity_type]));
164       }
165
166       // Check non-revisioned values are loaded.
167       $this->assertTrue(isset($entity_revision->created->value), format_string('%entity_type: Non-revisioned field is loaded.', ['%entity_type' => $entity_type]));
168       $this->assertEqual($entity_revision->created->value, $values['en'][2]['created'], format_string('%entity_type: Non-revisioned field value is the same between revisions.', ['%entity_type' => $entity_type]));
169     }
170
171     // Confirm the correct revision text appears in the edit form.
172     $entity = $storage->load($entity->id->value);
173     $this->drupalGet($entity_type . '/manage/' . $entity->id->value . '/edit');
174     $this->assertFieldById('edit-name-0-value', $entity->name->value, format_string('%entity_type: Name matches in UI.', ['%entity_type' => $entity_type]));
175     $this->assertFieldById('edit-translatable-test-field-0-value', $entity->translatable_test_field->value, format_string('%entity_type: Text matches in UI.', ['%entity_type' => $entity_type]));
176   }
177
178   /**
179    * Tests that an entity revision is upcasted in the correct language.
180    */
181   public function testEntityRevisionParamConverter() {
182     // Create a test entity with multiple revisions and translations for them.
183     $entity = EntityTestMulRev::create([
184       'name' => 'default revision - en',
185       'user_id' => $this->webUser,
186       'language' => 'en',
187     ]);
188     $entity->addTranslation('de', ['name' => 'default revision - de']);
189     $entity->save();
190
191     $pending_revision = \Drupal::entityTypeManager()->getStorage('entity_test_mulrev')->loadUnchanged($entity->id());
192
193     $pending_revision->setNewRevision();
194     $pending_revision->isDefaultRevision(FALSE);
195
196     $pending_revision->name = 'pending revision - en';
197     $pending_revision->save();
198
199     $pending_revision_translation = $pending_revision->getTranslation('de');
200     $pending_revision_translation->name = 'pending revision - de';
201     $pending_revision_translation->save();
202
203     // Check that the entity revision is upcasted in the correct language.
204     $revision_url = 'entity_test_mulrev/' . $entity->id() . '/revision/' . $pending_revision->getRevisionId() . '/view';
205
206     $this->drupalGet($revision_url);
207     $this->assertText('pending revision - en');
208     $this->assertNoText('pending revision - de');
209
210     $this->drupalGet('de/' . $revision_url);
211     $this->assertText('pending revision - de');
212     $this->assertNoText('pending revision - en');
213   }
214
215   /**
216    * Tests manual revert of the revision ID value.
217    *
218    * @covers \Drupal\Core\Entity\ContentEntityBase::getRevisionId
219    * @covers \Drupal\Core\Entity\ContentEntityBase::getLoadedRevisionId
220    * @covers \Drupal\Core\Entity\ContentEntityBase::setNewRevision
221    * @covers \Drupal\Core\Entity\ContentEntityBase::isNewRevision
222    */
223   public function testNewRevisionRevert() {
224     $entity = EntityTestMulRev::create(['name' => 'EntityLoadedRevisionTest']);
225     $entity->save();
226
227     // Check that revision ID field is reset while the loaded revision ID is
228     // preserved when flagging a new revision.
229     $revision_id = $entity->getRevisionId();
230     $entity->setNewRevision();
231     $this->assertNull($entity->getRevisionId());
232     $this->assertEquals($revision_id, $entity->getLoadedRevisionId());
233     $this->assertTrue($entity->isNewRevision());
234
235     // Check that after manually restoring the original revision ID, the entity
236     // is stored without creating a new revision.
237     $key = $entity->getEntityType()->getKey('revision');
238     $entity->set($key, $revision_id);
239     $entity->save();
240     $this->assertEquals($revision_id, $entity->getRevisionId());
241     $this->assertEquals($revision_id, $entity->getLoadedRevisionId());
242
243     // Check that manually restoring the original revision ID causes the "new
244     // revision" state to be reverted.
245     $entity->setNewRevision();
246     $this->assertNull($entity->getRevisionId());
247     $this->assertEquals($revision_id, $entity->getLoadedRevisionId());
248     $this->assertTrue($entity->isNewRevision());
249     $entity->set($key, $revision_id);
250     $this->assertFalse($entity->isNewRevision());
251     $this->assertEquals($revision_id, $entity->getRevisionId());
252     $this->assertEquals($revision_id, $entity->getLoadedRevisionId());
253
254     // Check that flagging a new revision again works correctly.
255     $entity->setNewRevision();
256     $this->assertNull($entity->getRevisionId());
257     $this->assertEquals($revision_id, $entity->getLoadedRevisionId());
258     $this->assertTrue($entity->isNewRevision());
259
260     // Check that calling setNewRevision() on a new entity without a revision ID
261     // and then with a revision ID does not unset the revision ID.
262     $entity = EntityTestMulRev::create(['name' => 'EntityLoadedRevisionTest']);
263     $entity->set('revision_id', NULL);
264     $entity->set('revision_id', 5);
265     $this->assertTrue($entity->isNewRevision());
266     $entity->setNewRevision();
267     $this->assertEquals(5, $entity->get('revision_id')->value);
268
269   }
270
271 }