Security update for Core, with self-updated composer
[yaffs-website] / web / core / lib / Drupal / Core / Entity / Plugin / Validation / Constraint / EntityChangedConstraintValidator.php
index b1fee2a29452bf2c290b01053b60aac3f58851e1..28d81ba6e4de28e14401950cfff5198ec37c16fe 100644 (file)
@@ -18,10 +18,23 @@ class EntityChangedConstraintValidator extends ConstraintValidator {
       /** @var \Drupal\Core\Entity\EntityInterface $entity */
       if (!$entity->isNew()) {
         $saved_entity = \Drupal::entityManager()->getStorage($entity->getEntityTypeId())->loadUnchanged($entity->id());
-        // A change to any other translation must add a violation to the current
-        // translation because there might be untranslatable shared fields.
-        if ($saved_entity && $saved_entity->getChangedTimeAcrossTranslations() > $entity->getChangedTimeAcrossTranslations()) {
-          $this->context->addViolation($constraint->message);
+        // Ensure that all the entity translations are the same as or newer
+        // than their current version in the storage in order to avoid
+        // reverting other changes. In fact the entity object that is being
+        // saved might contain an older entity translation when different
+        // translations are being concurrently edited.
+        if ($saved_entity) {
+          $common_translation_languages = array_intersect_key($entity->getTranslationLanguages(), $saved_entity->getTranslationLanguages());
+          foreach (array_keys($common_translation_languages) as $langcode) {
+            // Merely comparing the latest changed timestamps across all
+            // translations is not sufficient since other translations may have
+            // been edited and saved in the meanwhile. Therefore, compare the
+            // changed timestamps of each entity translation individually.
+            if ($saved_entity->getTranslation($langcode)->getChangedTime() > $entity->getTranslation($langcode)->getChangedTime()) {
+              $this->context->addViolation($constraint->message);
+              break;
+            }
+          }
         }
       }
     }