ImageFieldFormatter::isValidImage()   B
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 24
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 3
nop 0
dl 0
loc 24
rs 8.6845
c 0
b 0
f 0
1
<?php
2
3
namespace Drupal\entity_embed\Plugin\entity_embed\EntityEmbedDisplay;
4
5
use Drupal\Core\Access\AccessResult;
6
use Drupal\Core\Entity\EntityTypeManagerInterface;
7
use Drupal\Core\Field\FormatterPluginManager;
8
use Drupal\Core\Form\FormStateInterface;
9
use Drupal\Core\Image\ImageFactory;
10
use Drupal\Core\Language\LanguageManagerInterface;
11
use Drupal\Core\Session\AccountInterface;
12
use Drupal\Core\TypedData\TypedDataManager;
13
use Symfony\Component\DependencyInjection\ContainerInterface;
14
15
/**
16
 * Entity Embed Display reusing image field formatters.
17
 *
18
 * @see \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayInterface
19
 *
20
 * @EntityEmbedDisplay(
21
 *   id = "image",
22
 *   label = @Translation("Image"),
23
 *   entity_types = {"file"},
24
 *   deriver = "Drupal\entity_embed\Plugin\Derivative\FieldFormatterDeriver",
25
 *   field_type = "image",
26
 *   provider = "image"
27
 * )
28
 */
29
class ImageFieldFormatter extends FileFieldFormatter {
30
31
  /**
32
   * The image factory.
33
   *
34
   * @var \Drupal\Core\Image\ImageFactory
35
   */
36
  protected $imageFactory;
37
38
  /**
39
   * {@inheritdoc}
40
   *
41
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
42
   *   The entity manager service.
43
   * @param \Drupal\Core\Field\FormatterPluginManager $formatter_plugin_manager
44
   *   The field formatter plugin manager.
45
   * @param \Drupal\Core\TypedData\TypedDataManager $typed_data_manager
46
   *   The typed data manager.
47
   * @param \Drupal\Core\Image\ImageFactory $image_factory
48
   *   The image factory.
49
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
50
   *   The language manager.
51
   */
52
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, FormatterPluginManager $formatter_plugin_manager, TypedDataManager $typed_data_manager, ImageFactory $image_factory, LanguageManagerInterface $language_manager) {
53
    parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $formatter_plugin_manager, $typed_data_manager, $language_manager);
54
    $this->imageFactory = $image_factory;
55
  }
56
57
  /**
58
   * {@inheritdoc}
59
   */
60 View Code Duplication
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
61
    return new static(
62
      $configuration,
63
      $plugin_id,
64
      $plugin_definition,
65
      $container->get('entity_type.manager'),
66
      $container->get('plugin.manager.field.formatter'),
67
      $container->get('typed_data_manager'),
68
      $container->get('image.factory'),
69
      $container->get('language_manager')
70
    );
71
  }
72
73
  /**
74
   * {@inheritdoc}
75
   */
76
  public function getFieldValue() {
77
    $value = parent::getFieldValue();
78
    // File field support descriptions, but images do not.
79
    unset($value['description']);
80
    $value += array_intersect_key($this->getAttributeValues(), array('alt' => '', 'title' => ''));
81
    return $value;
82
  }
83
84
  /**
85
   * {@inheritdoc}
86
   */
87
  public function access(AccountInterface $account = NULL) {
88
    return parent::access($account)->andIf($this->isValidImage());
89
  }
90
91
  /**
92
   * Checks if the image is valid.
93
   *
94
   * @return \Drupal\Core\Access\AccessResult
95
   *   Returns the access result.
96
   */
97
  protected function isValidImage() {
98
    // If entity type is not file we have to return early to prevent fatal in
99
    // the condition above. Access should already be forbidden at this point,
100
    // which means this won't have any effect.
101
    // @see EntityEmbedDisplayBase::access()
102
    if ($this->getEntityTypeFromContext() != 'file') {
103
      return AccessResult::forbidden();
104
    }
105
    $access = AccessResult::allowed();
106
107
    // @todo needs cacheability metadata for getEntityFromContext.
108
    // @see \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayBase::getEntityFromContext()
109
    /** @var \Drupal\file\FileInterface $entity */
110
    if ($entity = $this->getEntityFromContext()) {
111
      // Loading large files is slow, make sure it is an image mime type before
112
      // doing that.
113
      list($type,) = explode('/', $entity->getMimeType(), 2);
114
      $access = AccessResult::allowedIf($type == 'image' && $this->imageFactory->get($entity->getFileUri())->isValid())
115
        // See the above @todo, this is the best we can do for now.
116
        ->addCacheableDependency($entity);
117
    }
118
119
    return $access;
120
  }
121
122
  /**
123
   * {@inheritdoc}
124
   */
125
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
126
    $form = parent::buildConfigurationForm($form, $form_state);
127
128
    // File field support descriptions, but images do not.
129
    unset($form['description']);
130
131
    // Ensure that the 'Link image to: Content' setting is not available.
132
    if ($this->getDerivativeId() == 'image') {
133
      unset($form['image_link']['#options']['content']);
134
    }
135
136
    $entity_element = $form_state->get('entity_element');
137
    // The alt attribute is *required*, but we allow users to opt-in to empty
138
    // alt attributes for the very rare edge cases where that is valid by
139
    // specifying two double quotes as the alternative text in the dialog.
140
    // However, that *is* stored as an empty alt attribute, so if we're editing
141
    // an existing image (which means the src attribute is set) and its alt
142
    // attribute is empty, then we show that as two double quotes in the dialog.
143
    // @see https://www.drupal.org/node/2307647
144
    // Alt attribute behavior is taken from the Core image dialog to ensure a
145
    // consistent UX across various forms.
146
    // @see Drupal\editor\Form\EditorImageDialog::buildForm()
147
    $alt = $this->getAttributeValue('alt', '');
148
    if ($alt === '') {
149
      // Do not change empty alt text to two double quotes if the previously
150
      // used Entity Embed Display plugin was not 'image:image'. That means that
151
      // some other plugin was used so if this image formatter is selected at a
152
      // later stage, then this should be treated as a new edit. We show two
153
      // double quotes in place of empty alt text only if that was filled
154
      // intentionally by the user.
155
      if (!empty($entity_element) && $entity_element['data-entity-embed-display'] == 'image:image') {
156
        $alt = '""';
157
      }
158
    }
159
160
    // Add support for editing the alternate and title text attributes.
161
    $form['alt'] = array(
162
      '#type' => 'textfield',
163
      '#title' => $this->t('Alternate text'),
164
      '#default_value' => $alt,
165
      '#description' => $this->t('This text will be used by screen readers, search engines, or when the image cannot be loaded.'),
166
      '#parents' => array('attributes', 'alt'),
167
      '#required' => TRUE,
168
      '#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).'),
169
      '#maxlength' => 512,
170
    );
171
    $form['title'] = array(
172
      '#type' => 'textfield',
173
      '#title' => $this->t('Title'),
174
      '#default_value' => $this->getAttributeValue('title', ''),
175
      '#description' => t('The title is used as a tool tip when the user hovers the mouse over the image.'),
176
      '#parents' => array('attributes', 'title'),
177
      '#maxlength' => 1024,
178
    );
179
180
    return $form;
181
  }
182
183
  /**
184
   * {@inheritdoc}
185
   */
186
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
187
    // When the alt attribute is set to two double quotes, transform it to the
188
    // empty string: two double quotes signify "empty alt attribute". See above.
189
    if (trim($form_state->getValue(array('attributes', 'alt'))) === '""') {
190
      $form_state->setValue(array('attributes', 'alt'), '');
191
    }
192
  }
193
194
}
195