66e1abb2c51ed0ce10169ff85abea870e1abcfc9
[yaffs-website] / web / core / tests / Drupal / KernelTests / Core / Entity / ContentEntityChangedTest.php
1 <?php
2
3 namespace Drupal\KernelTests\Core\Entity;
4
5 use Drupal\entity_test\Entity\EntityTestMulChanged;
6 use Drupal\entity_test\Entity\EntityTestMulRevChanged;
7 use Drupal\language\Entity\ConfigurableLanguage;
8
9 /**
10  * Tests basic EntityChangedInterface functionality.
11  *
12  * @group Entity
13  */
14 class ContentEntityChangedTest extends EntityKernelTestBase {
15
16   /**
17    * Modules to enable.
18    *
19    * @var array
20    */
21   public static $modules = ['language', 'user', 'system', 'field', 'text', 'filter', 'entity_test'];
22
23   /**
24    * The EntityTestMulChanged entity type storage.
25    *
26    * @var \Drupal\Core\Entity\EntityStorageInterface
27    */
28   protected $mulChangedStorage;
29
30   /**
31    * The EntityTestMulRevChanged entity type storage.
32    *
33    * @var \Drupal\Core\Entity\EntityStorageInterface
34    */
35   protected $mulRevChangedStorage;
36
37   /**
38    * {@inheritdoc}
39    */
40   protected function setUp() {
41     parent::setUp();
42
43     // Enable an additional language.
44     ConfigurableLanguage::createFromLangcode('de')->save();
45     ConfigurableLanguage::createFromLangcode('fr')->save();
46
47     $this->installEntitySchema('entity_test_mul_changed');
48     $this->installEntitySchema('entity_test_mulrev_changed');
49
50     $this->mulChangedStorage = $this->entityManager->getStorage('entity_test_mul_changed');
51     $this->mulRevChangedStorage = $this->entityManager->getStorage('entity_test_mulrev_changed');
52   }
53
54   /**
55    * Tests basic EntityChangedInterface functionality.
56    */
57   public function testChanged() {
58     $user1 = $this->createUser();
59     $user2 = $this->createUser();
60
61     // Create a test entity.
62     $entity = EntityTestMulChanged::create([
63       'name' => $this->randomString(),
64       'not_translatable' => $this->randomString(),
65       'user_id' => $user1->id(),
66       'language' => 'en',
67     ]);
68     $entity->save();
69
70     $this->assertTrue(
71       $entity->getChangedTime() >= REQUEST_TIME,
72       'Changed time of original language is valid.'
73     );
74
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.
79     $this->assertTrue(
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.'
83     );
84
85     $this->assertEqual(
86       $entity->getChangedTime(), $entity->getChangedTimeAcrossTranslations(),
87       'Changed time of original language is the same as changed time across all translations.'
88     );
89
90     $changed_en = $entity->getChangedTime();
91
92     /** @var \Drupal\entity_test\Entity\EntityTestMulRevChanged $german */
93     $german = $entity->addTranslation('de');
94
95     $entity->save();
96
97     $this->assertEqual(
98       $entity->getChangedTime(), $changed_en,
99       'Changed time of original language did not change.'
100     );
101
102     $this->assertTrue(
103       $german->getChangedTime() > $entity->getChangedTime(),
104       'Changed time of the German translation is newer then the original language.'
105     );
106
107     $this->assertEqual(
108       $german->getChangedTime(), $entity->getChangedTimeAcrossTranslations(),
109       'Changed time of the German translation is the newest time across all translations.'
110     );
111
112     $changed_de = $german->getChangedTime();
113
114     $entity->save();
115
116     $this->assertEqual(
117       $entity->getChangedTime(), $changed_en,
118       'Changed time of original language did not change.'
119     );
120
121     $this->assertEqual(
122       $german->getChangedTime(), $changed_de,
123       'Changed time of the German translation did not change.'
124     );
125
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();
129
130     $this->assertTrue(
131       $entity->getChangedTime() > $changed_en,
132       'Changed time of original language did change.'
133     );
134
135     $this->assertTrue(
136       $german->getChangedTime() > $changed_de,
137       'Changed time of the German translation did change.'
138     );
139
140     $this->assertEquals($entity->getChangedTime(), $german->getChangedTime(), 'When editing a non-translatable field the updated changed time is equal across all translations.');
141
142     $changed_en = $entity->getChangedTime();
143     $changed_de = $german->getChangedTime();
144
145     $entity->setOwner($user2);
146
147     $entity->save();
148
149     $this->assertTrue(
150       $entity->getChangedTime() > $changed_en,
151       'Changed time of original language did change.'
152     );
153
154     $this->assertEqual(
155       $german->getChangedTime(), $changed_de,
156       'Changed time of the German translation did not change.'
157     );
158
159     $this->assertTrue(
160       $entity->getChangedTime() > $german->getChangedTime(),
161       'Changed time of original language is newer then the German translation.'
162     );
163
164     $this->assertEqual(
165       $entity->getChangedTime(), $entity->getChangedTimeAcrossTranslations(),
166       'Changed time of the original language is the newest time across all translations.'
167     );
168
169     $changed_en = $entity->getChangedTime();
170
171     // Save entity without any changes.
172     $entity->save();
173
174     $this->assertEqual(
175       $entity->getChangedTime(), $changed_en,
176       'Changed time of original language did not change.'
177     );
178
179     $this->assertEqual(
180       $german->getChangedTime(), $changed_de,
181       'Changed time of the German translation did not change.'
182     );
183
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();
189
190     $this->assertEqual(
191       reset($ids), $entity->id(),
192       'Entity query can access changed time of original language.'
193     );
194
195     $query = $this->mulChangedStorage->getQuery();
196     $ids = $query->condition('changed', $changed_en, '=', 'en')->execute();
197
198     $this->assertEqual(
199       reset($ids), $entity->id(),
200       'Entity query can access changed time of original language by setting the original language as condition.'
201     );
202
203     $query = $this->mulChangedStorage->getQuery();
204     $ids = $query->condition('changed', $changed_de, '=', 'en')->execute();
205
206     $this->assertFalse(
207       $ids,
208       'There\'s no original entity stored having the changed time of the German translation.'
209     );
210
211     $query = $this->mulChangedStorage->getQuery();
212     $ids = $query->condition('changed', $changed_en)->condition('default_langcode', '1')->execute();
213
214     $this->assertEqual(
215       reset($ids), $entity->id(),
216       'Entity query can access changed time of default language.'
217     );
218
219     $query = $this->mulChangedStorage->getQuery();
220     $ids = $query->condition('changed', $changed_de)->condition('default_langcode', '1')->execute();
221
222     $this->assertFalse(
223       $ids,
224       'There\'s no entity stored using the default language having the changed time of the German translation.'
225     );
226
227     $query = $this->mulChangedStorage->getQuery();
228     $ids = $query->condition('changed', $changed_de)->execute();
229
230     $this->assertEqual(
231       reset($ids), $entity->id(),
232       'Entity query can access changed time of the German translation.'
233     );
234
235     $query = $this->mulChangedStorage->getQuery();
236     $ids = $query->condition('changed', $changed_de, '=', 'de')->execute();
237
238     $this->assertEqual(
239       reset($ids), $entity->id(),
240       'Entity query can access changed time of the German translation.'
241     );
242
243     $query = $this->mulChangedStorage->getQuery();
244     $ids = $query->condition('changed', $changed_en, '=', 'de')->execute();
245
246     $this->assertFalse(
247       $ids,
248       'There\'s no German translation stored having the changed time of the original language.'
249     );
250
251     $query = $this->mulChangedStorage->getQuery();
252     $ids = $query->condition('changed', $changed_de, '>')->execute();
253
254     $this->assertEqual(
255       reset($ids), $entity->id(),
256       'Entity query can access changed time regardless of translation.'
257     );
258
259     $query = $this->mulChangedStorage->getQuery();
260     $ids = $query->condition('changed', $changed_en, '<')->execute();
261
262     $this->assertEqual(
263       reset($ids), $entity->id(),
264       'Entity query can access changed time regardless of translation.'
265     );
266
267     $query = $this->mulChangedStorage->getQuery();
268     $ids = $query->condition('changed', 0, '>')->execute();
269
270     $this->assertEqual(
271       reset($ids), $entity->id(),
272       'Entity query can access changed time regardless of translation.'
273     );
274
275     $query = $this->mulChangedStorage->getQuery();
276     $ids = $query->condition('changed', $changed_en, '>')->execute();
277
278     $this->assertFalse(
279       $ids,
280       'Entity query can access changed time regardless of translation.'
281     );
282   }
283
284   /**
285    * Tests revisionable EntityChangedInterface functionality.
286    */
287   public function testRevisionChanged() {
288     $user1 = $this->createUser();
289     $user2 = $this->createUser();
290
291     // Create a test entity.
292     $entity = EntityTestMulRevChanged::create([
293       'name' => $this->randomString(),
294       'user_id' => $user1->id(),
295       'language' => 'en',
296     ]);
297     $entity->save();
298
299     $this->assertTrue(
300       $entity->getChangedTime() >= REQUEST_TIME,
301       'Changed time of original language is valid.'
302     );
303
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.
307     $this->assertTrue(
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.'
311     );
312
313     $this->assertEqual(
314       $entity->getChangedTime(), $entity->getChangedTimeAcrossTranslations(),
315       'Changed time of original language is the same as changed time across all translations.'
316     );
317
318     $this->assertTrue(
319       $this->getRevisionTranslationAffectedFlag($entity),
320       'Changed flag of original language is set for a new entity.'
321     );
322
323     $changed_en = $entity->getChangedTime();
324
325     $entity->setNewRevision();
326     // Save entity without any changes but create new revision.
327     $entity->save();
328     // A new revision without any changes should not set a new changed time.
329     $this->assertEqual(
330       $entity->getChangedTime(), $changed_en,
331       'Changed time of original language did not change.'
332     );
333
334     $this->assertFalse(
335       $this->getRevisionTranslationAffectedFlag($entity),
336       'Changed flag of original language is not set for new revision without changes.'
337     );
338
339     $entity->setNewRevision();
340     $entity->setOwner($user2);
341     $entity->save();
342
343     $this->assertTrue(
344       $entity->getChangedTime() > $changed_en,
345       'Changed time of original language has been updated by new revision.'
346     );
347
348     $this->assertTrue(
349       $this->getRevisionTranslationAffectedFlag($entity),
350       'Changed flag of original language is set for new revision with changes.'
351     );
352
353     $changed_en = $entity->getChangedTime();
354
355     /** @var \Drupal\entity_test\Entity\EntityTestMulRevChanged $german */
356     $german = $entity->addTranslation('de');
357
358     $entity->save();
359
360     $this->assertEqual(
361       $entity->getChangedTime(), $changed_en,
362       'Changed time of original language did not change.'
363     );
364
365     $this->assertTrue(
366       $german->getChangedTime() > $entity->getChangedTime(),
367       'Changed time of the German translation is newer then the original language.'
368     );
369
370     $this->assertEqual(
371       $german->getChangedTime(), $entity->getChangedTimeAcrossTranslations(),
372       'Changed time of the German translation is the newest time across all translations.'
373     );
374
375     $this->assertTrue(
376       $this->getRevisionTranslationAffectedFlag($entity),
377       'Changed flag of original language is not reset by adding a new translation.'
378     );
379
380     $this->assertTrue(
381       $this->getRevisionTranslationAffectedFlag($german),
382       'Changed flag of German translation is set when adding the translation.'
383     );
384
385     $changed_de = $german->getChangedTime();
386
387     $entity->setNewRevision();
388     // Save entity without any changes but create new revision.
389     $entity->save();
390
391     $this->assertEqual(
392       $entity->getChangedTime(), $changed_en,
393       'Changed time of original language did not change.'
394     );
395
396     $this->assertEqual(
397       $german->getChangedTime(), $changed_de,
398       'Changed time of the German translation did not change.'
399     );
400
401     $this->assertFalse(
402       $this->getRevisionTranslationAffectedFlag($entity),
403       'Changed flag of original language is not set for new revision without changes.'
404     );
405
406     $this->assertFalse(
407       $this->getRevisionTranslationAffectedFlag($german),
408       'Changed flag of the German translation is not set for new revision without changes.'
409     );
410
411     $entity->setNewRevision();
412     $german->setOwner($user2);
413     $entity->save();
414
415     $this->assertEqual(
416       $entity->getChangedTime(), $changed_en,
417       'Changed time of original language did not change.'
418     );
419
420     $this->assertTrue(
421       $german->getChangedTime() > $changed_de,
422       'Changed time of the German translation did change.'
423     );
424
425     $this->assertEqual(
426       $german->getChangedTime(), $entity->getChangedTimeAcrossTranslations(),
427       'Changed time of the German translation is the newest time across all translations.'
428     );
429
430     $this->assertFalse(
431       $this->getRevisionTranslationAffectedFlag($entity),
432       'Changed flag of original language is not set when changing the German Translation.'
433     );
434
435     $this->assertTrue(
436       $this->getRevisionTranslationAffectedFlag($german),
437       'Changed flag of German translation is set when changing the German translation.'
438     );
439
440     $french = $entity->addTranslation('fr');
441
442     $entity->setNewRevision();
443     $entity->save();
444
445     $this->assertEqual(
446       $entity->getChangedTime(), $changed_en,
447       'Changed time of original language did not change.'
448     );
449
450     $this->assertTrue(
451       $french->getChangedTime() > $entity->getChangedTime(),
452       'Changed time of the French translation is newer then the original language.'
453     );
454
455     $this->assertTrue(
456       $french->getChangedTime() > $entity->getChangedTime(),
457       'Changed time of the French translation is newer then the German translation.'
458     );
459
460     $this->assertEqual(
461       $french->getChangedTime(), $entity->getChangedTimeAcrossTranslations(),
462       'Changed time of the French translation is the newest time across all translations.'
463     );
464
465     $this->assertFalse(
466       $this->getRevisionTranslationAffectedFlag($entity),
467       'Changed flag of original language is reset by adding a new translation and a new revision.'
468     );
469
470     $this->assertFalse(
471       $this->getRevisionTranslationAffectedFlag($german),
472       'Changed flag of German translation is reset by adding a new translation and a new revision.'
473     );
474
475     $this->assertTrue(
476       $this->getRevisionTranslationAffectedFlag($french),
477       'Changed flag of French translation is set when adding the translation and a new revision.'
478     );
479
480     $entity->removeTranslation('fr');
481
482     $entity->setNewRevision();
483     $entity->save();
484
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();
496
497     // The assertion fails unless https://www.drupal.org/node/2513094 is
498     // committed.
499     $this->assertFalse(
500       $this->getRevisionTranslationAffectedFlag($entity),
501       'Changed flag of original language is reset by adding a new translation and a new revision.'
502     );
503
504     $this->assertFalse(
505       $this->getRevisionTranslationAffectedFlag($german),
506       'Changed flag of German translation is reset by adding a new translation and a new revision.'
507     );
508
509     $this->assertTrue(
510       $this->getRevisionTranslationAffectedFlag($french),
511       'Changed flag of French translation is set when adding the translation and a new revision.'
512     );
513
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);
520     $entity->save();
521
522     $this->assertFalse(
523       $this->getRevisionTranslationAffectedFlag($german),
524       'German translation changed but the changed flag is reset manually.'
525     );
526
527     $entity->setNewRevision();
528     $german->setRevisionTranslationAffected(TRUE);
529     $entity->save();
530
531     $this->assertTrue(
532       $this->getRevisionTranslationAffectedFlag($german),
533       'German translation is not changed and a new revision is created but the changed flag is set manually.'
534     );
535
536     $german->setOwner($user2);
537     $entity->setNewRevision();
538     $german->setRevisionTranslationAffected(FALSE);
539     $entity->save();
540
541     $this->assertFalse(
542       $this->getRevisionTranslationAffectedFlag($german),
543       'German translation changed and a new revision is created but the changed flag is reset manually.'
544     );
545
546   }
547
548   /**
549    * Retrieves the revision translation affected flag value.
550    *
551    * @param \Drupal\entity_test\Entity\EntityTestMulRevChanged $entity
552    *   The entity object to be checked.
553    *
554    * @return bool
555    *   The flag value.
556    */
557   protected function getRevisionTranslationAffectedFlag(EntityTestMulRevChanged $entity) {
558     $query = $this->mulRevChangedStorage->getQuery();
559     $ids = $query->condition('revision_translation_affected', 1, '=', $entity->language()->getId())->execute();
560     $id = reset($ids);
561     return (bool) ($id == $entity->id());
562   }
563
564 }