cloudinary-8.x-1.x-dev/modules/cloudinary_source_migrate/cloudinary_source_migrate.deploy.php
modules/cloudinary_source_migrate/cloudinary_source_migrate.deploy.php
<?php
/**
* @file
* Perform scripts after config import.
*/
use Cloudinary\Asset\AssetType;
use Cloudinary\Asset\DeliveryType;
use Drupal\Core\Field\FieldItemBase;
/**
* Migrate old cloudinary media entities to new bundles.
*/
function cloudinary_source_migrate_deploy_media_entites(array &$sandbox) {
/** @var \Drupal\cloudinary_source_migrate\CloudinarySourceMigrateHelperInterface $migrate_helper */
$migrate_helper = \Drupal::service('cloudinary_source_migrate.helper');
$old_new_bundle_map = $migrate_helper->getMediaBundleMap();
if (!$old_new_bundle_map) {
return;
}
if (!isset($sandbox['progress'])) {
$sandbox['progress'] = 0;
// Get all media ids of old media bundles.
$ids = \Drupal::entityQuery('media')
->accessCheck(FALSE)
->condition('bundle', array_keys($old_new_bundle_map), 'IN')
->execute();
if (!$ids) {
return;
}
$sandbox['total'] = count($ids);
$sandbox['ids'] = array_chunk(array_values($ids), 5);
}
$ids = array_pop($sandbox['ids']) ?? [];
if (!$ids) {
$sandbox['#finished'] = 1;
}
// Init cloudinary sdk manually to work within CLI.
cloudinary_sdk_init();
$media_storage = \Drupal::entityTypeManager()->getStorage('media');
$media_type_storage = \Drupal::entityTypeManager()->getStorage('media_type');
/** @var \Drupal\cloudinary_sdk\Service\AssetHelperInterface $asset_helper */
$asset_helper = \Drupal::service('cloudinary_sdk.asset_helper');
/** @var \Drupal\cloudinary_media_library_widget\Service\CloudinaryFileHelperInterface $file_helper */
$file_helper = \Drupal::service('cloudinary_media_library_widget.file_helper');
/** @var \Drupal\media\MediaInterface[] $entities */
$entities = $media_storage->loadMultiple($ids);
/** @var \Drupal\media\MediaTypeInterface[] $media_types */
$media_types = $media_type_storage->loadMultiple(array_values($old_new_bundle_map));
foreach ($entities as $source_media) {
// Migrate media only once.
if ($migrate_helper->isMigrated($source_media)) {
continue;
}
$source_configuration = $source_media->getSource()->getConfiguration();
$source_resource_type = $source_configuration['source_field'];
$item = $source_media->get($source_resource_type)->first();
assert($item instanceof FieldItemBase);
// Get target media type information.
$target_media_id = $old_new_bundle_map[$source_media->bundle()];
$target_media_type = $media_types[$target_media_id];
$target_media_type_configuration = $target_media_type->getSource()
->getConfiguration();
$target_source_field = $target_media_type_configuration['source_field'];
$target_resource_type = $target_media_type_configuration['resource_type'];
$default_values = [];
// Migrate custom cloudinary transformation from the specific field.
if ($source_media->hasField('field_cloudinary_transformation')) {
$default_values['transformation'] = $source_media->get('field_cloudinary_transformation')->value;
}
// Populate default values for the image.
if ($target_resource_type === AssetType::IMAGE) {
$default_values['width'] = $item->width;
$default_values['title'] = $item->title;
$default_values['alt'] = $item->alt;
$default_values['height'] = $item->height;
}
try {
$asset = $migrate_helper->getAssetFromFieldItem($item, $target_resource_type);
}
catch (\Exception $e) {
// Not applicable.
continue;
}
// Let developers generate a media name based on the asset.
$media_name = $asset['public_id'];
\Drupal::moduleHandler()->alter('cloudinary_source_migrate_media_name', $media_name, $asset);
// Populate alt attribute for images only.
if ($target_resource_type === AssetType::IMAGE && !$default_values['alt']) {
$default_values['alt'] = $media_name;
}
$info = [
'public_id' => $asset['public_id'],
'resource_type' => $asset[AssetType::KEY],
'delivery_type' => $asset[DeliveryType::KEY],
];
// Non-video resources require a file creation.
if ($target_resource_type !== AssetType::VIDEO) {
$value = $asset_helper->generateStringValue($info);
$new_file = $file_helper->createFile($value);
$default_values['target_id'] = $new_file->id();
}
/** @var \Drupal\media\MediaInterface $target_media */
$target_media = $media_storage->create([
'bundle' => $target_media_id,
'created' => $source_media->getCreatedTime(),
'changed' => $source_media->getChangedTime(),
'uid' => $source_media->getOwnerId(),
'langcode' => $source_media->language()->getId(),
'name' => $media_name,
]);
$target_media->set($target_source_field, $info + $default_values);
$target_media->save();
$migrate_helper->setDestinationId($source_media, $target_media);
}
$sandbox['progress'] += count($ids);
$sandbox['#finished'] = $sandbox['progress'] / $sandbox['total'];
}
/**
* Migrate old references to new one for cloudinary media.
*/
function cloudinary_source_migrate_deploy_media_entites_reference(array &$sandbox) {
/** @var \Drupal\cloudinary_source_migrate\CloudinarySourceMigrateHelperInterface $migrate_helper */
$migrate_helper = \Drupal::service('cloudinary_source_migrate.helper');
$old_new_ids = $migrate_helper->getDestinationMap();
if (!$old_new_ids) {
return;
}
$old_ids = array_keys($old_new_ids);
if (!isset($sandbox['progress'])) {
$sandbox['progress'] = 0;
$fields_to_migrate = $migrate_helper->getEntityReferenceFieldsToMigrate();
$results = [];
$total = 0;
foreach ($fields_to_migrate as $entity_type_id => $info) {
/** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */
$entity_type = \Drupal::entityTypeManager()->getDefinition($entity_type_id);
foreach ($info as $bundle => $fields) {
if (!isset($results[$entity_type_id])) {
$results[$entity_type_id] = [
'fields' => [],
'ids' => [],
];
}
$results[$entity_type_id]['fields'][$bundle] = $fields;
$query = \Drupal::entityQuery($entity_type_id)
->accessCheck(FALSE)
->condition($entity_type->getKey('bundle'), $bundle);
$group_or = $query->orConditionGroup();
foreach ($fields as $field_name) {
$group_or->condition("{$field_name}.target_id", $old_ids, 'IN');
}
$query->condition($group_or);
$ids = $query->execute();
$total += count($ids);
$results[$entity_type_id]['ids'] = array_merge($results[$entity_type_id]['ids'], array_values($ids));
}
}
// Split into smaller chunks.
foreach ($results as $entity_type_id => $entity_ids) {
$results[$entity_type_id]['ids'] = array_chunk($entity_ids['ids'], 10);
}
if (!$total) {
return;
}
$sandbox['total'] = $total;
$sandbox['ids'] = $results;
}
if (!$sandbox['ids']) {
$sandbox['#finished'] = 1;
}
$entity_type_id = key($sandbox['ids']);
$item = &$sandbox['ids'][$entity_type_id];
$ids = array_pop($item['ids']) ?? [];
// Exit from the loop if no ids found. Clear the info from the sandbox
// to go to the next iteration.
if (!$ids) {
unset($sandbox['ids'][$entity_type_id]);
}
// Init cloudinary sdk manually for CLI.
cloudinary_sdk_init();
$fields = $item['fields'];
$storage = \Drupal::entityTypeManager()->getStorage($entity_type_id);
/** @var \Drupal\Core\Entity\TranslatableInterface[] $entities */
$entities = $storage->loadMultiple($ids);
foreach ($entities as $entity) {
foreach ($entity->getTranslationLanguages() as $langcode => $language) {
$translation = $entity->getTranslation($langcode);
$needs_update = FALSE;
foreach ($fields[$entity->bundle()] as $field_name) {
if (!$translation->hasField($field_name)) {
continue;
}
$values = $translation->get($field_name)->getValue();
foreach ($values as $delta => $value) {
// Simply replace old id by new one.
if (isset($old_new_ids[$value['target_id']])) {
$values[$delta]['target_id'] = $old_new_ids[$value['target_id']];
$needs_update = TRUE;
}
}
$translation->set($field_name, $values);
}
if ($needs_update) {
$translation->save();
}
}
}
$sandbox['progress'] += count($ids);
$sandbox['#finished'] = $sandbox['progress'] / $sandbox['total'];
}
