cloudinary-8.x-1.x-dev/modules/cloudinary_source_migrate/src/CloudinarySourceMigrateHelper.php
modules/cloudinary_source_migrate/src/CloudinarySourceMigrateHelper.php
<?php
namespace Drupal\cloudinary_source_migrate;
use Cloudinary\Api\Admin\AdminApi;
use Cloudinary\Asset\AssetType;
use Cloudinary\Asset\DeliveryType;
use Drupal\cloudinary_media_library_widget\CloudinaryInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\State\State;
use Drupal\file\Plugin\Field\FieldType\FileItem;
use Drupal\media\MediaInterface;
use Drupal\media\MediaTypeInterface;
use Drupal\video_embed_field\Plugin\Field\FieldType\VideoEmbedField;
/**
* Build a service to help migrating cloudinary source.
*/
class CloudinarySourceMigrateHelper implements CloudinarySourceMigrateHelperInterface {
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected EntityTypeManagerInterface $entityTypeManager;
/**
* The state storage.
*
* @var \Drupal\Core\State\State
*/
protected State $state;
/**
* The entity field manager.
*
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
*/
protected EntityFieldManagerInterface $entityFieldManager;
/**
* Construct of CloudinarySourceMigrateHelper.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\State\State $state
* The state storage.
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
* The entity field manager.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, State $state, EntityFieldManagerInterface $entity_field_manager) {
$this->entityTypeManager = $entity_type_manager;
$this->state = $state;
$this->entityFieldManager = $entity_field_manager;
}
/**
* {@inheritdoc}
*/
public function getMediaBundleMap(): array {
$resource_old_bundle_map = [
AssetType::IMAGE => 'cloudinary_image',
AssetType::VIDEO => 'cloudinary_video',
AssetType::RAW => 'file',
];
$media_type_storage = $this->entityTypeManager->getStorage('media_type');
/** @var \Drupal\media\MediaTypeInterface[] $media_types */
$media_types = $media_type_storage->loadMultiple();
$cloudinary_types = array_filter($media_types, function (MediaTypeInterface $media_type) {
return $media_type->getSource() instanceof CloudinaryInterface;
});
$bundle_map = [];
foreach ($cloudinary_types as $media_type) {
$configuration = $media_type->getSource()->getConfiguration();
$resource_type = $configuration['resource_type'];
if (!isset($resource_old_bundle_map[$resource_type])) {
continue;
}
$bundle_map[$resource_old_bundle_map[$resource_type]] = $media_type->id();
}
return $bundle_map;
}
/**
* {@inheritdoc}
*/
public function getDestinationMap(): array {
return $this->state->get(self::DESTINATION_MAP_KEY, []);
}
/**
* {@inheritdoc}
*/
public function setDestinationId(MediaInterface $old_media, MediaInterface $new_media): void {
$state = $this->getDestinationMap();
$state[$old_media->id()] = $new_media->id();
$this->state->set(self::DESTINATION_MAP_KEY, $state);
}
/**
* {@inheritdoc}
*/
public function clearDestinationMap(): void {
$this->state->delete(self::DESTINATION_MAP_KEY);
}
/**
* {@inheritdoc}
*/
public function isMigrated(MediaInterface $media): bool {
return isset($this->getDestinationMap()[$media->id()]);
}
/**
* {@inheritdoc}
*/
public function getPublicIdFromFieldItem($item): string {
if ($item instanceof VideoEmbedField) {
$uri = $item->value;
}
elseif ($item instanceof FileItem) {
/** @var \Drupal\file\FileInterface $file */
$file = $item->entity;
$uri = $file->getFileUri();
}
if (!isset($uri)) {
throw new \Exception('Not applicable');
}
[$scheme, $target] = explode('://', $uri);
// Make sure we work with cloudinary file scheme only.
if ($scheme !== 'cloudinary') {
throw new \Exception('Not applicable');
}
$parts = explode('.', $target);
// Exclude format from the target.
if (count($parts) > 1) {
array_pop($parts);
}
return implode('.', $parts);
}
/**
* {@inheritdoc}
*/
public function getAssetFromFieldItem($item, string $resource_type): array {
$public_id = $this->getPublicIdFromFieldItem($item);
$api = new AdminApi();
$resource_types = [];
// Common documents like PDF use image type. So let's try to load a resource
// with image type first.
if ($resource_type === AssetType::RAW) {
$resource_types[] = AssetType::IMAGE;
}
$resource_types[] = $resource_type;
foreach ($resource_types as $type) {
try {
return (array) $api->asset($public_id, [
AssetType::KEY => $type,
DeliveryType::KEY => DeliveryType::UPLOAD,
]);
}
catch (\Exception $e) {
// We try again but with fallback type.
}
}
// Asset not found.
throw new \Exception('Not applicable');
}
/**
* {@inheritdoc}
*/
public function getEntityReferenceFieldsToMigrate(): array {
$media_type_storage = $this->entityTypeManager->getStorage('media_type');
/** @var \Drupal\media\MediaTypeInterface[] $media_types */
$media_types = $media_type_storage->loadMultiple();
$map = $this->entityFieldManager->getFieldMapByFieldType('entity_reference');
$fields_to_migrate = [];
foreach ($map as $entity_type => $fields) {
foreach ($fields as $field_name => $info) {
foreach ($info['bundles'] as $bundle) {
$field_definitions = $this->entityFieldManager->getFieldDefinitions($entity_type, $bundle);
$target_type = $field_definitions[$field_name]->getSetting('target_type');
if ($target_type !== 'media') {
continue;
}
$settings = $field_definitions[$field_name]->getSetting('handler_settings');
$types_to_migrate = array_filter($settings['target_bundles'], function ($media_type_id) use ($media_types) {
return $media_types[$media_type_id]->getSource() instanceof CloudinaryInterface;
});
if ($types_to_migrate) {
$fields_to_migrate[$entity_type][$bundle][] = $field_name;
}
}
}
}
return $fields_to_migrate;
}
}
