Completed
Push — 8.x-1.x ( 657e32...c248cd )
by Janez
02:38
created

ImageFieldFormatter::isValidImage()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 21
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 3
eloc 8
c 1
b 1
f 0
nc 3
nop 0
dl 0
loc 21
rs 9.3142
1
<?php
2
3
/**
4
 * @file
5
 * Contains \Drupal\entity_embed\Plugin\entity_embed\EntityEmbedDisplay\ImageFieldFormatter.
6
 */
7
8
namespace Drupal\entity_embed\Plugin\entity_embed\EntityEmbedDisplay;
9
10
use Drupal\Core\Access\AccessResult;
11
use Drupal\Core\Entity\EntityManagerInterface;
12
use Drupal\Core\Field\FormatterPluginManager;
13
use Drupal\Core\Form\FormStateInterface;
14
use Drupal\Core\Image\ImageFactory;
15
use Drupal\Core\Session\AccountInterface;
16
use Drupal\Core\TypedData\TypedDataManager;
17
use Symfony\Component\DependencyInjection\ContainerInterface;
18
19
/**
20
 * Entity Embed Display reusing image field formatters.
21
 *
22
 * @see \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayInterface
23
 *
24
 * @EntityEmbedDisplay(
25
 *   id = "image",
26
 *   label = @Translation("Image"),
27
 *   entity_types = {"file"},
28
 *   deriver = "Drupal\entity_embed\Plugin\Derivative\FieldFormatterDeriver",
29
 *   field_type = "image",
30
 *   provider = "image"
31
 * )
32
 */
33
class ImageFieldFormatter extends FileFieldFormatter {
34
35
  /**
36
    * The image factory.
37
    *
38
    * @var \Drupal\Core\Image\ImageFactory
39
    */
40
    protected $imageFactory;
41
42
  /**
43
   * {@inheritdoc}
44
   *
45
   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
46
   *   The entity manager service.
47
   * @param \Drupal\Core\Field\FormatterPluginManager $formatter_plugin_manager
48
   *   The field formatter plugin manager.
49
   * @param \Drupal\Core\TypedData\TypedDataManager $typed_data_manager
50
   *   The typed data manager.
51
   * @param \Drupal\Core\Image\ImageFactory $image_factory
52
   *   The image factory.
53
   */
54
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager, FormatterPluginManager $formatter_plugin_manager, TypedDataManager $typed_data_manager, ImageFactory $image_factory) {
55
    parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_manager, $formatter_plugin_manager, $typed_data_manager);
56
    $this->imageFactory = $image_factory;
57
  }
58
59
  /**
60
   * {@inheritdoc}
61
   */
62 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...
63
    return new static(
64
      $configuration,
65
      $plugin_id,
66
      $plugin_definition,
67
      $container->get('entity.manager'),
68
      $container->get('plugin.manager.field.formatter'),
69
      $container->get('typed_data_manager'),
70
      $container->get('image.factory')
71
    );
72
  }
73
74
  /**
75
   * {@inheritdoc}
76
   */
77
  public function getFieldValue() {
78
    $value = parent::getFieldValue();
79
    // File field support descriptions, but images do not.
80
    unset($value['description']);
81
    $value += array_intersect_key($this->getAttributeValues(), array('alt' => '', 'title' => ''));
82
    return $value;
83
  }
84
85
  /**
86
   * {@inheritdoc}
87
   */
88
  public function access(AccountInterface $account = NULL) {
89
    return parent::access($account)->andIf($this->isValidImage());
90
  }
91
92
  /**
93
   * Checks if the image is valid.
94
   *
95
   * @return \Drupal\Core\Access\AccessResult
96
   *   Returns the access result.
97
   */
98
  protected function isValidImage() {
99
    // If entity type is not file we have to return early to prevent fatal in
100
    // the condition above. Access should already be forbidden at this point,
101
    // which means this won't have any effect.
102
    // @see EntityEmbedDisplayBase::access()
103
    if ($this->getEntityTypeFromContext() != 'file') {
104
      return AccessResult::forbidden();
105
    }
106
    $access = AccessResult::allowed();
107
108
    // @todo needs cacheability metadata for getEntityFromContext.
109
    // @see \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayBase::getEntityFromContext()
110
    /** @var \Drupal\file\FileInterface $entity */
111
    if ($entity = $this->getEntityFromContext()) {
112
      $access = AccessResult::allowedIf($this->imageFactory->get($entity->getFileUri())->isValid())
113
        // See the above @todo, this is the best we can do for now.
114
        ->addCacheableDependency($entity);
115
    }
116
117
    return $access;
118
  }
119
120
  /**
121
   * {@inheritdoc}
122
   */
123
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
124
    $form = parent::buildConfigurationForm($form, $form_state);
125
126
    // File field support descriptions, but images do not.
127
    unset($form['description']);
128
129
    // Ensure that the 'Link image to: Content' setting is not available.
130
    if ($this->getDerivativeId() == 'image') {
131
      unset($form['image_link']['#options']['content']);
132
    }
133
134
    $entity_element = $form_state->get('entity_element');
135
    // The alt attribute is *required*, but we allow users to opt-in to empty
136
    // alt attributes for the very rare edge cases where that is valid by
137
    // specifying two double quotes as the alternative text in the dialog.
138
    // However, that *is* stored as an empty alt attribute, so if we're editing
139
    // an existing image (which means the src attribute is set) and its alt
140
    // attribute is empty, then we show that as two double quotes in the dialog.
141
    // @see https://www.drupal.org/node/2307647
142
    // Alt attribute behavior is taken from the Core image dialog to ensure a
143
    // consistent UX across various forms.
144
    // @see Drupal\editor\Form\EditorImageDialog::buildForm()
145
    $alt = $this->getAttributeValue('alt', '');
146
    if ($alt === '') {
147
      // Do not change empty alt text to two double quotes if the previously
148
      // used Entity Embed Display plugin was not 'image:image'. That means that
149
      // some other plugin was used so if this image formatter is selected at a
150
      // later stage, then this should be treated as a new edit. We show two
151
      // double quotes in place of empty alt text only if that was filled
152
      // intentionally by the user.
153
      if (!empty($entity_element) && $entity_element['data-entity-embed-display'] == 'image:image') {
154
        $alt = '""';
155
      }
156
    }
157
158
    // Add support for editing the alternate and title text attributes.
159
    $form['alt'] = array(
160
      '#type' => 'textfield',
161
      '#title' => $this->t('Alternate text'),
162
      '#default_value' => $alt,
163
      '#description' => $this->t('This text will be used by screen readers, search engines, or when the image cannot be loaded.'),
164
      '#parents' => array('attributes', 'alt'),
165
      '#required' => TRUE,
166
      '#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).'),
167
      '#maxlength' => 512,
168
    );
169
    $form['title'] = array(
170
      '#type' => 'textfield',
171
      '#title' => $this->t('Title'),
172
      '#default_value' => $this->getAttributeValue('title', ''),
173
      '#description' => t('The title is used as a tool tip when the user hovers the mouse over the image.'),
174
      '#parents' => array('attributes', 'title'),
175
      '#maxlength' => 1024,
176
    );
177
178
    return $form;
179
  }
180
181
  /**
182
   * {@inheritdoc}
183
   */
184
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
185
    // When the alt attribute is set to two double quotes, transform it to the
186
    // empty string: two double quotes signify "empty alt attribute". See above.
187
    if (trim($form_state->getValue(array('attributes', 'alt'))) === '""') {
188
      $form_state->setValue(array('attributes', 'alt'), '');
189
    }
190
  }
191
192
}
193