diff --git a/core/modules/migrate/src/Audit/AuditInterface.php b/core/modules/migrate/src/Audit/AuditInterface.php deleted file mode 100644 index e70bf12809..0000000000 --- a/core/modules/migrate/src/Audit/AuditInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -audit(); - } - elseif ($destination->getHighestId() > $id_map->getHighestId()) { + if ($destination->getHighestId() > $id_map->getHighestId() || ($destination instanceof EntityContentComplete && $this->auditEntityComplete($migration))) { return AuditResult::fail($migration, [ $this->t('The destination system contains data which was not created by a migration.'), ]); } + return AuditResult::pass($migration); } @@ -58,4 +57,44 @@ public function auditMultiple(array $migrations) { return $conflicts; } + /** + * Audits an EntityComplete migration. + * + * @param \Drupal\migrate\Plugin\MigrationInterface $migration + * The migration to audit. + * + * @return bool + * TRUE if the audit passes and FALSE if not. + * + * @todo Refactor in https://www.drupal.org/project/drupal/issues/3061676 or + * https://www.drupal.org/project/drupal/issues/3091004 + */ + private function auditEntityComplete(MigrationInterface $migration) { + $map_table = $migration->getIdMap()->mapTableName(); + + $database = \Drupal::database(); + if (!$database->schema()->tableExists($map_table)) { + throw new \InvalidArgumentException(); + } + + $query = $database->select($map_table, 'map') + ->fields('map', ['destid2']) + ->range(0, 1) + ->orderBy('destid2', 'DESC'); + $max = (int) $query->execute()->fetchField(); + + // Make a migration based on node_complete but with an entity_revision + // destination. + $revision_migration = $migration->getPluginDefinition(); + $revision_migration['id'] = $migration->getPluginId() . '-revision'; + $revision_migration['destination']['plugin'] = 'entity_revision:node'; + $revision_migration = \Drupal::service('plugin.manager.migration')->createStubMigration($revision_migration); + + // Get the highest node revision ID. + $destination = $revision_migration->getDestinationPlugin(); + $highest = $destination->getHighestId(); + + return $max <= $highest; + } + } diff --git a/core/modules/migrate/src/Plugin/migrate/destination/EntityContentComplete.php b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentComplete.php index c7e2bcbe0e..88e44bab65 100644 --- a/core/modules/migrate/src/Plugin/migrate/destination/EntityContentComplete.php +++ b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentComplete.php @@ -2,19 +2,10 @@ namespace Drupal\migrate\Plugin\migrate\destination; -use Drupal\Core\Database\Connection; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityChangedInterface; -use Drupal\Core\Entity\EntityFieldManagerInterface; -use Drupal\Core\Entity\EntityStorageInterface; -use Drupal\Core\Field\FieldTypePluginManagerInterface; -use Drupal\migrate\Audit\AuditInterface; -use Drupal\migrate\Audit\AuditResult; use Drupal\migrate\EntityFieldDefinitionTrait; -use Drupal\migrate\Plugin\MigrationInterface; -use Drupal\migrate\Plugin\MigrationPluginManagerInterface; use Drupal\migrate\Row; -use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides a destination for migrating the entire entity revision table. @@ -24,66 +15,10 @@ * deriver = "Drupal\migrate\Plugin\Derivative\MigrateEntityComplete" * ) */ -class EntityContentComplete extends EntityContentBase implements AuditInterface { +class EntityContentComplete extends EntityContentBase { use EntityFieldDefinitionTrait; - /** - * The migration plugin manager. - * - * @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface - */ - protected $migrationPluginManager; - - /** - * Constructs a content entity. - * - * @param array $configuration - * A configuration array containing information about the plugin instance. - * @param string $plugin_id - * The plugin ID for the plugin instance. - * @param mixed $plugin_definition - * The plugin implementation definition. - * @param \Drupal\migrate\Plugin\MigrationInterface $migration - * The migration entity. - * @param \Drupal\Core\Entity\EntityStorageInterface $storage - * The storage for this entity type. - * @param array $bundles - * The list of bundles this entity type has. - * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager - * The entity field manager. - * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager - * The field type plugin manager service. - * @param \Drupal\migrate\Plugin\MigrationPluginManagerInterface $migration_plugin_manager - * The migration plugin manager. - * @param \Drupal\Core\Database\Connection $database - * The database. - */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, EntityStorageInterface $storage, array $bundles, EntityFieldManagerInterface $entity_field_manager, FieldTypePluginManagerInterface $field_type_manager, MigrationPluginManagerInterface $migration_plugin_manager, Connection $database) { - parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $storage, $bundles, $entity_field_manager, $field_type_manager); - $this->migrationPluginManager = $migration_plugin_manager; - $this->database = $database; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) { - $entity_type = static::getEntityTypeId($plugin_id); - return new static( - $configuration, - $plugin_id, - $plugin_definition, - $migration, - $container->get('entity_type.manager')->getStorage($entity_type), - array_keys($container->get('entity_type.bundle.info')->getBundleInfo($entity_type)), - $container->get('entity_field.manager'), - $container->get('plugin.manager.field.field_type'), - $container->get('plugin.manager.migration'), - $container->get('database') - ); - } - /** * {@inheritdoc} */ @@ -180,65 +115,4 @@ protected function save(ContentEntityInterface $entity, array $old_destination_i ]; } - /** - * {@inheritdoc} - */ - public function audit() { - // Check node IDs first. - if ($this->getHighestId() > $this->migration->getIdMap()->getHighestId()) { - return AuditResult::fail($this->migration, [ - $this->t('The destination system contains data which was not created by a migration.'), - ]); - } - - $max = $this->getHighestMigratedNodeRevisionId(); - - // Make a migration based on node_complete but with an entity_revision - // destination. - $revision_migration = $this->migration->getPluginDefinition(); - $revision_migration['id'] = $this->migration->getPluginId() . '-revision'; - $revision_migration['destination']['plugin'] = 'entity_revision:node'; - $revision_migration = $this->migrationPluginManager->createStubMigration($revision_migration); - - // Get the highest node revision ID. - $destination = $revision_migration->getDestinationPlugin(); - $highest = $destination->getHighestId(); - - if ($highest > $max) { - return AuditResult::fail($this->migration, [ - t('The destination system contains data which was not created by a migration.'), - ]); - } - - return AuditResult::pass($this->migration); - } - - /** - * Gets highest migrated node revision ID. - * - * @return int - * The highest migrated node revision ID. - * - * @throws \InvalidArgumentException - * Thrown when the ID map table does not exist. - */ - protected function getHighestMigratedNodeRevisionId() : int { - $map_table = $this->migration->getIdMap()->mapTableName(); - - // @todo It seems that we should implement this on the ID map as accessing - // the database directly here looks wrong. - if (!$this->database->schema()->tableExists($map_table)) { - throw new \InvalidArgumentException(); - } - - $query = $this->database->select($map_table, 'map') - ->fields('map', ['destid2']) - ->range(0, 1) - ->orderBy('destid2', 'DESC'); - $ids[] = $query->execute()->fetchField(); - $max = (int) (max($ids)); - - return $max; - } - }