|
<?php |
|
|
|
/** |
|
* @property integer $total Total entities in set |
|
* @property array $unchanged entities that were left unchanged |
|
* @property array $succeeded entities that was successfully migrated |
|
* @property array $failed entities that failed to migrate |
|
* @property bool $success if all the entities were successfully migrated |
|
*/ |
|
class ContentEntityMigrationResult extends stdClass |
|
{} |
|
|
|
|
|
abstract class ContentEntityMigrationTool |
|
{ |
|
const ENTITY_TYPE = ''; |
|
const ENTITY_ID_COL = ''; |
|
const ENTITY_GROUP_COL = ''; |
|
|
|
const DATABASE_TARGET = 'default'; |
|
const DATABASE_KEY = null; |
|
|
|
/** |
|
* @return \Drupal\Core\Database\Connection |
|
*/ |
|
public static function getDatabase() |
|
{ |
|
return \Drupal\Core\Database\Database::getConnection( |
|
static::DATABASE_TARGET, |
|
static::DATABASE_KEY |
|
); |
|
} |
|
|
|
/** |
|
* @return \Drupal\Core\Entity\EntityStorageInterface|null |
|
*/ |
|
public static function getStorage() |
|
{ |
|
try { |
|
return \Drupal |
|
::entityTypeManager() |
|
->getStorage(static::ENTITY_TYPE); |
|
} catch (\Drupal\Component\Plugin\Exception\PluginNotFoundException $e) { |
|
} catch (\Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException $e) { |
|
} |
|
return null; |
|
} |
|
|
|
/** |
|
* @param string|int $groupId |
|
* @param Closure|null $queryCallback |
|
* |
|
* @return \Drupal\Core\Entity\ContentEntityInterface[]|string[]|int[] |
|
*/ |
|
public static function entitiesByGroup($groupId, $queryCallback = null) |
|
{ |
|
$query = static::getStorage()->getQuery(); |
|
$query->condition(static::ENTITY_GROUP_COL, $groupId); |
|
if ($queryCallback instanceof \Closure) { |
|
$query = call_user_func($queryCallback, $query); |
|
} |
|
|
|
return $query->execute(); |
|
} |
|
|
|
/** |
|
* @param \Drupal\Core\Entity\ContentEntityInterface|object|string|int $entity |
|
* |
|
* @return int|string |
|
*/ |
|
public static function ensureEntityId(&$entity) |
|
{ |
|
if (is_object($entity)) { |
|
return $entity->id(); |
|
} |
|
|
|
return $entity; |
|
} |
|
|
|
/** |
|
* @param string|int $id |
|
* |
|
* @return \Drupal\Core\Entity\EntityInterface|null |
|
*/ |
|
public static function entityById($id) |
|
{ |
|
return static::getStorage()->load($id); |
|
} |
|
|
|
/** |
|
* @param \Drupal\Core\Entity\ContentEntityInterface|string|int $entity |
|
* @param string|int $targetGroupId |
|
* |
|
* @return null|bool Returns boolean about success of change, null if change was not necessary |
|
*/ |
|
abstract public static function changeEntityGroupId(&$entity, $targetGroupId); |
|
|
|
/** |
|
* @param $sourceGroupId |
|
* @param $targetGroupId |
|
* @param Closure|null $queryCallback |
|
* |
|
* @return ContentEntityMigrationResult |
|
*/ |
|
public static function migrateToAnotherGroup($sourceGroupId, $targetGroupId, $queryCallback = null) |
|
{ |
|
$entities = static::entitiesByGroup($sourceGroupId, $queryCallback); |
|
$result = new ContentEntityMigrationResult; |
|
$result->total = count($entities); |
|
$result->unchanged = []; |
|
$result->succeeded = []; |
|
$result->failed = []; |
|
foreach ($entities as $entity) { |
|
$change = static::changeEntityGroupId($entity, $targetGroupId); |
|
if (is_null($change)) { |
|
$result->unchanged[] = $entity; |
|
} else { |
|
if ($change) { |
|
$result->succeeded[] = $entity; |
|
} else { |
|
$result->failed[] = $entity; |
|
} |
|
} |
|
} |
|
$result->success = (count($result->succeeded) == $result->total); |
|
|
|
return $result; |
|
} |
|
} |
|
|
|
/** |
|
* Class NodeMigrationTool |
|
* |
|
* @method static \Drupal\node\NodeStorage|null getStorage() |
|
*/ |
|
//class NodeMigrationToolContent extends ContentEntityMigrationTool |
|
//{ |
|
// const ENTITY_TYPE = 'node'; |
|
// const ENTITY_ID_COL = 'nid'; |
|
// const ENTITY_GROUP_COL = 'type'; |
|
|
|
// public static function changeEntityGroupId(&$entity, $targetGroupId, $queryCallback = null, $verify = false) |
|
// { |
|
// $storage = static::getStorage(); |
|
// |
|
// // Get the names of the base tables. |
|
// $baseTableNames = []; |
|
// $baseTableNames[] = $storage->getBaseTable(); |
|
// $baseTableNames[] = $storage->getDataTable(); |
|
// // (Note that revision base tables don't have the bundle.) |
|
// |
|
// // For field tables, we need to ask the table mapping handler: |
|
// $tableMapping = $storage->getTableMapping(); |
|
// |
|
// // Get the names of the field tables for fields on the taxonomy dictionary. |
|
// $fieldTableNames = []; |
|
// foreach ($source_bundle_fields as $field) { |
|
// $field_table = $tableMapping->getFieldTableName($field->getName()); |
|
// $fieldTableNames[] = $field_table; |
|
// |
|
// $field_storage_definition = $field->getFieldStorageDefinition(); |
|
// $field_revision_table = $tableMapping |
|
// ->getDedicatedRevisionTableName($field_storage_definition); |
|
// |
|
// // Field revision tables DO have the bundle! |
|
// $fieldTableNames[] = $field_revision_table; |
|
// } |
|
// |
|
// // Get the node IDs to update. |
|
// $query = \Drupal::service('entity.query')->get('node'); |
|
// // Your conditions here! |
|
// // In our case, page nodes with a certain field populated. |
|
// $query->condition('type', 'page'); |
|
// $query->exists(‘field_in_question’); |
|
// $nids = $query->execute(); |
|
// |
|
// // Base tables have 'nid' and 'type' columns. |
|
// foreach ($baseTableNames as $table_name) { |
|
// $query = static::getDatabase() |
|
// ->update($table_name) |
|
// ->fields(['type' => 'service']) |
|
// ->condition('nid', $service_nids, 'IN') |
|
// ->execute(); |
|
// } |
|
// |
|
// // Field tables have 'entity_id' and 'bundle' columns. |
|
// foreach ($fieldTableNames as $table_name) { |
|
// $query = static::getDatabase() |
|
// ->update($table_name) |
|
// ->fields(['bundle' => 'service']) |
|
// ->condition('entity_id', $service_nids, 'IN') |
|
// ->execute(); |
|
// } |
|
// } |
|
//} |
|
|
|
/** |
|
* Class TermMigrationTool |
|
* |
|
* @method static \Drupal\taxonomy\TermStorage|null getStorage() |
|
* @method static \Drupal\taxonomy\TermInterface|null entityById($id) |
|
*/ |
|
class TermMigrationToolContent extends ContentEntityMigrationTool |
|
{ |
|
const ENTITY_TYPE = 'taxonomy_term'; |
|
const ENTITY_ID_COL = 'tid'; |
|
const ENTITY_GROUP_COL = 'vid'; |
|
|
|
/** |
|
* @inheritdoc |
|
*/ |
|
public static function changeEntityGroupId(&$entity, $targetGroupId, $queryCallback = null, $verify = false) |
|
{ |
|
$result = null; |
|
if (!is_object($entity)) { |
|
$entity = static::entityById($entity); |
|
} |
|
if ($entity->get(static::ENTITY_GROUP_COL) === $targetGroupId) { |
|
return $result; |
|
} |
|
$entityId = static::ensureEntityId($entity); |
|
|
|
$storage = static::getStorage(); |
|
|
|
// Get the names of the base tables. |
|
$baseTableNames = []; |
|
$baseTableNames[] = $storage->getBaseTable(); |
|
$baseTableNames[] = $storage->getDataTable(); |
|
|
|
$transactionId = 'changeEntityGroupId'; |
|
static::getDatabase()->startTransaction($transactionId); |
|
foreach ($baseTableNames as $tableName) { |
|
$query = static |
|
::getDatabase() |
|
->update($tableName) |
|
->fields([static::ENTITY_GROUP_COL => $targetGroupId]) |
|
->condition(static::ENTITY_ID_COL, $entityId, '='); |
|
try { |
|
$queryResult = $query->execute(); |
|
} catch (Exception $e) { |
|
$queryResult = false; |
|
} |
|
if ($queryResult) { |
|
if ($verify) { |
|
$entity = static::getStorage()->load($entity); |
|
$result = ($entity->get(static::ENTITY_GROUP_COL) === $targetGroupId); |
|
} else { |
|
$result = true; |
|
} |
|
} |
|
if ($result === false) { |
|
break; |
|
} |
|
} |
|
if ($result === false) { |
|
static::getDatabase()->rollBack($transactionId); |
|
} |
|
|
|
return $result; |
|
} |
|
} |