*/
class ContentEntityForm extends EntityForm implements ContentEntityFormInterface {
- /**
- * The entity manager.
- *
- * @var \Drupal\Core\Entity\EntityManagerInterface
- */
- protected $entityManager;
-
/**
* The entity being used by this form.
*
*/
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');
}
*/
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')
);
$this->addRevisionableFormFields($form);
}
+ $form['footer'] = [
+ '#type' => 'container',
+ '#weight' => 99,
+ '#attributes' => [
+ 'class' => ['entity-content-form-footer'],
+ ],
+ '#optional' => TRUE,
+ ];
+
return $form;
}
$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);
// 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);
// 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());
}
}
* 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();
'#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' => [