3 namespace Drupal\KernelTests\Core\Entity;
5 use Drupal\entity_test\Entity\EntityTestMulChanged;
6 use Drupal\entity_test\Entity\EntityTestMulRevChanged;
7 use Drupal\language\Entity\ConfigurableLanguage;
10 * Tests basic EntityChangedInterface functionality.
14 class ContentEntityChangedTest extends EntityKernelTestBase {
21 public static $modules = ['language', 'user', 'system', 'field', 'text', 'filter', 'entity_test'];
24 * The EntityTestMulChanged entity type storage.
26 * @var \Drupal\Core\Entity\EntityStorageInterface
28 protected $mulChangedStorage;
31 * The EntityTestMulRevChanged entity type storage.
33 * @var \Drupal\Core\Entity\EntityStorageInterface
35 protected $mulRevChangedStorage;
40 protected function setUp() {
43 // Enable an additional language.
44 ConfigurableLanguage::createFromLangcode('de')->save();
45 ConfigurableLanguage::createFromLangcode('fr')->save();
47 $this->installEntitySchema('entity_test_mul_changed');
48 $this->installEntitySchema('entity_test_mulrev_changed');
50 $this->mulChangedStorage = $this->entityManager->getStorage('entity_test_mul_changed');
51 $this->mulRevChangedStorage = $this->entityManager->getStorage('entity_test_mulrev_changed');
55 * Tests basic EntityChangedInterface functionality.
57 public function testChanged() {
58 $user1 = $this->createUser();
59 $user2 = $this->createUser();
61 // Create a test entity.
62 $entity = EntityTestMulChanged::create([
63 'name' => $this->randomString(),
64 'not_translatable' => $this->randomString(),
65 'user_id' => $user1->id(),
71 $entity->getChangedTime() >= REQUEST_TIME,
72 'Changed time of original language is valid.'
75 // We can't assert equality here because the created time is set to the
76 // request time, while instances of ChangedTestItem use the current
77 // timestamp every time. Therefor we check if the changed timestamp is
78 // between the created time and now.
80 ($entity->getChangedTime() >= $entity->get('created')->value) &&
81 (($entity->getChangedTime() - $entity->get('created')->value) <= time() - REQUEST_TIME),
82 'Changed and created time of original language can be assumed to be identical.'
86 $entity->getChangedTime(), $entity->getChangedTimeAcrossTranslations(),
87 'Changed time of original language is the same as changed time across all translations.'
90 $changed_en = $entity->getChangedTime();
92 /** @var \Drupal\entity_test\Entity\EntityTestMulRevChanged $german */
93 $german = $entity->addTranslation('de');
98 $entity->getChangedTime(), $changed_en,
99 'Changed time of original language did not change.'
103 $german->getChangedTime() > $entity->getChangedTime(),
104 'Changed time of the German translation is newer then the original language.'
108 $german->getChangedTime(), $entity->getChangedTimeAcrossTranslations(),
109 'Changed time of the German translation is the newest time across all translations.'
112 $changed_de = $german->getChangedTime();
117 $entity->getChangedTime(), $changed_en,
118 'Changed time of original language did not change.'
122 $german->getChangedTime(), $changed_de,
123 'Changed time of the German translation did not change.'
126 // Update a non-translatable field to make sure that the changed timestamp
127 // is updated for all translations.
128 $entity->set('not_translatable', $this->randomString())->save();
131 $entity->getChangedTime() > $changed_en,
132 'Changed time of original language did change.'
136 $german->getChangedTime() > $changed_de,
137 'Changed time of the German translation did change.'
140 $this->assertEquals($entity->getChangedTime(), $german->getChangedTime(), 'When editing a non-translatable field the updated changed time is equal across all translations.');
142 $changed_en = $entity->getChangedTime();
143 $changed_de = $german->getChangedTime();
145 $entity->setOwner($user2);
150 $entity->getChangedTime() > $changed_en,
151 'Changed time of original language did change.'
155 $german->getChangedTime(), $changed_de,
156 'Changed time of the German translation did not change.'
160 $entity->getChangedTime() > $german->getChangedTime(),
161 'Changed time of original language is newer then the German translation.'
165 $entity->getChangedTime(), $entity->getChangedTimeAcrossTranslations(),
166 'Changed time of the original language is the newest time across all translations.'
169 $changed_en = $entity->getChangedTime();
171 // Save entity without any changes.
175 $entity->getChangedTime(), $changed_en,
176 'Changed time of original language did not change.'
180 $german->getChangedTime(), $changed_de,
181 'Changed time of the German translation did not change.'
184 // At this point the changed time of the original language (en) is newer
185 // than the changed time of the German translation. Now test that entity
186 // queries work as expected.
187 $query = $this->mulChangedStorage->getQuery();
188 $ids = $query->condition('changed', $changed_en)->execute();
191 reset($ids), $entity->id(),
192 'Entity query can access changed time of original language.'
195 $query = $this->mulChangedStorage->getQuery();
196 $ids = $query->condition('changed', $changed_en, '=', 'en')->execute();
199 reset($ids), $entity->id(),
200 'Entity query can access changed time of original language by setting the original language as condition.'
203 $query = $this->mulChangedStorage->getQuery();
204 $ids = $query->condition('changed', $changed_de, '=', 'en')->execute();
208 'There\'s no original entity stored having the changed time of the German translation.'
211 $query = $this->mulChangedStorage->getQuery();
212 $ids = $query->condition('changed', $changed_en)->condition('default_langcode', '1')->execute();
215 reset($ids), $entity->id(),
216 'Entity query can access changed time of default language.'
219 $query = $this->mulChangedStorage->getQuery();
220 $ids = $query->condition('changed', $changed_de)->condition('default_langcode', '1')->execute();
224 'There\'s no entity stored using the default language having the changed time of the German translation.'
227 $query = $this->mulChangedStorage->getQuery();
228 $ids = $query->condition('changed', $changed_de)->execute();
231 reset($ids), $entity->id(),
232 'Entity query can access changed time of the German translation.'
235 $query = $this->mulChangedStorage->getQuery();
236 $ids = $query->condition('changed', $changed_de, '=', 'de')->execute();
239 reset($ids), $entity->id(),
240 'Entity query can access changed time of the German translation.'
243 $query = $this->mulChangedStorage->getQuery();
244 $ids = $query->condition('changed', $changed_en, '=', 'de')->execute();
248 'There\'s no German translation stored having the changed time of the original language.'
251 $query = $this->mulChangedStorage->getQuery();
252 $ids = $query->condition('changed', $changed_de, '>')->execute();
255 reset($ids), $entity->id(),
256 'Entity query can access changed time regardless of translation.'
259 $query = $this->mulChangedStorage->getQuery();
260 $ids = $query->condition('changed', $changed_en, '<')->execute();
263 reset($ids), $entity->id(),
264 'Entity query can access changed time regardless of translation.'
267 $query = $this->mulChangedStorage->getQuery();
268 $ids = $query->condition('changed', 0, '>')->execute();
271 reset($ids), $entity->id(),
272 'Entity query can access changed time regardless of translation.'
275 $query = $this->mulChangedStorage->getQuery();
276 $ids = $query->condition('changed', $changed_en, '>')->execute();
280 'Entity query can access changed time regardless of translation.'
285 * Tests revisionable EntityChangedInterface functionality.
287 public function testRevisionChanged() {
288 $user1 = $this->createUser();
289 $user2 = $this->createUser();
291 // Create a test entity.
292 $entity = EntityTestMulRevChanged::create([
293 'name' => $this->randomString(),
294 'user_id' => $user1->id(),
300 $entity->getChangedTime() >= REQUEST_TIME,
301 'Changed time of original language is valid.'
304 // We can't assert equality here because the created time is set to the
305 // request time while instances of ChangedTestItem use the current
306 // timestamp every time.
308 ($entity->getChangedTime() >= $entity->get('created')->value) &&
309 (($entity->getChangedTime() - $entity->get('created')->value) <= time() - REQUEST_TIME),
310 'Changed and created time of original language can be assumed to be identical.'
314 $entity->getChangedTime(), $entity->getChangedTimeAcrossTranslations(),
315 'Changed time of original language is the same as changed time across all translations.'
319 $this->getRevisionTranslationAffectedFlag($entity),
320 'Changed flag of original language is set for a new entity.'
323 $changed_en = $entity->getChangedTime();
325 $entity->setNewRevision();
326 // Save entity without any changes but create new revision.
328 // A new revision without any changes should not set a new changed time.
330 $entity->getChangedTime(), $changed_en,
331 'Changed time of original language did not change.'
335 $this->getRevisionTranslationAffectedFlag($entity),
336 'Changed flag of original language is not set for new revision without changes.'
339 $entity->setNewRevision();
340 $entity->setOwner($user2);
344 $entity->getChangedTime() > $changed_en,
345 'Changed time of original language has been updated by new revision.'
349 $this->getRevisionTranslationAffectedFlag($entity),
350 'Changed flag of original language is set for new revision with changes.'
353 $changed_en = $entity->getChangedTime();
355 /** @var \Drupal\entity_test\Entity\EntityTestMulRevChanged $german */
356 $german = $entity->addTranslation('de');
361 $entity->getChangedTime(), $changed_en,
362 'Changed time of original language did not change.'
366 $german->getChangedTime() > $entity->getChangedTime(),
367 'Changed time of the German translation is newer then the original language.'
371 $german->getChangedTime(), $entity->getChangedTimeAcrossTranslations(),
372 'Changed time of the German translation is the newest time across all translations.'
376 $this->getRevisionTranslationAffectedFlag($entity),
377 'Changed flag of original language is not reset by adding a new translation.'
381 $this->getRevisionTranslationAffectedFlag($german),
382 'Changed flag of German translation is set when adding the translation.'
385 $changed_de = $german->getChangedTime();
387 $entity->setNewRevision();
388 // Save entity without any changes but create new revision.
392 $entity->getChangedTime(), $changed_en,
393 'Changed time of original language did not change.'
397 $german->getChangedTime(), $changed_de,
398 'Changed time of the German translation did not change.'
402 $this->getRevisionTranslationAffectedFlag($entity),
403 'Changed flag of original language is not set for new revision without changes.'
407 $this->getRevisionTranslationAffectedFlag($german),
408 'Changed flag of the German translation is not set for new revision without changes.'
411 $entity->setNewRevision();
412 $german->setOwner($user2);
416 $entity->getChangedTime(), $changed_en,
417 'Changed time of original language did not change.'
421 $german->getChangedTime() > $changed_de,
422 'Changed time of the German translation did change.'
426 $german->getChangedTime(), $entity->getChangedTimeAcrossTranslations(),
427 'Changed time of the German translation is the newest time across all translations.'
431 $this->getRevisionTranslationAffectedFlag($entity),
432 'Changed flag of original language is not set when changing the German Translation.'
436 $this->getRevisionTranslationAffectedFlag($german),
437 'Changed flag of German translation is set when changing the German translation.'
440 $french = $entity->addTranslation('fr');
442 $entity->setNewRevision();
446 $entity->getChangedTime(), $changed_en,
447 'Changed time of original language did not change.'
451 $french->getChangedTime() > $entity->getChangedTime(),
452 'Changed time of the French translation is newer then the original language.'
456 $french->getChangedTime() > $entity->getChangedTime(),
457 'Changed time of the French translation is newer then the German translation.'
461 $french->getChangedTime(), $entity->getChangedTimeAcrossTranslations(),
462 'Changed time of the French translation is the newest time across all translations.'
466 $this->getRevisionTranslationAffectedFlag($entity),
467 'Changed flag of original language is reset by adding a new translation and a new revision.'
471 $this->getRevisionTranslationAffectedFlag($german),
472 'Changed flag of German translation is reset by adding a new translation and a new revision.'
476 $this->getRevisionTranslationAffectedFlag($french),
477 'Changed flag of French translation is set when adding the translation and a new revision.'
480 $entity->removeTranslation('fr');
482 $entity->setNewRevision();
485 // This block simulates exactly the flow of a node form submission of a new
486 // translation and a new revision.
487 $form_entity_builder_entity = EntityTestMulRevChanged::load($entity->id());
488 // ContentTranslationController::prepareTranslation().
489 $form_entity_builder_entity = $form_entity_builder_entity->addTranslation('fr', $form_entity_builder_entity->toArray());
490 // EntityForm::buildEntity() during form submit.
491 $form_entity_builder_clone = clone $form_entity_builder_entity;
492 // NodeForm::submitForm().
493 $form_entity_builder_clone->setNewRevision();
494 // EntityForm::save().
495 $form_entity_builder_clone->save();
497 // The assertion fails unless https://www.drupal.org/node/2513094 is
500 $this->getRevisionTranslationAffectedFlag($entity),
501 'Changed flag of original language is reset by adding a new translation and a new revision.'
505 $this->getRevisionTranslationAffectedFlag($german),
506 'Changed flag of German translation is reset by adding a new translation and a new revision.'
510 $this->getRevisionTranslationAffectedFlag($french),
511 'Changed flag of French translation is set when adding the translation and a new revision.'
514 // Since above a clone of the entity was saved and then this entity is saved
515 // again, we have to update the revision ID to the current one.
516 $german->set('revision_id', $form_entity_builder_clone->getRevisionId());
517 $german->updateLoadedRevisionId();
518 $german->setOwner($user1);
519 $german->setRevisionTranslationAffected(FALSE);
523 $this->getRevisionTranslationAffectedFlag($german),
524 'German translation changed but the changed flag is reset manually.'
527 $entity->setNewRevision();
528 $german->setRevisionTranslationAffected(TRUE);
532 $this->getRevisionTranslationAffectedFlag($german),
533 'German translation is not changed and a new revision is created but the changed flag is set manually.'
536 $german->setOwner($user2);
537 $entity->setNewRevision();
538 $german->setRevisionTranslationAffected(FALSE);
542 $this->getRevisionTranslationAffectedFlag($german),
543 'German translation changed and a new revision is created but the changed flag is reset manually.'
549 * Retrieves the revision translation affected flag value.
551 * @param \Drupal\entity_test\Entity\EntityTestMulRevChanged $entity
552 * The entity object to be checked.
557 protected function getRevisionTranslationAffectedFlag(EntityTestMulRevChanged $entity) {
558 $query = $this->mulRevChangedStorage->getQuery();
559 $ids = $query->condition('revision_translation_affected', 1, '=', $entity->language()->getId())->execute();
561 return (bool) ($id == $entity->id());