migmag-1.0.x-dev/migmag_rollbackable/src/Traits/RollbackableTrait.php
migmag_rollbackable/src/Traits/RollbackableTrait.php
<?php
declare(strict_types=1);
namespace Drupal\migmag_rollbackable\Traits;
use Drupal\migrate\Row;
/**
* Trait for rollbackable destination plugins.
*/
trait RollbackableTrait {
use RollbackableConnectionTrait;
use RollbackableDataTrait;
use RollbackableFlagTrait;
use RollbackableTargetTrait;
/**
* {@inheritdoc}
*/
public function import(Row $row, array $old_destination_id_values = []) {
$target_object_id = $this->getTargetObjectId($row);
$component = $this->getTargetComponent($row);
$langcode = $this->getTargetLangcode($row);
// We need to know whether the config was new BEFORE we called the original
// import method of the parent class. If something goes wrong during the
// actual import (e.g. we run into an exception), we shouldn't flag the
// config as new.
if ($component) {
$component_was_new = $this->targetObjectComponentIsNew($target_object_id, $component, $langcode);
}
$target_was_new = $this->targetObjectIsNew($target_object_id, $langcode);
$previous_values = $this->getPreviousValues($row, $target_object_id, $component, $langcode);
// Parent import returns TRUE when an actual save happened. But since an
// ID map entry is saved only if the returned value is not 'TRUE', we need a
// meaningful value.
if ($parent_destination_ids = parent::import($row, $old_destination_id_values)) {
// Only flag the target component as new component if it is not considered
// as being new after the import.
if (
!empty($component_was_new) &&
!$this->targetObjectComponentIsNew($target_object_id, $component, $langcode)
) {
$this->flagTargetAsNew($target_object_id, $component, $langcode);
}
if ($target_was_new) {
$this->flagTargetAsNew($target_object_id, '', $langcode);
}
// We will save rollback data if there is no preexisting record saved by
// the actual migration, even if the new config is exactly the same as the
// old, because we want to restore the original state if every related
// migration was rolled back.
$this->saveTargetRollbackData($target_object_id, $previous_values, $component, $langcode);
return $this->generateDestinationIds($parent_destination_ids, $target_object_id, $component, $langcode);
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function rollback(array $destination_identifier) {
$target_object_id = $this->getTargetObjectId($destination_identifier);
$component = $this->getTargetComponent($destination_identifier);
$langcode = $this->getTargetLangcode($destination_identifier);
// If the config does not exist now, and was therefore generated on the fly,
// there is nothing to roll back. We have to clean up all the related data
// we stored before.
if ($this->targetObjectIsNew($target_object_id, $langcode)) {
$this->cleanUpAllLeftovers($target_object_id, $langcode);
return;
}
// Act on the current migration plugin's rollback data.
// This does the PARTIAL rollback: key-value pairs within the config.
// Partial means that we might have keys that weren't touched during the
// migration – we neither modify those on rollback.
$this->performRollback($target_object_id, $component, $langcode);
$this->postRollbackCleanup($target_object_id, $langcode);
}
/**
* Removes ANY rollback data as well as the 'new' flags.
*
* This method shouldn't be used unless the target object was deleted before
* rolling back any of the related migrations.
*
* @param string $target_object_id
* The ID of the target object (a configuration, entity etc).
* @param string $langcode
* The language code.
*/
protected function cleanUpAllLeftovers(string $target_object_id, string $langcode) {
if ($this->targetHasAnyRollbackData($target_object_id, $langcode)) {
$this->deleteAllTargetRollbackData($target_object_id, $langcode);
}
$this->removeEveryNewTargetFlag($target_object_id, $langcode);
}
/**
* Performs the data rollback for the current target.
*
* @param string $target_object_id
* The ID of the target object (a configuration, entity etc).
* @param string $component
* The name (an internal unique identifier) of the component.
* @param string $langcode
* The language code.
*/
protected function performRollback(string $target_object_id, string $component, string $langcode) {
if ($this->targetHasRollbackData($target_object_id, $component, $langcode)) {
$this->doDataRollback(
$this->getTargetRollbackData($target_object_id, $component, $langcode),
$target_object_id,
$component,
$langcode
);
$this->deleteTargetRollbackData($target_object_id, $component, $langcode);
}
}
/**
* Performs post-rollback cleanup.
*
* Deletes the given config if it was created by a rollbackable migration and
* removes the related 'new' flag.
*
* @param string $target_object_id
* The ID of the target object (a configuration, entity etc).
* @param string $langcode
* The language code.
*/
protected function postRollbackCleanup(string $target_object_id, string $langcode) {
if (
!$this->targetHasAnyRollbackData($target_object_id, $langcode) &&
$this->targetHasNewFlag($target_object_id, '', $langcode)
) {
$this->deleteTargetObject($target_object_id, $langcode);
$this->removeEveryNewTargetFlag($target_object_id, $langcode);
}
}
}
