cloudinary-8.x-1.x-dev/modules/cloudinary_media_library_widget/src/Plugin/media/Source/Cloudinary.php

modules/cloudinary_media_library_widget/src/Plugin/media/Source/Cloudinary.php
<?php

namespace Drupal\cloudinary_media_library_widget\Plugin\media\source;

use Cloudinary\Asset\AssetType;
use Cloudinary\Cloudinary as CloudinarySdk;
use Cloudinary\Configuration\Configuration;
use Consolidation\OutputFormatters\Exception\UnknownFieldException;
use Drupal\cloudinary_media_library_widget\CloudinaryInterface;
use Drupal\cloudinary_sdk\Service\CloudinaryAssetHelper;
use Drupal\Core\Form\FormStateInterface;
use Drupal\media\MediaInterface;
use Drupal\media\MediaSourceBase;
use Drupal\media\Plugin\media\Source\File;
use Drupal\media\Plugin\media\Source\Image;

/**
 * Provides media source plugin for cloudinary assets.
 *
 * @MediaSource(
 *   id = "cloudinary",
 *   label = @Translation("Cloudinary"),
 *   description = @Translation("Use Cloudinary assets for reusable media."),
 *   allowed_field_types = {
 *     "cloudinary_image",
 *     "cloudinary_video",
 *     "cloudinary_raw",
 *   },
 *   default_thumbnail_filename = "generic.png",
 *   forms = {
 *     "media_library_add" = "\Drupal\cloudinary_media_library_widget\Form\CloudinaryUploadForm",
 *   },
 * )
 */
class Cloudinary extends MediaSourceBase implements CloudinaryInterface {

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'resource_type' => AssetType::IMAGE,
    ] + parent::defaultConfiguration();
  }

  /**
   * {@inheritdoc}
   */
  public function getMetadataAttributes() {
    $attributes = [
      'public_id' => $this->t('Asset public ID'),
      'transformation' => $this->t('Asset transformation'),
      'context' => $this->t('Asset metadata'),
      'secure_url' => $this->t('Asset secure url'),
      'resource_type' => $this->t('Asset type'),
      'delivery_type' => $this->t('Asset delivery type'),
      'duration' => $this->t('Video duration'),
      File::METADATA_ATTRIBUTE_NAME => $this->t('Name'),
      File::METADATA_ATTRIBUTE_MIME => $this->t('MIME type'),
      File::METADATA_ATTRIBUTE_SIZE => $this->t('File size'),
      Image::METADATA_ATTRIBUTE_WIDTH => $this->t('Width'),
      Image::METADATA_ATTRIBUTE_HEIGHT => $this->t('Height'),
    ];

    // Fetch list of custom metadata fields.
    $fields = CloudinaryAssetHelper::cloudinary()->adminApi()->listMetadataFields();

    foreach ($fields->offsetGet('metadata_fields') as $metadata) {
      $attributes["external_metadata_{$metadata['external_id']}"] = $metadata['label'];
    }

    return $attributes;
  }

  /**
   * Get instance of cloudinary API.
   *
   * @return \Cloudinary\Cloudinary
   *   The cloudinary API.
   */
  public static function cloudinary() {
    return new CloudinarySdk(Configuration::instance());
  }

  /**
   * {@inheritdoc}
   */
  public function getMetadata(MediaInterface $media, $attribute_name) {
    $item = $media->get($this->configuration['source_field']);

    /** @var \Drupal\file\FileInterface $file */
    $file = $item->entity ?? NULL;

    /** @var \Drupal\cloudinary_media_library_widget\Service\CloudinaryFileHelperInterface $file_helper */
    $file_helper = \Drupal::service('cloudinary_media_library_widget.file_helper');

    /** @var \Drupal\cloudinary_sdk\Service\AssetHelperInterface $asset_helper */
    $asset_helper = \Drupal::service('cloudinary_sdk.asset_helper');

    // @todo Add support for multiple items for common attributes.
    switch ($attribute_name) {
      case 'thumbnail_uri':
        $info = $item->first()->getValue();

        // For raw files we display a default icon.
        if ($info['resource_type'] === AssetType::RAW) {
          return parent::getMetadata($media, $attribute_name);
        }

        $value = $asset_helper->generateStringValue($info);

        return $file_helper->generateUriForFileWithTransformation($value);

      case 'thumbnail_alt_value':
        if (isset($item->alt)) {
          return $item->alt;
        }

        if (isset($item->description)) {
          return $item->description;
        }

        // Use name as fallback alt text.
        return $this->getMetadata($media, 'default_name');

      case 'default_name':
        if (isset($item->title)) {
          return $item->title;
        }

        if (isset($item->description)) {
          return $item->description;
        }

        return parent::getMetadata($media, 'default_name');

      case 'public_id':
        return $item->public_id;

      case 'transformation':
        return $item->transformation;

      case 'resource_type':
        return $item->resource_type;

      case 'delivery_type':
        return $item->delivery_type;

      case File::METADATA_ATTRIBUTE_NAME:
        if ($file) {
          return $file->getFilename();
        }

        if (isset($item->description)) {
          return $item->description;
        }

        return parent::getMetadata($media, File::METADATA_ATTRIBUTE_NAME);

      case File::METADATA_ATTRIBUTE_MIME:
        if ($file) {
          return $file->getMimeType();
        }

        /** @var \Symfony\Component\Mime\MimeTypeGuesserInterface $guesser */
        $guesser = \Drupal::service('file.mime_type.guesser');

        $asset = $asset_helper->loadAssetByPublicId($item->public_id, $item->resource_type);
        $target = implode('.', [$asset->getPublicId(), $asset->getFormat()]);

        return $guesser->guessMimeType($target);

      case File::METADATA_ATTRIBUTE_SIZE:
        $asset = $asset_helper->loadAssetByPublicId($item->public_id, $item->resource_type);

        return $asset->getBytes();

      case Image::METADATA_ATTRIBUTE_WIDTH:
        return $item->width;

      case Image::METADATA_ATTRIBUTE_HEIGHT:
        return $item->height;

      case 'secure_url':
        $value = $asset_helper->generateStringValue($item->first()->getValue());
        $uri = $file_helper->generateUriForExternalUrl($value);

        return \Drupal::service('file_url_generator')->generateAbsoluteString($uri);

      case 'context':
        $asset = $asset_helper->loadAssetByPublicId($item->public_id, $item->resource_type);

        return $asset->getCustomContext();

      case 'duration':
        $asset = $asset_helper->loadAssetByPublicId($item->public_id, $item->resource_type);

        return $asset->getDuration();
    }

    // Get metadata from the asset if metadata structured fields are used.
    if (preg_match('/^external_metadata_(.+)$/', $attribute_name, $matches)) {
      $asset = $asset_helper->loadAssetByPublicId($item->public_id, $item->resource_type);
      $metadata_values = $asset->getMetadata();

      return $metadata_values[$matches[1]] ?? '';
    }

    return parent::getMetadata($media, $attribute_name);
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $form = parent::buildConfigurationForm($form, $form_state);
    $is_source_visible = $form['source_field']['#access'] ?? TRUE;
    $options = $form['source_field']['#options'];

    if ($is_source_visible) {
      // Group fields by field type.
      foreach ($options as $field_name => $label) {
        $field_resource_type = $this->getResourceTypeByFieldName($field_name);
        unset($options[$field_name]);
        $options[ucfirst($field_resource_type)][$field_name] = $label;
      }

      $form['source_field']['#options'] = $options;
    }
    elseif (!$options) {
      // Display custom message to explain automatic field creation.
      $form['source_field_message'] = [
        '#markup' => $this->t('Cloudinary field will be automatically created based on resource type to store the essential information about the media item.'),
      ];
    }

    $form['resource_type'] = [
      '#type' => 'select',
      '#title' => $this->t('Resource type'),
      '#default_value' => $this->configuration['resource_type'],
      '#description' => $this->t('The type of the asset to work with.'),
      '#disabled' => !empty($this->configuration['source_field']),
      '#options' => [
        AssetType::IMAGE => $this->t('Image'),
        AssetType::VIDEO => $this->t('Video'),
        AssetType::RAW => $this->t('Document'),
      ],
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
    $source_field = $form_state->getValue('source_field');

    // Check if existing field matches the resource type from the form.
    if ($source_field) {
      $field_resource_type = $this->getResourceTypeByFieldName($source_field);

      if ($form_state->getValue('resource_type') !== $field_resource_type) {
        $form_state->setErrorByName('resource_type', $this->t('The selected resource type does not match existing source field.'));
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  protected function createSourceFieldStorage() {
    $resource_type = $this->configuration['resource_type'];
    $field_type = "cloudinary_{$resource_type}";

    return $this->entityTypeManager
      ->getStorage('field_storage_config')
      ->create([
        'entity_type' => 'media',
        'field_name' => $this->getSourceFieldName(),
        'type' => $field_type,
      ]);
  }

  /**
   * {@inheritdoc}
   */
  protected function getSourceFieldName() {
    $resource_type = $this->configuration['resource_type'];
    $base_id = "field_media_cloudinary_{$resource_type}";
    $tries = 0;
    $storage = $this->entityTypeManager->getStorage('field_storage_config');

    // Iterate at least once, until no field with the generated ID is found.
    do {
      $id = $base_id;
      // If we've tried before, increment and append the suffix.
      if ($tries) {
        $id .= '_' . $tries;
      }
      $field = $storage->load('media.' . $id);
      $tries++;
    } while ($field);

    return $id;
  }

  /**
   * Get the resource type based on field name of the media source.
   *
   * @param string $field_name
   *   The name of the field to check.
   *
   * @return string
   *   The resource name that matches the field.
   */
  protected function getResourceTypeByFieldName($field_name) {
    $storage = $this->entityTypeManager->getStorage('field_storage_config');
    /** @var \Drupal\field\FieldStorageConfigInterface $field */
    $field = $storage->load("media.{$field_name}");

    if (!$field) {
      throw new UnknownFieldException($field_name);
    }

    $bundles = $field->getBundles();

    /** @var \Drupal\media\MediaTypeInterface $media_type */
    $media_type = $this->entityTypeManager->getStorage('media_type')
      ->load(reset($bundles));

    $configuration = $media_type->getSource()->getConfiguration();

    return $configuration['resource_type'];
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc