public function MergeRemoteStructure::resolveConflictsContentEntity in Conflict 8.2
Resolves conflicts on content entities.
Parameters
\Drupal\conflict\Event\EntityConflictResolutionEvent: The entity conflict discovery event.
Overrides MergeStrategyInterface::resolveConflictsContentEntity
File
- modules/
conflict_paragraphs/ src/ ConflictResolution/ MergeRemoteStructure.php, line 25
Class
Namespace
Drupal\conflict_paragraphs\ConflictResolutionCode
public function resolveConflictsContentEntity(EntityConflictResolutionEvent $event) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $local_entity */
$local_entity = $event
->getLocalEntity();
/** @var \Drupal\Core\Entity\ContentEntityInterface $remote_entity */
$remote_entity = $event
->getRemoteEntity();
/** @var \Drupal\Core\Entity\ContentEntityInterface $original_entity */
$original_entity = $event
->getBaseEntity();
/** @var \Drupal\Core\Entity\ContentEntityInterface $result_entity */
$result_entity = $event
->getResultEntity();
/** @var \Drupal\Core\Form\FormStateInterface $form_state */
$form_state = $event
->getContextParameter('form_state');
// TODO this supports only paragraphs at first level.
foreach ($event
->getConflicts() as $property => $conflict_type) {
$field_definition = $remote_entity
->getFieldDefinition($property);
if (ParagraphsWidget::isApplicable($field_definition)) {
$local_paragraph_ids_unsorted = array_map(function ($value) {
return $value['target_id'];
}, $local_entity
->get($property)
->getValue());
$server_paragraph_ids_unsorted = array_map(function ($value) {
return $value['target_id'];
}, $remote_entity
->get($property)
->getValue());
$original_paragraph_ids_unsorted = array_map(function ($value) {
return $value['target_id'];
}, $original_entity
->get($property)
->getValue());
$local_paragraph_ids_sorted = $local_paragraph_ids_unsorted;
$server_paragraph_ids_sorted = $server_paragraph_ids_unsorted;
$original_paragraph_ids_sorted = $original_paragraph_ids_unsorted;
sort($local_paragraph_ids_sorted);
sort($server_paragraph_ids_sorted);
sort($original_paragraph_ids_sorted);
// No entities have been added or deleted in the server version.
if ($server_paragraph_ids_sorted == $original_paragraph_ids_sorted) {
// If the server version has been saved with different sorting, then
// apply this sorting to the current result entity and widget state.
/** @var \Drupal\entity_reference_revisions\EntityReferenceRevisionsFieldItemList $field_item_list */
$field_item_list = $result_entity
->get($property);
$server_field_item_list = $remote_entity
->get($property);
$field_item_list_unsorted = clone $field_item_list;
$field_item_list
->setValue(NULL);
foreach ($server_field_item_list as $index => $server_field_item) {
$entity_id = $server_field_item->target_id;
foreach ($field_item_list_unsorted as $local_item) {
if ($entity_id == $local_item->target_id) {
// If an entity has been flagged as needing a manual merge, then
// we have to keep the local version for the merge UI, otherwise
// we can inherit the remote version.
if ($local_item->entity->{EntityConflictHandlerInterface::CONFLICT_ENTITY_NEEDS_MANUAL_MERGE}) {
$item_value = $local_item
->getValue();
$item_value['entity'] = $local_item->entity;
}
else {
$item_value = $server_field_item
->getValue();
$item_value['entity'] = $server_field_item->entity;
if ($form_state) {
// During a form submission this code will be called twice
// - first during the validation to build the entity and
// then during the submission. However if we exchange the
// server entity with the static reference too early, then
// the old user input will be mapped on it. Therefore we
// need to exchange it with the proper reference first after
// the validation is complete. Until then break the global
// reference by using a clone.
if (!$form_state
->isValidationComplete()) {
$item_value['entity'] = clone $item_value['entity'];
}
// Prevent mapping the user input. On form rebuild the
// values from the remote entity should be used instead of
// the ones submitted in the current session.
$path = [
$property,
$index,
];
$input =& $form_state
->getUserInput();
NestedArray::unsetValue($input, $path);
}
}
$field_item_list
->appendItem($item_value);
break;
}
}
}
// TODO this supports only paragraphs at first level.
if ($form_state) {
$this
->reorderWidgetState($field_item_list, $form_state);
}
}
else {
$new_paragraph_ids = array_diff($server_paragraph_ids_sorted, $original_paragraph_ids_sorted);
$removed_paragraph_ids = array_diff($original_paragraph_ids_sorted, $server_paragraph_ids_sorted);
// Only new paragraphs added.
if ($new_paragraph_ids && empty($removed_paragraph_ids)) {
/** @var \Drupal\entity_reference_revisions\EntityReferenceRevisionsFieldItemList $field_item_list */
$field_item_list = $result_entity
->get($property);
$server_field_item_list = $remote_entity
->get($property);
$field_item_list_unsorted = clone $field_item_list;
$field_item_list
->setValue(NULL);
foreach ($server_paragraph_ids_unsorted as $index => $entity_id) {
foreach ($field_item_list_unsorted as $item) {
if ($entity_id == $item->target_id) {
$item_value = $item
->getValue();
$item_value['entity'] = $item->entity;
$field_item_list
->appendItem($item_value);
// Found, do not search in the server list to append.
continue 2;
}
}
foreach ($server_field_item_list as $item) {
if ($entity_id == $item->target_id) {
$item_value = $item
->getValue();
$item_value['entity'] = $item->entity;
$field_item_list
->appendItem($item_value);
if ($form_state && !$form_state
->isValidationComplete()) {
$item_value['entity'] = clone $item_value['entity'];
}
break;
}
}
}
// TODO this supports only paragraphs at first level.
if ($form_state) {
$this
->reorderWidgetState($field_item_list, $form_state);
}
}
elseif ($removed_paragraph_ids && empty($new_paragraph_ids)) {
/** @var \Drupal\entity_reference_revisions\EntityReferenceRevisionsFieldItemList $field_item_list */
$field_item_list = $result_entity
->get($property);
$field_item_list_unsorted = clone $field_item_list;
$field_item_list
->setValue(NULL);
foreach ($field_item_list_unsorted as $item) {
if (!in_array($item->target_id, $removed_paragraph_ids)) {
$item_value = $item
->getValue();
$item_value['entity'] = $item->entity;
$field_item_list
->appendItem($item_value);
}
else {
// Keep the entity only if it is flagged as conflicting,
// otherwise it was not changed by the current session and can
// be removed.
$entity = $item->entity;
if ($entity->{EntityConflictHandlerInterface::CONFLICT_ENTITY_NEEDS_MANUAL_MERGE} && $entity->{EntityConflictHandlerInterface::CONFLICT_ENTITY_SERVER} === 'removed') {
$item_value = $item
->getValue();
$item_value['entity'] = $item->entity;
$field_item_list
->appendItem($item_value);
}
}
}
// TODO this supports only paragraphs at first level.
if ($form_state) {
$this
->reorderWidgetState($field_item_list, $form_state);
}
}
elseif (!empty($removed_paragraph_ids) && !empty($new_paragraph_ids)) {
// TODO not yet supported.
if ($form_state) {
$form_state
->set('manual-merge-not-possible', TRUE);
}
}
}
}
}
}