cloudinary-8.x-1.x-dev/modules/cloudinary_media_library_widget/src/Service/CloudinaryFileHelper.php
modules/cloudinary_media_library_widget/src/Service/CloudinaryFileHelper.php
<?php
namespace Drupal\cloudinary_media_library_widget\Service;
use Cloudinary\Asset\AssetType;
use Drupal\cloudinary_media_library_widget\Plugin\Field\FieldType\CloudinaryImage;
use Drupal\cloudinary_media_library_widget\Plugin\media\source\Cloudinary;
use Drupal\cloudinary_sdk\Service\AssetHelperInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\file\FileInterface;
use Drupal\media\MediaInterface;
/**
* Build a service to solve common cloudinary file issues.
*/
class CloudinaryFileHelper implements CloudinaryFileHelperInterface {
/**
* The asset generator.
*
* @var \Drupal\cloudinary_sdk\Service\AssetHelperInterface
*/
protected AssetHelperInterface $assetHelper;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected EntityTypeManagerInterface $entityTypeManager;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected AccountInterface $currentUser;
/**
* Constructs a service object.
*
* @param \Drupal\cloudinary_sdk\Service\AssetHelperInterface $generator
* The asset generator.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
*/
public function __construct(AssetHelperInterface $generator, EntityTypeManagerInterface $entity_type_manager, AccountInterface $current_user) {
$this->assetHelper = $generator;
$this->entityTypeManager = $entity_type_manager;
$this->currentUser = $current_user;
}
/**
* {@inheritdoc}
*/
public static function getPublicIdFromFileUri(string $uri): string {
[, $target] = explode('://', $uri, 2);
// Support new format of the cloudinary uri.
if (preg_match('/^(image|video|raw):(upload|private|authenticated):([^:]*)(:(.+))?$/', $target, $matches)) {
$public_id = $matches[3];
}
else {
// Support old format of the cloudinary uri.
$parts = explode('.', $target);
if ($parts > 1) {
array_pop($parts);
}
$public_id = implode('.', $parts);
}
return $public_id;
}
/**
* {@inheritdoc}
*/
public static function getRawTransformationByMedia(MediaInterface $media): ?string {
$source_field = $media->getSource()->getConfiguration()['source_field'];
$item = $media->get($source_field)->first();
// Support new custom field which stores the value in a separate property.
if ($item instanceof CloudinaryImage) {
return $item->transformation;
}
// Check if media entity has a dedicated field to store raw transformation.
if ($media->hasField('field_cloudinary_transformation')) {
return $media->get('field_cloudinary_transformation')->value;
}
return NULL;
}
/**
* {@inheritdoc}
*/
public function generateUriForFile(string $value, bool $allow_overrides = TRUE): string {
$info = $this->assetHelper->parseValue($value);
$asset = $this->assetHelper->loadAssetByPublicId($info['public_id'], $info['resource_type']);
// Use format if it's available, otherwise it will be a part of the id.
$source = $info['public_id'];
if ($format = $asset->getFormat()) {
// Force jpeg format for PDF and video to generate a preview image.
if ($allow_overrides && ($format === 'pdf' || $info['resource_type'] === AssetType::VIDEO)) {
$format = 'jpeg';
}
$source = implode('.', [$info['public_id'], $format]);
}
$target = implode(':', [
$info['resource_type'],
$info['delivery_type'],
$source,
]);
return "cloudinary://{$target}";
}
/**
* {@inheritdoc}
*/
public function generateUriForFileWithTransformation(string $value): string {
$info = $this->assetHelper->parseValue($value);
// If no custom transformation then we generate default file uri.
if (!$info['transformation']) {
return $this->generateUriForFile($value);
}
$asset = $this->assetHelper->loadAssetByPublicId($info['public_id'], $info['resource_type']);
// Use format if it's available, otherwise it will be a part of the id.
$source = $info['public_id'];
if ($format = $asset->getFormat()) {
// Force jpeg format for PDF and video to generate a preview image.
if ($info['resource_type'] === AssetType::VIDEO || $format === 'pdf') {
$format = 'jpeg';
}
$source = implode('.', [$info['public_id'], $format]);
}
return "cloudinary://{$info['transformation']}/v1/{$source}";
}
/**
* {@inheritdoc}
*/
public function generateUriForExternalUrl(string $value): string {
$info = $this->assetHelper->parseValue($value);
$target = implode(':', array_filter([
$info['resource_type'],
$info['delivery_type'],
$info['public_id'],
$info['transformation'],
]));
return "cloudinary://{$target}";
}
/**
* {@inheritdoc}
*/
public function createFile(string $value): FileInterface {
$uri = $this->generateUriForFile($value, FALSE);
$storage = $this->entityTypeManager->getStorage('file');
// Check if there is already file with this file uri.
$files = $storage->loadByProperties([
'uri' => $uri,
]);
$file = reset($files);
if ($file instanceof FileInterface) {
return $file;
}
$file_name = explode(':', $uri);
$file_name = array_pop($file_name);
/** @var \Drupal\file\FileInterface $file */
$file = $storage->create([
'uri' => $uri,
'filename' => basename($file_name),
'uid' => $this->currentUser->id(),
]);
// Save temp file before we validation. The file will get usage and
// permanent status once the field value will be stored in the database.
$file->setTemporary();
$file->save();
return $file;
}
}
