You are here

MediaImageDecorator.php in Entity Embed 8

File

src/Plugin/entity_embed/EntityEmbedDisplay/MediaImageDecorator.php
View source
<?php

namespace Drupal\entity_embed\Plugin\entity_embed\EntityEmbedDisplay;

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayInterface;
use Drupal\image\Plugin\Field\FieldType\ImageItem;
use Drupal\media\MediaInterface;

/**
 * Decorator on all EntityEmbedDisplays that adds alt and title overriding.
 */
class MediaImageDecorator implements EntityEmbedDisplayInterface {
  use StringTranslationTrait;

  /**
   * A string that signifies not to render the alt text.
   *
   * @const string
   */
  const EMPTY_STRING = '""';

  /**
   * The decorated EntityEmbedDisplay class.
   *
   * @var \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayInterface
   */
  private $decorated;

  /**
   * MediaImageDecorator constructor.
   *
   * @param \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayInterface $decorated
   *   The decorated EntityEmbedDisplay plugin.
   */
  public function __construct(EntityEmbedDisplayInterface $decorated) {
    $this->decorated = $decorated;
  }

  /**
   * Passes through all unknown calls to the decorated object.
   */
  public function __call($method, $args) {
    return call_user_func_array([
      $this->decorated,
      $method,
    ], $args);
  }

  /**
   * {@inheritdoc}
   */
  public function access(AccountInterface $account = NULL) {
    return $this->decorated
      ->access($account);
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
    return $this->decorated
      ->validateConfigurationForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return $this->decorated
      ->defaultConfiguration();
  }

  /**
   * {@inheritdoc}
   */
  public function calculateDependencies() {
    return $this->decorated
      ->calculateDependencies();
  }

  /**
   * {@inheritdoc}
   */
  public function getConfiguration() {
    return $this->decorated
      ->getConfiguration();
  }

  /**
   * {@inheritdoc}
   */
  public function getPluginDefinition() {
    return $this->decorated
      ->getPluginDefinition();
  }

  /**
   * {@inheritdoc}
   */
  public function getPluginId() {
    return $this->decorated
      ->getPluginId();
  }

  /**
   * {@inheritdoc}
   */
  public function setConfiguration(array $configuration) {
    return $this->decorated
      ->setConfiguration($configuration);
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $form = $this->decorated
      ->buildConfigurationForm($form, $form_state);

    /** @var \Drupal\Core\Entity\EntityInterface $entity */
    $entity = $this->decorated
      ->getEntityFromContext();
    if ($image_field = $this
      ->getMediaImageSourceField($entity)) {
      $settings = $entity->{$image_field}
        ->getItemDefinition()
        ->getSettings();
      $attributes = $this
        ->getAttributeValues();
      $alt = isset($attributes['alt']) ? $attributes['alt'] : NULL;
      $title = isset($attributes['title']) ? $attributes['title'] : NULL;

      // Setting empty alt to double quotes. See ImageFieldFormatter.
      if ($settings['alt_field_required'] && $alt === '') {
        $alt = static::EMPTY_STRING;
      }
      if (!empty($settings['alt_field'])) {

        // Add support for editing the alternate and title text attributes.
        $form['alt'] = [
          '#type' => 'textfield',
          '#title' => $this
            ->t('Alternate text'),
          '#default_value' => $alt,
          '#description' => $this
            ->t('This text will be used by screen readers, search engines, or when the image cannot be loaded.'),
          '#required_error' => $this
            ->t('Alternative text is required.<br />(Only in rare cases should this be left empty. To create empty alternative text, enter <code>""</code> — two double quotes without any content).'),
          '#maxlength' => 512,
          '#placeholder' => $entity->{$image_field}->alt,
        ];
      }
      if (!empty($settings['title_field'])) {
        $form['title'] = [
          '#type' => 'textfield',
          '#title' => $this
            ->t('Title'),
          '#default_value' => $title,
          '#description' => t('The title is used as a tool tip when the user hovers the mouse over the image.'),
          '#maxlength' => 1024,
          '#placeholder' => $entity->{$image_field}->title,
        ];
      }
    }
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {

    /** @var \Drupal\Core\Entity\EntityInterface $entity */
    $entity = $this->decorated
      ->getEntityFromContext();
    if ($image_field = $this
      ->getMediaImageSourceField($entity)) {
      $settings = $entity->{$image_field}
        ->getItemDefinition()
        ->getSettings();
      $values = $form_state
        ->getValue([
        'attributes',
        'data-entity-embed-display-settings',
      ]);
      if (!empty($settings['alt_field'])) {

        // When the alt attribute is set to two double quotes, transform it to
        // the empty string: two double quotes signify "empty alt attribute".
        // See ImagefieldFormatter.
        if (trim($values['alt']) === static::EMPTY_STRING) {
          $values['alt'] = static::EMPTY_STRING;
        }
        elseif ($values['alt'] === $entity->{$image_field}->alt) {
          $values['alt'] = '';
        }
        $form_state
          ->setValue([
          'attributes',
          'alt',
        ], $values['alt']);
        $form_state
          ->unsetValue([
          'attributes',
          'data-entity-embed-display-settings',
          'alt',
        ]);
      }
      if (!empty($settings['title_field'])) {
        if (empty($values['title'])) {
          $values['title'] = '';
        }
        elseif ($values['title'] === $entity->{$image_field}->title) {
          $values['title'] = '';
        }
        $form_state
          ->setValue([
          'attributes',
          'title',
        ], $values['title']);
        $form_state
          ->unsetValue([
          'attributes',
          'data-entity-embed-display-settings',
          'title',
        ]);
      }
    }
    $this->decorated
      ->submitConfigurationForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function build() {
    $build = $this->decorated
      ->build();

    /** @var \Drupal\Core\Entity\EntityInterface $entity */
    $entity = $this->decorated
      ->getEntityFromContext();
    if ($image_field = $this
      ->getMediaImageSourceField($entity)) {
      $settings = $entity->{$image_field}
        ->getItemDefinition()
        ->getSettings();
      if (!empty($settings['alt_field']) && $this
        ->hasAttribute('alt')) {
        $entity->{$image_field}->alt = $this
          ->getAttributeValue('alt');
        $entity->thumbnail->alt = $this
          ->getAttributeValue('alt');
      }
      if (!empty($settings['title_field']) && $this
        ->hasAttribute('title')) {
        $entity->{$image_field}->title = $this
          ->getAttributeValue('title');
        $entity->thumbnail->title = $this
          ->getAttributeValue('title');
      }
    }
    return $build;
  }

  /**
   * Get image field from source config.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   Embedded entity.
   *
   * @return string|null
   *   String of image field name.
   */
  protected function getMediaImageSourceField(EntityInterface $entity) {
    if (!$entity instanceof MediaInterface) {
      return NULL;
    }
    $field_definition = $entity
      ->getSource()
      ->getSourceFieldDefinition($entity->bundle->entity);
    $item_class = $field_definition
      ->getItemDefinition()
      ->getClass();
    if ($item_class == ImageItem::class || is_subclass_of($item_class, ImageItem::class)) {
      return $field_definition
        ->getName();
    }
    return NULL;
  }

}

Classes

Namesort descending Description
MediaImageDecorator Decorator on all EntityEmbedDisplays that adds alt and title overriding.