public function ContentEntityConflictHandler::entityFormEntityBuilder in Conflict 8.2
Entity builder method.
Parameters
string $entity_type_id: The entity type ID.
\Drupal\Core\Entity\EntityInterface $entity: The entity.
$form: The entity form.
\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form.
See also
\Drupal\conflict\Entity\ContentEntityConflictHandler::entityFormAlter()
File
- src/
Entity/ ContentEntityConflictHandler.php, line 172
Class
Namespace
Drupal\conflict\EntityCode
public function entityFormEntityBuilder($entity_type_id, EntityInterface $entity, &$form, FormStateInterface $form_state) {
// Run only as part of the final form level submission.
if (!$this
->isFormLevelSubmission($form_state)) {
return;
}
if ($entity instanceof ContentEntityInterface && !$entity
->isNew()) {
if ($entity
->isDefaultRevision()) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity_server */
$id = $entity
->id();
$entity_server = $this->storage
->loadUnchanged($id);
}
else {
// TODO - how to deal with forward revisions?
return;
}
$input = $form_state
->getUserInput();
$hash_path = $form['#parents'];
$hash_path[] = 'conflict_entity_original_hash';
$hash = NestedArray::getValue($input, $hash_path);
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity_original */
$entity_original = unserialize($this->keyValueOriginalEntity
->get($hash));
// Set the original entity as it might have changed. The original entity
// in our context is the one that was used to build the form initially
// and not the unchanged entity.
$entity->{static::CONFLICT_ENTITY_ORIGINAL} = $entity_original;
// Currently we do not support concurrent editing in the following cases:
// - editing a translation that is removed on the newest version.
// - while creating a new translation.
$edited_langcode = $entity
->language()
->getId();
if (!$entity_server
->hasTranslation($edited_langcode)) {
if ($entity_original
->hasTranslation($edited_langcode)) {
// Currently being on a translation that has been removed in the
// newest version.
$form_state
->setError($form, t('You are editing a translation, that has been removed meanwhile. As a result, your changes cannot be saved.'));
return;
}
else {
// @todo A new translation is being added. Currently we do not have
// any support for concurrent editing during translating content. If
// the entity has been modified meanwhile then the
// EntityChangedConstraintValidator will fail.
return;
}
}
else {
if (!$entity_original
->hasTranslation($edited_langcode)) {
$form_state
->setError($form, t('You are creating a translation, that has been created meanwhile. As a result, your changes cannot be saved.'));
return;
}
}
// Work directly with the entity translations.
$entity_server = $entity_server
->getTranslation($edited_langcode);
$entity_original = $entity_original
->getTranslation($edited_langcode);
// Check if the entity requires a merge.
$needs_merge = $this
->needsMerge($entity, $entity_original, $entity_server, FALSE);
if ($needs_merge) {
/** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */
$form_display = $form_state
->getFormObject()
->getFormDisplay($form_state);
// Append each field's widget to the field so that further processing
// can access it.
foreach (array_keys($form_display
->getComponents()) as $field_name) {
if ($entity
->getFieldDefinition($field_name)) {
$entity
->get($field_name)->conflictWidget = $form_display
->getRenderer($field_name);
}
}
// Auto merge changes in other translations.
$this
->autoMergeNonEditedTranslations($entity, $entity_server);
// Auto merge changes in non-editable fields.
$this
->autoMergeNonEditableFields($entity, $entity_server, $form_display);
// Auto merge non-changed fields.
$this
->autoMergeNotTouchedFields($entity, $entity_original, $entity_server, $form, $form_state);
// Auto merge entity metadata.
$this
->autoMergeEntityMetadata($entity, $entity_server, $form, $form_state);
// Run the entities through the event system for conflict discovery
// and resolution.
$context = new ParameterBag([
'form' => $form,
'form_state' => $form_state,
'form_display' => $form_display,
]);
// Disable the merge remote only changes strategy, which is enabled by
// default.
// TODO reconsider the decision for having all strategies enabled by
// default! They should be instead enabled through configuration and/or
// hooks/events.
$context
->set('merge_strategy.disabled', [
'conflict.merge_remote_only_changes',
]);
$conflicts = $this->conflictManager
->resolveConflicts($entity, $entity_server, $entity_original, $entity, $context);
// In case the entity still has conflicts then a user interaction is
// needed.
$needs_merge = !empty($conflicts) || $this
->needsMerge($entity, $entity_original, $entity_server, TRUE);
if ($needs_merge) {
// Prepare the entity for conflict resolution.
$this
->prepareConflictResolution($entity, $entity_server);
// If the entity supports conflict UI merge then add the path to it to
// the form state storage, otherwise flag the form with an error as it
// would've been flagged by the entity constraint "EntityChanged".
// @see \Drupal\Core\Entity\Plugin\Validation\Constraint\EntityChangedConstraint::$message
// @see \Drupal\Core\Entity\Plugin\Validation\Constraint\EntityChangedConstraintValidator::validate()
if ($this->entityType
->get('conflict_ui_merge_supported') && !(bool) $form_state
->get('manual-merge-not-possible')) {
$path = implode('.', $form['#parents']);
$conflict_paths = $form_state
->get('conflict.paths') ?: [];
$conflict_paths[$path] = [
'entity_type' => $entity_type_id,
'entity_id' => $entity
->id(),
];
$form_state
->set('conflict.paths', $conflict_paths);
}
else {
$message = t('The content has either been modified by another user, or you have already submitted modifications. As a result, your changes cannot be saved.');
$message .= ' ' . t('Unfortunately no conflict resolution could be provided for the set of changes.');
$form_state
->setError($form, $message);
}
}
}
}
}