cloudinary-8.x-1.x-dev/modules/cloudinary_sdk/src/Service/CloudinaryAssetHelper.php
modules/cloudinary_sdk/src/Service/CloudinaryAssetHelper.php
<?php
namespace Drupal\cloudinary_sdk\Service;
use Cloudinary\Api\ApiResponse;
use Cloudinary\Asset\AssetType;
use Cloudinary\Asset\Image;
use Cloudinary\Asset\Video;
use Cloudinary\Cloudinary;
use Cloudinary\Configuration\Configuration;
use Cloudinary\Tag\BaseTag;
use Cloudinary\Transformation\Resize;
use Drupal\cloudinary_media_library_widget\Model\Asset;
use Symfony\Component\Serializer\Serializer;
/**
* Define a service to work with custom value from cloudinary form element.
*/
class CloudinaryAssetHelper implements AssetHelperInterface {
/**
* The serializer service.
*
* @var \Symfony\Component\Serializer\Serializer
*/
protected Serializer $serializer;
/**
* Constructs a service object.
*
* @param \Symfony\Component\Serializer\Serializer $serializer
* The serializer service.
*/
public function __construct(Serializer $serializer) {
$this->serializer = $serializer;
}
/**
* Get instance of cloudinary API.
*
* @return \Cloudinary\Cloudinary
* The cloudinary API.
*/
public static function cloudinary() {
return new Cloudinary(Configuration::instance());
}
/**
* {@inheritdoc}
*/
public function generatePreviewImageUrl(string $value, int $width = 400): ?string {
$asset = $this->getBaseMediaAsset($value);
// No preview available if base media asset is not found.
if (!$asset) {
return NULL;
}
$info = $this->parseValue($value);
// Force small size of the thumbnail to increase performance.
$asset->resize(Resize::fill()->width($width));
// Apply only custom transformation for the preview image.
// Applying default transformation does not make sense.
if ($info['transformation']) {
$asset->addTransformation($info['transformation']);
}
// Force extension to support PDF thumbnails.
$asset->extension('jpeg');
return (string) $asset->toUrl();
}
/**
* {@inheritdoc}
*/
public function renderAsset(string $value): ?array {
try {
$info = $this->parseValue($value);
}
catch (\Exception $e) {
// Nothing to render here.
return NULL;
}
switch ($info['resource_type']) {
case AssetType::IMAGE:
return $this->renderImage($info);
case AssetType::VIDEO:
return $this->renderVideo($info);
}
// Nothing to render.
return NULL;
}
/**
* Render image asset in Drupal way.
*
* @param array $info
* The parsed value from the form element.
*
* @return array
* Renderable array with image element build.
*/
protected function renderImage(array $info): array {
return [
'#type' => 'cloudinary_image',
'#public_id' => $info['public_id'],
'#delivery_type' => $info['delivery_type'],
'#raw_transformation' => $info['transformation'] ?? '',
];
}
/**
* Render video asset in Drupal way.
*
* @param array $info
* The parsed value from the form element.
*
* @return array
* Renderable array with video element build.
*/
protected function renderVideo(array $info): array {
return [
'#type' => 'cloudinary_video',
'#public_id' => $info['public_id'],
'#delivery_type' => $info['delivery_type'],
'#raw_transformation' => $info['transformation'] ?? '',
];
}
/**
* {@inheritdoc}
*/
public function isApplicable(string $value): bool {
return preg_match('/^cloudinary:(image|video|raw):(upload|private|authenticated):([^:]*)(:(.+))?$/', $value) > 0;
}
/**
* {@inheritdoc}
*/
public function parseValue(string $value): array {
if (!$this->isApplicable($value)) {
throw new \Exception('Could not parse the value.');
}
preg_match('/^cloudinary:(image|video|raw):(upload|private|authenticated):([^:]*)(:(.+))?$/', $value, $matches);
[, $resource_type, $delivery_type, $public_id,, $transformation] = array_pad($matches, 6, NULL);
return [
'type' => 'cloudinary',
'resource_type' => $resource_type,
'delivery_type' => $delivery_type,
'public_id' => $public_id,
'transformation' => $transformation ?? '',
];
}
/**
* {@inheritdoc}
*/
public function getBaseTag(string $value): ?BaseTag {
try {
$info = $this->parseValue($value);
}
catch (\Exception $e) {
// Nothing to render here.
return NULL;
}
switch ($info['resource_type']) {
case AssetType::IMAGE:
return static::cloudinary()->imageTag($info['public_id']);
case AssetType::VIDEO:
return static::cloudinary()->videoTag($info['public_id']);
}
// Nothing to render.
return NULL;
}
/**
* {@inheritdoc}
*/
public function generateStringValue(array $value): string {
if (!isset($value['resource_type']) || !isset($value['delivery_type']) || !isset($value['public_id'])) {
throw new \Exception('Some fields are missing from the field value.');
}
return implode(':', array_filter([
'cloudinary',
$value['resource_type'],
$value['delivery_type'],
$value['public_id'],
$value['transformation'] ?? NULL,
]));
}
/**
* {@inheritdoc}
*/
public function loadAssetByPublicId(string $public_id, string $resource_type = AssetType::IMAGE): Asset {
$asset_data = static::cloudinary()->adminApi()->asset($public_id, [
AssetType::KEY => $resource_type,
]);
assert($asset_data instanceof ApiResponse);
$asset = $this->serializer->denormalize($asset_data, Asset::class);
assert($asset instanceof Asset);
return $asset;
}
/**
* {@inheritdoc}
*/
public function getBaseMediaAsset(string $value): Video|Image|NULL {
$info = $this->parseValue($value);
$asset = NULL;
switch ($info['resource_type']) {
case AssetType::IMAGE:
$asset = static::cloudinary()->image($info['public_id']);
break;
case AssetType::VIDEO:
$asset = static::cloudinary()->video($info['public_id']);
break;
}
if (!$asset) {
return NULL;
}
$asset->deliveryType($info['delivery_type']);
return $asset;
}
}
