Pull merge.
[yaffs-website] / web / core / lib / Drupal / Core / Entity / ContentEntityForm.php
index 14e910d1e1635ab5ac355f90c7c9063d1ab9d771..75bde9fe3502b48148d9e7d14dafabf72e888df2 100644 (file)
@@ -15,13 +15,6 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
  */
 class ContentEntityForm extends EntityForm implements ContentEntityFormInterface {
 
-  /**
-   * The entity manager.
-   *
-   * @var \Drupal\Core\Entity\EntityManagerInterface
-   */
-  protected $entityManager;
-
   /**
    * The entity being used by this form.
    *
@@ -43,19 +36,29 @@ class ContentEntityForm extends EntityForm implements ContentEntityFormInterface
    */
   protected $time;
 
+  /**
+   * The entity repository service.
+   *
+   * @var \Drupal\Core\Entity\EntityRepositoryInterface
+   */
+  protected $entityRepository;
+
   /**
    * Constructs a ContentEntityForm object.
    *
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
+   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
+   *   The entity repository service.
    * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
    *   The entity type bundle service.
    * @param \Drupal\Component\Datetime\TimeInterface $time
    *   The time service.
    */
-  public function __construct(EntityManagerInterface $entity_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) {
-    $this->entityManager = $entity_manager;
-
+  public function __construct(EntityRepositoryInterface $entity_repository, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) {
+    if ($entity_repository instanceof EntityManagerInterface) {
+      @trigger_error('Passing the entity.manager service to ContentEntityForm::__construct() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Pass the entity.repository service instead. See https://www.drupal.org/node/2549139.', E_USER_DEPRECATED);
+      $this->entityManager = $entity_repository;
+    }
+    $this->entityRepository = $entity_repository;
     $this->entityTypeBundleInfo = $entity_type_bundle_info ?: \Drupal::service('entity_type.bundle.info');
     $this->time = $time ?: \Drupal::service('datetime.time');
   }
@@ -65,7 +68,7 @@ class ContentEntityForm extends EntityForm implements ContentEntityFormInterface
    */
   public static function create(ContainerInterface $container) {
     return new static(
-      $container->get('entity.manager'),
+      $container->get('entity.repository'),
       $container->get('entity_type.bundle.info'),
       $container->get('datetime.time')
     );
@@ -127,6 +130,15 @@ class ContentEntityForm extends EntityForm implements ContentEntityFormInterface
       $this->addRevisionableFormFields($form);
     }
 
+    $form['footer'] = [
+      '#type' => 'container',
+      '#weight' => 99,
+      '#attributes' => [
+        'class' => ['entity-content-form-footer'],
+      ],
+      '#optional' => TRUE,
+    ];
+
     return $form;
   }
 
@@ -179,10 +191,29 @@ class ContentEntityForm extends EntityForm implements ContentEntityFormInterface
 
     $violations = $entity->validate();
 
-    // Remove violations of inaccessible fields and not edited fields.
-    $violations
-      ->filterByFieldAccess($this->currentUser())
-      ->filterByFields(array_diff(array_keys($entity->getFieldDefinitions()), $this->getEditedFieldNames($form_state)));
+    // Remove violations of inaccessible fields.
+    $violations->filterByFieldAccess($this->currentUser());
+
+    // In case a field-level submit button is clicked, for example the 'Add
+    // another item' button for multi-value fields or the 'Upload' button for a
+    // File or an Image field, make sure that we only keep violations for that
+    // specific field.
+    $edited_fields = [];
+    if ($limit_validation_errors = $form_state->getLimitValidationErrors()) {
+      foreach ($limit_validation_errors as $section) {
+        $field_name = reset($section);
+        if ($entity->hasField($field_name)) {
+          $edited_fields[] = $field_name;
+        }
+      }
+      $edited_fields = array_unique($edited_fields);
+    }
+    else {
+      $edited_fields = $this->getEditedFieldNames($form_state);
+    }
+
+    // Remove violations for fields that are not edited.
+    $violations->filterByFields(array_diff(array_keys($entity->getFieldDefinitions()), $edited_fields));
 
     $this->flagViolations($violations, $form, $form_state);
 
@@ -235,7 +266,7 @@ class ContentEntityForm extends EntityForm implements ContentEntityFormInterface
     // Flag entity level violations.
     foreach ($violations->getEntityViolations() as $violation) {
       /** @var \Symfony\Component\Validator\ConstraintViolationInterface $violation */
-      $form_state->setErrorByName('', $violation->getMessage());
+      $form_state->setErrorByName(str_replace('.', '][', $violation->getPropertyPath()), $violation->getMessage());
     }
     // Let the form display flag violations of its fields.
     $this->getFormDisplay($form_state)->flagWidgetsErrorsFromViolations($violations, $form, $form_state);
@@ -279,7 +310,7 @@ class ContentEntityForm extends EntityForm implements ContentEntityFormInterface
       // Imply a 'view' operation to ensure users edit entities in the same
       // language they are displayed. This allows to keep contextual editing
       // working also for multilingual entities.
-      $form_state->set('langcode', $this->entityManager->getTranslationFromContext($this->entity)->language()->getId());
+      $form_state->set('langcode', $this->entityRepository->getTranslationFromContext($this->entity)->language()->getId());
     }
   }
 
@@ -381,6 +412,7 @@ class ContentEntityForm extends EntityForm implements ContentEntityFormInterface
    *   An associative array containing the structure of the form.
    */
   protected function addRevisionableFormFields(array &$form) {
+    /** @var ContentEntityTypeInterface $entity_type */
     $entity_type = $this->entity->getEntityType();
 
     $new_revision_default = $this->getNewRevisionDefault();
@@ -411,9 +443,10 @@ class ContentEntityForm extends EntityForm implements ContentEntityFormInterface
       '#access' => !$this->entity->isNew() && $this->entity->get($entity_type->getKey('revision'))->access('update'),
       '#group' => 'revision_information',
     ];
-
-    if (isset($form['revision_log'])) {
-      $form['revision_log'] += [
+    // Get log message field's key from definition.
+    $log_message_field = $entity_type->getRevisionMetadataKey('revision_log_message');
+    if ($log_message_field && isset($form[$log_message_field])) {
+      $form[$log_message_field] += [
         '#group' => 'revision_information',
         '#states' => [
           'visible' => [