final class Migrator in Lightning Workflow 8.3
Same name and namespace in other branches
- 8.2 modules/lightning_scheduler/src/Migrator.php \Drupal\lightning_scheduler\Migrator
The migration is not an API and should not be extended or re-used.
Hierarchy
- class \Drupal\lightning_scheduler\Migrator uses StringTranslationTrait
Expanded class hierarchy of Migrator
2 files declare their use of Migrator
- MigrationCommands.php in modules/
lightning_scheduler/ src/ Commands/ MigrationCommands.php - MigrationConfirmationForm.php in modules/
lightning_scheduler/ src/ Form/ MigrationConfirmationForm.php
1 string reference to 'Migrator'
- lightning_scheduler.services.yml in modules/
lightning_scheduler/ lightning_scheduler.services.yml - modules/lightning_scheduler/lightning_scheduler.services.yml
1 service uses Migrator
- lightning_scheduler.migrator in modules/
lightning_scheduler/ lightning_scheduler.services.yml - Drupal\lightning_scheduler\Migrator
File
- modules/
lightning_scheduler/ src/ Migrator.php, line 21
Namespace
Drupal\lightning_schedulerView source
final class Migrator {
use StringTranslationTrait;
/**
* The entity type manager service.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The database service.
*
* @var \Drupal\Core\Database\Connection
*/
protected $database;
/**
* The state service.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;
/**
* The messenger service.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* Migrator constructor.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager service.
* @param \Drupal\Core\Database\Connection $database
* The database service.
* @param \Drupal\Core\State\StateInterface $state
* The state service.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger service.
* @param \Drupal\Core\StringTranslation\TranslationInterface $translation
* (optional) The string translation service.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, Connection $database, StateInterface $state, MessengerInterface $messenger, TranslationInterface $translation = NULL) {
$this->entityTypeManager = $entity_type_manager;
$this->database = $database;
$this->state = $state;
$this->messenger = $messenger;
if ($translation) {
$this
->setStringTranslation($translation);
}
}
/**
* Returns the entity types still needing migration.
*
* @return string[]
* The entity type IDs that still need to be migrated.
*/
public function getMigrations() {
return $this->state
->get('lightning_scheduler.migrations', []);
}
/**
* Sets the entity types still needing migration.
*
* @param string[] $migrations
* The entity type IDs that still need to be migrated.
*/
public function setMigrations(array $migrations) {
return $this->state
->set('lightning_scheduler.migrations', $migrations);
}
/**
* Returns all content entity types which need to be migrated.
*
* @param string[] $limit
* (optional) An array of entity type IDs. If given, only those entity types
* will be considered.
*
* @return \Drupal\Core\Entity\EntityTypeInterface[]
* The entity types that need to be migrated.
*/
public function getEntityTypesToMigrate(array $limit = []) {
// Only content entities which have been marked as needing migration are
// considered.
$filter = function (EntityTypeInterface $entity_type) {
return $entity_type
->entityClassImplements(ContentEntityInterface::class);
};
$entity_types = array_filter($this->entityTypeManager
->getDefinitions(), $filter);
$migrations = $limit ?: $this
->getMigrations();
$migrations = array_flip($migrations);
return array_intersect_key($entity_types, $migrations);
}
/**
* Queries for all entities of a specific type which need to be migrated.
*
* @param string $entity_type_id
* The entity type ID.
*
* @return \Drupal\Core\Entity\Query\QueryInterface
* The prepared query.
*/
public function query($entity_type_id) {
$entity_type = $this->entityTypeManager
->getDefinition($entity_type_id);
$fields = [
$entity_type
->getKey('id'),
'scheduled_publication',
'scheduled_moderation_state',
];
if ($entity_type
->isRevisionable()) {
array_push($fields, $entity_type
->getKey('revision'));
}
if ($entity_type
->isTranslatable()) {
array_push($fields, $entity_type
->getKey('langcode'));
}
$table = $entity_type
->getRevisionDataTable() ?: $entity_type
->getDataTable();
return $this->database
->select($table)
->fields($table, $fields)
->isNotNull('scheduled_publication')
->isNotNull('scheduled_moderation_state');
}
/**
* Migrates all entities of a specific type.
*
* @param string $entity_type_id
* The entity type ID to migrate.
* @param callable $callback
* (optional) A callback to invoke after each item is migrated. It receives
* the entity type ID, the number of items migrated so far, the item itself
* (which will be an \stdClass object), and the migrator service.
*
* @return int
* The number of items that were migrated.
*/
public function migrateAll($entity_type_id, callable $callback = NULL) {
$items = $this
->query($entity_type_id)
->execute();
$count = 0;
foreach ($items as $item) {
$this
->migrate($entity_type_id, $item);
if ($callback) {
$callback($entity_type_id, ++$count, $item, $this);
}
}
$this
->completeMigration($entity_type_id);
return $count;
}
/**
* Migrates a single entity.
*
* @param string $entity_type_id
* The entity type ID.
* @param object $item
* The relevant entity information, as returned from query(). This will
* include the entity ID and values of the scheduled_moderation_state and
* scheduled_publication fields. Will also include the revision ID and
* langcode, if the entity type is revisionable and translatable,
* respectively.
*/
public function migrate($entity_type_id, $item) {
$storage = $this->entityTypeManager
->getStorage($entity_type_id);
$entity = $this
->load($storage, $item);
// A horrible hack to work around Content Moderation's opinions being a
// little too strong. See lightning_scheduler_entity_presave().
$entity->existingRevisionId = $entity
->getRevisionId();
$entity
->set('scheduled_transition_date', $item->scheduled_publication)
->set('scheduled_transition_state', $item->scheduled_moderation_state)->original
->set('scheduled_transition_date', NULL)
->set('scheduled_transition_state', NULL);
$storage
->save($entity);
}
/**
* Purges the data for a single base field field on a single entity type.
*
* Only entity types with SQL storage are supported.
*
* @param string $entity_type_id
* The entity type ID.
* @param string $field_name
* The name of the field to purge data.
*/
public function purge($entity_type_id, $field_name) {
$storage = $this->entityTypeManager
->getStorage($entity_type_id);
if ($storage instanceof SqlEntityStorageInterface) {
$table_mapping = $storage
->getTableMapping();
$values = [];
foreach ($table_mapping
->getColumnNames($field_name) as $column) {
$values[$column] = NULL;
}
$this->database
->update($table_mapping
->getFieldTableName($field_name))
->fields($values)
->execute();
}
}
/**
* Loads an entity to be migrated.
*
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
* The entity storage handler.
* @param object $item
* The relevant entity information. See ::migrate() for details.
*
* @return \Drupal\Core\Entity\ContentEntityInterface
* The loaded entity, with $entity->original set.
*/
protected function load(EntityStorageInterface $storage, $item) {
$entity_type = $storage
->getEntityType();
$id_key = $entity_type
->getKey('id');
if ($entity_type
->isRevisionable()) {
$vid_key = $entity_type
->getKey('revision');
}
if ($entity_type
->isTranslatable()) {
$language_key = $entity_type
->getKey('langcode');
}
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = isset($vid_key) ? $storage
->loadRevision($item->{$vid_key}) : $storage
->load($item->{$id_key});
if (isset($language_key)) {
$entity = $entity
->getTranslation($item->{$language_key});
}
$entity->original = $storage
->loadUnchanged($item->{$id_key});
return $entity;
}
/**
* Completes the migration for a single entity type.
*
* If the scheduled_publication or scheduled_moderation_state fields have
* been overridden, those overrides will be deleted in order to revert the
* fields and a message will be displayed reminding the user to remove those
* fields from their exported config.
*
* @param string $entity_type_id
* The entity type ID.
*/
public function completeMigration($entity_type_id) {
$storage = $this->entityTypeManager
->getStorage('base_field_override');
$overridden_fields = $storage
->getQuery()
->condition('entity_type', $entity_type_id)
->condition('field_name', [
'scheduled_publication',
'scheduled_moderation_state',
])
->execute();
if ($overridden_fields) {
$overridden_fields = $storage
->loadMultiple($overridden_fields);
$storage
->delete($overridden_fields);
$message = $this
->t('Overridden scheduled_publication and scheduled_moderation_state fields were detected. They have been reverted, but you must remember to remove them from your exported config.');
$this->messenger
->addWarning($message);
}
// Base fields have been reverted, and the migration is now complete.
$migrations = array_diff($this
->getMigrations(), [
$entity_type_id,
]);
$this
->setMigrations($migrations);
}
/**
* Generates a message to be shown before migrating a set of entity types.
*
* @param \Drupal\Core\Entity\EntityTypeInterface[] $entity_types
* The entity types that will be migrated.
* @param bool $html
* Whether to include HTML tags in the message.
*
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
* The generated message.
*/
public function generatePreMigrationMessage(array $entity_types, $html = TRUE) {
$entity_types = $this
->entityTypeOptions($entity_types);
$variables = [
'@entity_types' => Element::oxford($entity_types),
':maintenance_mode' => Url::fromRoute('system.site_maintenance_mode')
->toString(),
];
return $html ? $this
->t('You are about to migrate scheduled transitions for all @entity_types. This will modify your existing content and may take a long time if you have a huge site with tens of thousands of pieces of content. <strong>You cannot undo this</strong>, so you may want to <strong>back up your database</strong> and <a href=":maintenance_mode">switch to maintenance mode</a> before continuing.', $variables) : $this
->t('You are about to migrate scheduled transitions for all @entity_types. This will modify your existing content and may take a long time if you have a huge site with tens of thousands of pieces of content. You cannot undo this, so you may want to back up your database and switch to maintenance mode before continuing.', $variables);
}
/**
* Converts a set of entity type definitions to key/value options.
*
* @param \Drupal\Core\Entity\EntityTypeInterface[] $entity_types
* The entity type definitions.
*
* @return string[]
* The entity type labels, keyed by entity type ID.
*/
public function entityTypeOptions(array $entity_types) {
$to_option = function (EntityTypeInterface $entity_type) {
return $entity_type
->getPluralLabel();
};
return array_map($to_option, $entity_types);
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
Migrator:: |
protected | property | The database service. | |
Migrator:: |
protected | property | The entity type manager service. | |
Migrator:: |
protected | property | The messenger service. | |
Migrator:: |
protected | property | The state service. | |
Migrator:: |
public | function | Completes the migration for a single entity type. | |
Migrator:: |
public | function | Converts a set of entity type definitions to key/value options. | |
Migrator:: |
public | function | Generates a message to be shown before migrating a set of entity types. | |
Migrator:: |
public | function | Returns all content entity types which need to be migrated. | |
Migrator:: |
public | function | Returns the entity types still needing migration. | |
Migrator:: |
protected | function | Loads an entity to be migrated. | |
Migrator:: |
public | function | Migrates a single entity. | |
Migrator:: |
public | function | Migrates all entities of a specific type. | |
Migrator:: |
public | function | Purges the data for a single base field field on a single entity type. | |
Migrator:: |
public | function | Queries for all entities of a specific type which need to be migrated. | |
Migrator:: |
public | function | Sets the entity types still needing migration. | |
Migrator:: |
public | function | Migrator constructor. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. |