cloudinary-8.x-1.x-dev/modules/cloudinary_media_library_widget/cloudinary_media_library_widget.module

modules/cloudinary_media_library_widget/cloudinary_media_library_widget.module
<?php

/**
 * @file
 * Main module file.
 */

use Cloudinary\Api\Admin\AdminApi;
use Cloudinary\Configuration\Configuration;
use Drupal\cloudinary_media_library_widget\Service\CloudinaryMediaWidgetHelper;
use Drupal\cloudinary_media_library_widget\Plugin\Field\FieldType\CloudinaryImage;
use Drupal\cloudinary_sdk\Service\CloudinaryAssetHelper;
use Drupal\cloudinary_stream_wrapper\StreamWrapper\CloudinaryStreamWrapper;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Drupal\file\FileInterface;
use Drupal\media\MediaInterface;

/**
 * Implements hook_form_FORM_ID_alter() for cloudinary_sdk_settings().
 *
 * Alters the setting form for Cloudinary settings.
 *
 * @see cloudinary_sdk_settings()
 */
function cloudinary_media_library_widget_form_cloudinary_sdk_settings_alter(&$form, $form_state) {
  $config = \Drupal::config('cloudinary_media_library_widget.settings');
  $form['widget'] = [
    '#type' => 'fieldset',
    '#title' => t('Media library widget settings'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
  ];

  $form['widget']['cloudinary_saml_auth'] = [
    '#type' => 'checkbox',
    '#title' => t('SAML Authentication'),
    '#default_value' => $config->get('cloudinary_saml_auth'),
    '#description' => t('Whether to perform automatic SSO login via SAML for the specified username. This parameter is only needed if the "Enforce SAML login" option is disabled for your account.'),
  ];

  try {
    $api = new AdminApi();
    $root_folders = $api->rootFolders();
    $folders = [];
    foreach ($root_folders['folders'] as $folder) {
      $folders[$folder['path']] = t('Folder: /@path', [
        '@path' => $folder['path'],
      ]);
    }
  }
  catch (\Exception $e) {
    $folders = [];
  }

  $form['widget']['cloudinary_starting_folder'] = [
    '#type' => 'select',
    '#title' => t('Starting folder'),
    '#options' => $folders,
    '#empty_value' => '/',
    '#empty_option' => t('Root'),
    '#default_value' => $config->get('cloudinary_starting_folder'),
    '#description' => t('Instructs the widget to open in browse mode, displaying the contents of the specified folder.'),
  ];

  $form['metadata'] = [
    '#type' => 'fieldset',
    '#title' => t('Metadata attributes'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
  ];

  $title_options = [
    'context.custom.caption' => t('Contextual metadata: Title (caption)'),
  ];
  $description_options = [
    'context.custom.alt' => t('Contextual metadata: Description (alt)'),
  ];

  try {
    Configuration::instance()->validate();

    // Fetch list of custom metadata fields.
    $fields = CloudinaryAssetHelper::cloudinary()->adminApi()->listMetadataFields();
    foreach ($fields->offsetGet('metadata_fields') as $metadata) {
      if ($metadata['type'] === 'string') {
        $title_options[$metadata['external_id']] = $metadata['label'];
        $description_options[$metadata['external_id']] = $metadata['label'];
      }
    }
  }
  catch (\Exception $e) {
    $form['metadata']['#description'] = t('Please set up API connection and save the form to see list of all metadata including structure one.');
  }

  $form['metadata']['cloudinary_attribute_default_title'] = [
    '#title' => t('Default title (caption) attribute'),
    '#type' => 'select',
    '#description' => t('Use this attribute to automatically populate title attribute for an image and name for a media.'),
    '#options' => $title_options,
    '#default_value' => $config->get('cloudinary_attribute_default_title'),
  ];

  $form['metadata']['cloudinary_attribute_default_description'] = [
    '#title' => t('Default description (alt) attribute'),
    '#type' => 'select',
    '#description' => t('Use this attribute to automatically populate "alt text" for an image and "description" for a video/document.'),
    '#options' => $description_options,
    '#default_value' => $config->get('cloudinary_attribute_default_description'),
  ];

  $form['optimizations'] = [
    '#type' => 'fieldset',
    '#title' => t('Optimizations'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
  ];

  $image_optimizations = $config->get('cloudinary_image_optimizations') ?? [];
  $form['optimizations']['cloudinary_image_optimizations'] = [
    '#type' => 'textarea',
    '#title' => t('Default optimizations for image'),
    '#default_value' => $image_optimizations,
    '#description' => t('Represents a different component (separated by a "/"), for example: c_scale,w_400/f_auto/q_auto. Check official @docs to get more details.', [
      '@docs' => Link::fromTextAndUrl(
        t('docs'),
        Url::fromUri('https://cloudinary.com/documentation/image_transformations')->setOption('attributes', ['target' => '_blank'])
      )->toString(),
    ]),
    '#rows' => 2,
    '#weight' => 1,
  ];

  $breakpoints = $config->get('cloudinary_responsive_breakpoints') ?? [];
  $form['optimizations']['cloudinary_responsive_breakpoints'] = [
    '#type' => 'textarea',
    '#title' => t('Responsive breakpoints'),
    '#default_value' => CloudinaryMediaWidgetHelper::convertArrayOptionsToString($breakpoints),
    '#description' => t('Enter one value per line or separate it by comma. Check official @docs to get more details.', [
      '@docs' => Link::fromTextAndUrl(
        t('docs'),
        Url::fromUri('https://cloudinary.com/documentation/responsive_images#overriding_default_values')->setOption('attributes', ['target' => '_blank'])
      )->toString(),
    ]),
    '#weight' => 3,
  ];

  $form['#submit'][] = 'cloudinary_media_library_widget_settings_submit';
}

/**
 * Submit for the cloudinary_sdk_settings() form.
 */
function cloudinary_media_library_widget_settings_submit($form, FormStateInterface $form_state) {
  $widget_config = \Drupal::configFactory()
    ->getEditable('cloudinary_media_library_widget.settings');

  $settings = [
    'cloudinary_saml_auth',
    'cloudinary_starting_folder',
    'cloudinary_image_optimizations',
    'cloudinary_attribute_default_title',
    'cloudinary_attribute_default_description',
  ];

  // Set standard configuration.
  foreach ($settings as $option) {
    $widget_config->set($option, $form_state->getValue($option));
  }

  // Convert breakpoints to the proper format if it was seperated by comma.
  $breakpoints = explode(',', $form_state->getValue('cloudinary_responsive_breakpoints', ''));
  $breakpoints = array_map('trim', $breakpoints);
  $breakpoints_value = CloudinaryMediaWidgetHelper::convertArrayOptionsToString($breakpoints);

  $widget_config->set('cloudinary_responsive_breakpoints', CloudinaryMediaWidgetHelper::convertStringOptionsToArray($breakpoints_value));
  $widget_config->save();
}

/**
 * Implements hook_theme().
 */
function cloudinary_media_library_widget_theme() {
  return [
    'cloudinary_image_formatter' => [
      'variables' => [
        'item' => NULL,
        'item_attributes' => NULL,
        'url' => NULL,
      ],
    ],
  ];
}

/**
 * Implements hook_preprocess_HOOK() for image_formatter.
 *
 * Apply custom transformation for default image formatter.
 */
function cloudinary_media_library_widget_preprocess_image_formatter(&$variables) {
  $item = $variables['item'];

  if ($item instanceof CloudinaryImage) {
    /** @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');

    $info = $item->getValue();
    $value = $asset_helper->generateStringValue($info);
    $variables['image']['#uri'] = $file_helper->generateUriForFileWithTransformation($value);
  }
}

/**
 * Implements hook_preprocess_HOOK() for responsive_image_formatter.
 *
 * Apply custom transformation for responsive image formatter.
 */
function cloudinary_media_library_widget_preprocess_responsive_image_formatter(&$variables) {
  $item = $variables['item'];

  if ($item instanceof CloudinaryImage) {
    /** @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');

    $info = $item->getValue();
    $value = $asset_helper->generateStringValue($info);
    $variables['responsive_image']['#uri'] = $file_helper->generateUriForFileWithTransformation($value);
  }
}

/**
 * Implements hook_preprocess_HOOK() for drimage_formatter.
 *
 * Apply custom transformation for drimage formatter and improve performance.
 */
function cloudinary_media_library_widget_preprocess_drimage_formatter(&$variables) {
  $item = $variables['item'];

  // Properly handle aspect ratio behaviour, so it well integrated with
  // cloudinary behaviour.
  if ($item->entity instanceof FileInterface) {
    $uri = $item->entity->getFileUri();

    [$scheme] = explode('://', $uri, 2);

    if ($scheme !== 'cloudinary') {
      return;
    }

    $info = CloudinaryStreamWrapper::parseUri($uri);

    // Fix ration and add a placeholder to be replaced in htaccess by drimage
    // width and height. See README.md for more details about htaccess changes.
    $ratio = $variables['width'] / $variables['height'];
    $info['transformation'] = implode('/', array_filter([
      $info['transformation'],
      "ar_{$ratio},c_crop",
      "%replaceme%",
    ]));

    /** @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');

    $value = $asset_helper->generateStringValue($info);
    $uri = $file_helper->generateUriForExternalUrl($value);
    $variables['data']['original_source'] = \Drupal::service('file_url_generator')->generateAbsoluteString($uri);
  }
}

/**
 * Implements hook_field_formatter_info_alter().
 */
function cloudinary_media_library_widget_field_formatter_info_alter(array &$info) {
  // Support contrib/core image formatters for custom cloudinary field type.
  $field_formatters = [
    'cloudinary_image' => [
      'image',
      'responsive_image',
      'drimage',
    ],
    'cloudinary_raw' => [
      'file_default',
      'file_url_plain',
      'file_table',
    ],
  ];

  foreach ($field_formatters as $field_type => $formatters) {
    foreach ($formatters as $field_formatter) {
      if (isset($info[$field_formatter])) {
        $info[$field_formatter]['field_types'][] = $field_type;
      }
    }
  }
}

/**
 * Implements hook_ENTITY_TYPE_update() for media.
 *
 * Force updating media thumbnail when uri changes.
 */
function cloudinary_media_library_widget_media_update(MediaInterface $entity) {
  if ($entity->getSource()->getPluginId() === 'cloudinary' && isset($entity->original)) {
    $new_uri = $entity->getSource()->getMetadata($entity, 'thumbnail_uri');
    $old_uri = $entity->getSource()->getMetadata($entity->original, 'thumbnail_uri');

    if ($new_uri === $old_uri) {
      return;
    }

    $values = [
      'uri' => $new_uri,
    ];

    $file_storage = \Drupal::entityTypeManager()->getStorage('file');
    if ($existing = $file_storage->loadByProperties($values)) {
      $file = reset($existing);
    }
    else {
      /** @var \Drupal\file\FileInterface $file */
      $file = $file_storage->create($values);
      if ($owner = $entity->getOwner()) {
        $file->setOwner($owner);
      }
      $file->setPermanent();
      $file->save();
    }

    $entity->thumbnail->target_id = $file->id();
  }
}

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

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