easy_360-1.x-dev/src/Plugin/Field/FieldFormatter/Viewer.php

src/Plugin/Field/FieldFormatter/Viewer.php
<?php

namespace Drupal\easy_360\Plugin\Field\FieldFormatter;

use Drupal\image\Plugin\Field\FieldFormatter\ImageFormatterBase;

use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\Url;

use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Renders an image field as an Easy 360 Viewer.
 *
 * @FieldFormatter(
 *   id = "easy_360_viewer",
 *   label = @Translation("Easy 360 viewer"),
 *   field_types = {
 *     "image"
 *   },
 *   quickedit = {
 *     "editor" = "image"
 *   }
 * )
 */
class Viewer extends ImageFormatterBase implements
  ContainerFactoryPluginInterface {

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;

  /**
   * The image style entity storage.
   *
   * @var \Drupal\image\ImageStyleStorageInterface
   */
  protected $imageStyleStorage;

  /**
   * Constructs a Viewer object.
   *
   * @param string $plugin_id
   *   The plugin_id for the formatter.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
   *   The definition of the field to which the formatter is associated.
   * @param array $settings
   *   The formatter settings.
   * @param string $label
   *   The formatter label display setting.
   * @param string $view_mode
   *   The view mode.
   * @param array $third_party_settings
   *   Any third party settings settings.
   * @param \Drupal\Core\Session\AccountInterface $current_user
   *   The current user.
   * @param \Drupal\Core\Entity\EntityStorageInterface $image_style_storage
   *   The image style storage.
   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
   *   The string translation service.
   */
  public function __construct(
    $plugin_id,
    $plugin_definition,
    FieldDefinitionInterface $field_definition,
    array $settings,
    $label,
    $view_mode,
    array $third_party_settings,
    AccountInterface $current_user,
    EntityStorageInterface $image_style_storage,
    TranslationInterface $string_translation
  ) {
    parent::__construct(
      $plugin_id,
      $plugin_definition,
      $field_definition,
      $settings,
      $label,
      $view_mode,
      $third_party_settings
    );

    $this->currentUser = $current_user;
    $this->imageStyleStorage = $image_style_storage;
    $this->stringTranslation = $string_translation;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(
    ContainerInterface $container,
    array $configuration,
    $plugin_id,
    $plugin_definition
  ) {
    return new static(
      $plugin_id,
      $plugin_definition,
      $configuration['field_definition'],
      $configuration['settings'],
      $configuration['label'],
      $configuration['view_mode'],
      $configuration['third_party_settings'],
      $container->get('current_user'),
      $container->get('entity_type.manager')->getStorage('image_style'),
      $container->get('string_translation')
    );
  }

  /**
   * {@inheritdoc}
   *
   * @I Move image style settings to profiles
   *    type     : improvement
   *    priority : high
   *    labels   : config
   */
  public static function defaultSettings() {
    return [
      'large_image_style' => '',
      'small_image_style' => '',
    ] + parent::defaultSettings();
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state) {
    $image_styles = image_style_options(FALSE);
    $description_texts = [
      'large' => $this->t('It will be used when zooming into the image.'),
      'small' => $this->t('It will be used in the viewer.'),
    ];

    // An additional link to the image style configuration page, if the user has
    // the relevant permission.
    $description_link = Link::fromTextAndUrl(
      $this->t('Configure image styles'),
      Url::fromRoute('entity.image_style.collection')
    );
    $description_link = $description_link->toRenderable() + [
      '#access' => $this->currentUser->hasPermission('administer image styles'),
    ];

    // Configure the image styles for the large and small images.
    $element = [];
    foreach (['large', 'small'] as $size) {
      $element[$size . '_image_style'] = $this->buildImageStyleSettingForm(
        $size,
        $image_styles,
        $description_texts[$size],
        $description_link
      );
    }

    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function settingsSummary() {
    $summary = [];

    // Styles could be lost because of enabled/disabled modules that define
    // their styles in code.
    foreach (['large', 'small'] as $size) {
      $summary[] = $this->imageStyleSettingSummary($size);
    }

    return $summary;
  }

  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $elements = [];
    $files = $this->getEntitiesToView($items, $langcode);

    // Early opt-out if the field is empty.
    if (empty($files)) {
      return $elements;
    }

    $item_urls = [];
    $cache_tags = [];
    foreach (['large', 'small'] as $size) {
      [$style, $style_cache_tags] = $this->getStyleAndCacheTags($size);
      $cache_tags = Cache::mergeTags($cache_tags, $style_cache_tags);

      foreach ($files as $delta => $file) {
        if (!$style) {
          $item_urls[$delta][$size . '_image'] = $file->createFileUrl();
        }
        else {
          $item_urls[$delta][$size . '_image'] = file_url_transform_relative(
            $style->buildUrl($file->getFileUri())
          );
        }
      }
    }

    $elements = [
      '#theme' => 'easy_360_viewer',
      '#items' => $item_urls,
      '#attached' => ['library' => ['easy_360/viewer']],
      '#cache' => [
        'tags' => $cache_tags,
      ],
    ];

    return $elements;
  }

  /**
   * {@inheritdoc}
   */
  public function calculateDependencies() {
    // If this formatter uses valid image styles to display the small and large
    // images of the 360 viewer, add the image styles configuration entity as
    // dependencies.
    $dependencies = parent::calculateDependencies();
    $style_ids = [
      $this->getSetting('large_image_style'),
      $this->getSetting('small_image_style'),
    ];
    foreach ($style_ids as $style_id) {
      if (!$style_id) {
        continue;
      }

      $style = $this->imageStyleStorage->load($style_id);
      if (!$style) {
        continue;
      }

      $key = $style->getConfigDependencyKey();
      $dependencies[$key][] = $style->getConfigDependencyName();
    }

    return $dependencies;
  }

  /**
   * {@inheritdoc}
   */
  public function onDependencyRemoval(array $dependencies) {
    $changed = parent::onDependencyRemoval($dependencies);
    $style_ids = [
      $this->getSetting('large_image_style'),
      $this->getSetting('small_image_style'),
    ];

    foreach ($style_ids as $style_id) {
      if (!$style_id) {
        continue;
      }

      $style = $this->imageStyleStorage->load($style_id);
      if (!$style) {
        continue;
      }

      $key = $style->getConfigDependencyKey();
      $name = $style->getConfigDependencyName();
      if (!empty($dependencies[$key][$name])) {
        $replacement_id = $this->imageStyleStorage->getReplacementId($style_id);
        // If a valid replacement has been provided in the storage, replace the
        // image style with the replacement and signal that the formatter plugin
        // settings were updated.
        if (!$replacement_id) {
          continue;
        }
        if ($this->imageStyleStorage->load($replacement_id)) {
          $this->setSetting('image_style', $replacement_id);
          $changed = TRUE;
        }
      }
    }

    return $changed;
  }

  /**
   * Generates the form for the image style settings.
   *
   * @param string $size
   *   The Easy 360 Viewer size that the image style will be used for
   *   i.e. `large` or `small`.
   * @param array $image_styles
   *   Array of all image styles with both key and value set to the style name.
   * @param \Drupal\Core\StringTranslation\TranslatableMarkup $description_text
   *   The translated text that will be used as the description of the form
   *   field.
   * @param array $description_link
   *   The render array for an additional link that will be appended to the
   *   description.
   *
   * @return array
   *   The render array for the image style setting of the given size.
   */
  protected function buildImageStyleSettingForm(
    $size,
    array $image_styles,
    TranslatableMarkup $description_text,
    array $description_link
  ) {
    return [
      '#title' => $this->t(
        '@size image style',
        ['@size' => ucfirst($size)]
      ),
      '#type' => 'select',
      '#default_value' => $this->getSetting($size . '_image_style'),
      '#empty_option' => $this->t('None (original image)'),
      '#options' => $image_styles,
      '#description' => [
        ['#markup' => $description_text . '<br />'],
        $description_link,
      ],
    ];
  }

  /**
   * Generates the summary for the image style settings.
   *
   * @param string $size
   *   The Easy 360 Viewer size that the image style will be used for
   *   i.e. `large` or `small`.
   *
   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
   *   The setting summary.
   */
  protected function imageStyleSettingSummary($size) {
    $style_id = $this->getSetting($size . '_image_style');
    $styles = image_style_options(FALSE);

    // Unset possible 'No defined styles' option.
    unset($styles['']);

    if (!isset($styles[$style_id])) {
      return $this->t('Original image');
    }

    return $this->t(
      '@size image style: @style',
      [
        '@size' => ucfirst($size),
        '@style' => $styles[$style_id],
      ]
    );
  }

  /**
   * Returns the image style entity and its cache tags for the given size.
   *
   * @param string $size
   *   The Easy 360 Viewer size that the image style will be used for
   *   i.e. `large` or `small`.
   *
   * @return array
   *   An array containing the image style entity as the first element and the
   *   cache tags array as the second.
   */
  protected function getStyleAndCacheTags($size) {
    $style = NULL;
    $cache_tags = [];

    $style_id = $this->getSetting($size . '_image_style');
    if ($style_id) {
      $style = $this->imageStyleStorage->load($style_id);
      $cache_tags = $style->getCacheTags();
    }

    return [$style, $cache_tags];
  }

}

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

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