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) { |
|
|
|
|
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
|
|
|
|
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.