1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Drupal\entity_browser\Plugin\Field\FieldWidget; |
4
|
|
|
|
5
|
|
|
use Drupal\Component\Utility\Bytes; |
6
|
|
|
use Drupal\Component\Utility\SortArray; |
7
|
|
|
use Drupal\Core\Config\ConfigFactoryInterface; |
8
|
|
|
use Drupal\Core\Entity\EntityDisplayRepositoryInterface; |
9
|
|
|
use Drupal\Core\Entity\EntityTypeManagerInterface; |
10
|
|
|
use Drupal\Core\Field\FieldDefinitionInterface; |
11
|
|
|
use Drupal\Core\Field\FieldItemListInterface; |
12
|
|
|
use Drupal\Core\Form\FormStateInterface; |
13
|
|
|
use Drupal\Core\Image\ImageFactory; |
14
|
|
|
use Drupal\Core\Url; |
15
|
|
|
use Drupal\entity_browser\FieldWidgetDisplayManager; |
16
|
|
|
use Symfony\Component\DependencyInjection\ContainerInterface; |
17
|
|
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* Entity browser file widget. |
21
|
|
|
* |
22
|
|
|
* @FieldWidget( |
23
|
|
|
* id = "entity_browser_file", |
24
|
|
|
* label = @Translation("Entity browser"), |
25
|
|
|
* provider = "entity_browser", |
26
|
|
|
* multiple_values = TRUE, |
27
|
|
|
* field_types = { |
28
|
|
|
* "file", |
29
|
|
|
* "image" |
30
|
|
|
* } |
31
|
|
|
* ) |
32
|
|
|
*/ |
33
|
|
|
class FileBrowserWidget extends EntityReferenceBrowserWidget { |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Due to the table structure, this widget has a different depth. |
37
|
|
|
* |
38
|
|
|
* @var int |
39
|
|
|
*/ |
40
|
|
|
protected static $deleteDepth = 3; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* A list of currently edited items. Used to determine alt/title values. |
44
|
|
|
* |
45
|
|
|
* @var \Drupal\Core\Field\FieldItemListInterface |
46
|
|
|
*/ |
47
|
|
|
protected $items; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* The config factory service. |
51
|
|
|
* |
52
|
|
|
* @var \Drupal\Core\Config\ConfigFactoryInterface |
53
|
|
|
*/ |
54
|
|
|
protected $configFactory; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* The image factory service. |
58
|
|
|
* |
59
|
|
|
* @var \Drupal\Core\Image\ImageFactory |
60
|
|
|
*/ |
61
|
|
|
protected $imageFactory; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* The display repository service. |
65
|
|
|
* |
66
|
|
|
* @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface |
67
|
|
|
*/ |
68
|
|
|
protected $displayRepository; |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Constructs widget plugin. |
72
|
|
|
* |
73
|
|
|
* @param string $plugin_id |
74
|
|
|
* The plugin_id for the plugin instance. |
75
|
|
|
* @param mixed $plugin_definition |
76
|
|
|
* The plugin implementation definition. |
77
|
|
|
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition |
78
|
|
|
* The definition of the field to which the widget is associated. |
79
|
|
|
* @param array $settings |
80
|
|
|
* The widget settings. |
81
|
|
|
* @param array $third_party_settings |
82
|
|
|
* Any third party settings. |
83
|
|
|
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager |
84
|
|
|
* Entity type manager service. |
85
|
|
|
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher |
86
|
|
|
* Event dispatcher. |
87
|
|
|
* @param \Drupal\entity_browser\FieldWidgetDisplayManager $field_display_manager |
88
|
|
|
* Field widget display plugin manager. |
89
|
|
|
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory |
90
|
|
|
* The config factory. |
91
|
|
|
* @param \Drupal\Core\Image\ImageFactory $image_factory |
92
|
|
|
* The image factory. |
93
|
|
|
* @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $display_repository |
94
|
|
|
* The entity display repository service. |
95
|
|
|
*/ |
96
|
|
|
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeManagerInterface $entity_type_manager, EventDispatcherInterface $event_dispatcher, FieldWidgetDisplayManager $field_display_manager, ConfigFactoryInterface $config_factory, ImageFactory $image_factory, EntityDisplayRepositoryInterface $display_repository) { |
97
|
|
|
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings, $entity_type_manager, $event_dispatcher, $field_display_manager); |
98
|
|
|
$this->entityTypeManager = $entity_type_manager; |
99
|
|
|
$this->fieldDisplayManager = $field_display_manager; |
100
|
|
|
$this->configFactory = $config_factory; |
101
|
|
|
$this->imageFactory = $image_factory; |
102
|
|
|
$this->displayRepository = $display_repository; |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* {@inheritdoc} |
107
|
|
|
*/ |
108
|
|
|
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { |
109
|
|
|
return new static( |
110
|
|
|
$plugin_id, |
111
|
|
|
$plugin_definition, |
112
|
|
|
$configuration['field_definition'], |
113
|
|
|
$configuration['settings'], |
114
|
|
|
$configuration['third_party_settings'], |
115
|
|
|
$container->get('entity_type.manager'), |
116
|
|
|
$container->get('event_dispatcher'), |
117
|
|
|
$container->get('plugin.manager.entity_browser.field_widget_display'), |
118
|
|
|
$container->get('config.factory'), |
119
|
|
|
$container->get('image.factory'), |
120
|
|
|
$container->get('entity_display.repository') |
121
|
|
|
); |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
/** |
125
|
|
|
* {@inheritdoc} |
126
|
|
|
*/ |
127
|
|
|
public static function defaultSettings() { |
128
|
|
|
$settings = parent::defaultSettings(); |
129
|
|
|
|
130
|
|
|
// These settings are hidden. |
131
|
|
|
unset($settings['field_widget_display']); |
132
|
|
|
unset($settings['field_widget_display_settings']); |
133
|
|
|
|
134
|
|
|
$settings['view_mode'] = 'default'; |
135
|
|
|
$settings['preview_image_style'] = 'thumbnail'; |
136
|
|
|
|
137
|
|
|
return $settings; |
|
|
|
|
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* {@inheritdoc} |
142
|
|
|
*/ |
143
|
|
|
public function settingsForm(array $form, FormStateInterface $form_state) { |
144
|
|
|
$element = parent::settingsForm($form, $form_state); |
145
|
|
|
|
146
|
|
|
$element['field_widget_display']['#access'] = FALSE; |
147
|
|
|
$element['field_widget_display_settings']['#access'] = FALSE; |
148
|
|
|
|
149
|
|
|
$element['view_mode'] = [ |
150
|
|
|
'#title' => $this->t('File view mode'), |
151
|
|
|
'#type' => 'select', |
152
|
|
|
'#default_value' => $this->getSetting('view_mode'), |
153
|
|
|
'#options' => $this->displayRepository->getViewModeOptions('file'), |
154
|
|
|
]; |
155
|
|
|
|
156
|
|
|
$element['preview_image_style'] = [ |
157
|
|
|
'#title' => $this->t('Preview image style'), |
158
|
|
|
'#type' => 'select', |
159
|
|
|
'#options' => image_style_options(FALSE), |
160
|
|
|
'#default_value' => $this->getSetting('preview_image_style'), |
161
|
|
|
'#description' => $this->t('The preview image will be shown while editing the content. Only relevant if using the default file view mode.'), |
162
|
|
|
'#weight' => 15, |
163
|
|
|
'#access' => $this->fieldDefinition->getType() == 'image', |
164
|
|
|
]; |
165
|
|
|
|
166
|
|
|
return $element; |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
/** |
170
|
|
|
* {@inheritdoc} |
171
|
|
|
*/ |
172
|
|
|
public function settingsSummary() { |
173
|
|
|
$summary = []; |
174
|
|
|
$entity_browser_id = $this->getSetting('entity_browser'); |
175
|
|
|
$view_mode = $this->getSetting('view_mode'); |
176
|
|
|
$image_style_setting = $this->getSetting('preview_image_style'); |
177
|
|
|
|
178
|
|
|
if (empty($entity_browser_id)) { |
179
|
|
|
return [$this->t('No entity browser selected.')]; |
180
|
|
|
} |
181
|
|
|
else { |
182
|
|
|
$browser = $this->entityTypeManager->getStorage('entity_browser') |
183
|
|
|
->load($entity_browser_id); |
184
|
|
|
$summary[] = $this->t('Entity browser: @browser', ['@browser' => $browser->label()]); |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
if (!empty($view_mode)) { |
188
|
|
|
$summary[] = $this->t('View mode: @name', ['@name' => $view_mode]); |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
if ($this->fieldDefinition->getType() == 'image' && $view_mode == 'default') { |
192
|
|
|
$image_styles = image_style_options(FALSE); |
193
|
|
|
// Styles could be lost because of enabled/disabled modules that defines |
194
|
|
|
// their styles in code. |
195
|
|
|
if (isset($image_styles[$image_style_setting])) { |
196
|
|
|
$preview_image_style = $this->t('Preview image style: @style', ['@style' => $image_styles[$image_style_setting]]); |
197
|
|
|
} |
198
|
|
|
else { |
199
|
|
|
$preview_image_style = $this->t('No preview image'); |
200
|
|
|
} |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
array_unshift($summary, $preview_image_style); |
|
|
|
|
204
|
|
|
|
205
|
|
|
return $summary; |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
/** |
209
|
|
|
* {@inheritdoc} |
210
|
|
|
*/ |
211
|
|
|
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { |
212
|
|
|
$this->items = $items; |
213
|
|
|
return parent::formElement($items, $delta, $element, $form, $form_state); |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
/** |
217
|
|
|
* {@inheritdoc} |
218
|
|
|
*/ |
219
|
|
|
protected function displayCurrentSelection($details_id, $field_parents, $entities) { |
220
|
|
|
$field_type = $this->fieldDefinition->getType(); |
221
|
|
|
$field_settings = $this->fieldDefinition->getSettings(); |
222
|
|
|
$field_machine_name = $this->fieldDefinition->getName(); |
223
|
|
|
$file_settings = $this->configFactory->get('file.settings'); |
224
|
|
|
$widget_settings = $this->getSettings(); |
225
|
|
|
$view_mode = $widget_settings['view_mode']; |
226
|
|
|
$can_edit = (bool) $widget_settings['field_widget_edit']; |
227
|
|
|
|
228
|
|
|
$delta = 0; |
229
|
|
|
|
230
|
|
|
$order_class = $field_machine_name . '-delta-order'; |
231
|
|
|
|
232
|
|
|
$current = [ |
233
|
|
|
'#type' => 'table', |
234
|
|
|
'#header' => [ |
235
|
|
|
$this->t('Preview'), |
236
|
|
|
$this->t('Filename'), |
237
|
|
|
$this->t('Metadata'), |
238
|
|
|
['data' => $this->t('Operations'), 'colspan' => 2], |
239
|
|
|
$this->t('Order', [], ['context' => 'Sort order']), |
240
|
|
|
], |
241
|
|
|
'#empty' => $this->t('No files yet'), |
242
|
|
|
'#attributes' => ['class' => ['entities-list']], |
243
|
|
|
'#tabledrag' => [ |
244
|
|
|
[ |
245
|
|
|
'action' => 'order', |
246
|
|
|
'relationship' => 'sibling', |
247
|
|
|
'group' => $order_class, |
248
|
|
|
], |
249
|
|
|
], |
250
|
|
|
]; |
251
|
|
|
/** @var \Drupal\file\FileInterface[] $entities */ |
252
|
|
|
foreach ($entities as $entity) { |
253
|
|
|
// Check to see if this entity has an edit form. If not, the edit button |
254
|
|
|
// will only throw an exception. |
255
|
|
|
if (!$entity->getEntityType()->getFormClass('edit')) { |
256
|
|
|
$can_edit = FALSE; |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
$entity_id = $entity->id(); |
260
|
|
|
$uri = $entity->getFileUri(); |
261
|
|
|
if ($field_type == 'image' && $view_mode == 'default') { |
262
|
|
|
$image = $this->imageFactory->get($uri); |
263
|
|
|
if ($image->isValid()) { |
264
|
|
|
$width = $image->getWidth(); |
265
|
|
|
$height = $image->getHeight(); |
266
|
|
|
} |
267
|
|
|
else { |
268
|
|
|
$width = $height = NULL; |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
$display = [ |
272
|
|
|
'#weight' => -10, |
273
|
|
|
'#theme' => 'image_style', |
274
|
|
|
'#width' => $width, |
275
|
|
|
'#height' => $height, |
276
|
|
|
'#style_name' => $widget_settings['preview_image_style'], |
277
|
|
|
'#uri' => $uri, |
278
|
|
|
]; |
279
|
|
|
} |
280
|
|
|
else { |
281
|
|
|
$display = $this->entityTypeManager->getViewBuilder('file')->view($entity, $view_mode); |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
// Find the default description. |
285
|
|
|
$description = ''; |
286
|
|
|
$display_field = $field_settings['display_default']; |
287
|
|
|
$alt = ''; |
288
|
|
|
$title = ''; |
289
|
|
|
$weight = $delta; |
290
|
|
|
foreach ($this->items as $item) { |
291
|
|
|
if ($item->target_id == $entity_id) { |
292
|
|
|
if ($field_type == 'file') { |
293
|
|
|
$description = $item->description; |
294
|
|
|
$display_field = $item->display; |
295
|
|
|
} |
296
|
|
|
elseif ($field_type == 'image') { |
297
|
|
|
$alt = $item->alt; |
298
|
|
|
$title = $item->title; |
299
|
|
|
} |
300
|
|
|
$weight = $item->_weight ?: $delta; |
301
|
|
|
} |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
$current[$entity_id] = [ |
305
|
|
|
'#attributes' => [ |
306
|
|
|
'class' => ['draggable'], |
307
|
|
|
'data-entity-id' => $entity_id, |
308
|
|
|
], |
309
|
|
|
'display' => $display, |
310
|
|
|
'filename' => ['#markup' => $entity->label()], |
311
|
|
|
'meta' => [ |
312
|
|
|
'display_field' => [ |
313
|
|
|
'#type' => 'checkbox', |
314
|
|
|
'#title' => $this->t('Include file in display'), |
315
|
|
|
'#default_value' => (bool) $display_field, |
316
|
|
|
'#access' => $field_type == 'file' && $field_settings['display_field'], |
317
|
|
|
], |
318
|
|
|
'description' => [ |
319
|
|
|
'#type' => $file_settings->get('description.type'), |
320
|
|
|
'#title' => $this->t('Description'), |
321
|
|
|
'#default_value' => $description, |
322
|
|
|
'#size' => 45, |
323
|
|
|
'#maxlength' => $file_settings->get('description.length'), |
324
|
|
|
'#description' => $this->t('The description may be used as the label of the link to the file.'), |
325
|
|
|
'#access' => $field_type == 'file' && $field_settings['description_field'], |
326
|
|
|
], |
327
|
|
|
'alt' => [ |
328
|
|
|
'#type' => 'textfield', |
329
|
|
|
'#title' => $this->t('Alternative text'), |
330
|
|
|
'#default_value' => $alt, |
331
|
|
|
'#size' => 45, |
332
|
|
|
'#maxlength' => 512, |
333
|
|
|
'#description' => $this->t('This text will be used by screen readers, search engines, or when the image cannot be loaded.'), |
334
|
|
|
'#access' => $field_type == 'image' && $field_settings['alt_field'], |
335
|
|
|
'#required' => $field_type == 'image' && $field_settings['alt_field_required'], |
336
|
|
|
], |
337
|
|
|
'title' => [ |
338
|
|
|
'#type' => 'textfield', |
339
|
|
|
'#title' => $this->t('Title'), |
340
|
|
|
'#default_value' => $title, |
341
|
|
|
'#size' => 45, |
342
|
|
|
'#maxlength' => 1024, |
343
|
|
|
'#description' => $this->t('The title is used as a tool tip when the user hovers the mouse over the image.'), |
344
|
|
|
'#access' => $field_type == 'image' && $field_settings['title_field'], |
345
|
|
|
'#required' => $field_type == 'image' && $field_settings['title_field_required'], |
346
|
|
|
], |
347
|
|
|
], |
348
|
|
|
'edit_button' => [ |
349
|
|
|
'#type' => 'submit', |
350
|
|
|
'#value' => $this->t('Edit'), |
351
|
|
|
'#ajax' => [ |
352
|
|
|
'url' => Url::fromRoute('entity_browser.edit_form', ['entity_type' => $entity->getEntityTypeId(), 'entity' => $entity_id]), |
353
|
|
|
], |
354
|
|
|
'#access' => $can_edit, |
355
|
|
|
], |
356
|
|
|
'remove_button' => [ |
357
|
|
|
'#type' => 'submit', |
358
|
|
|
'#value' => $this->t('Remove'), |
359
|
|
|
'#ajax' => [ |
360
|
|
|
'callback' => [get_class($this), 'updateWidgetCallback'], |
361
|
|
|
'wrapper' => $details_id, |
362
|
|
|
], |
363
|
|
|
'#submit' => [[get_class($this), 'removeItemSubmit']], |
364
|
|
|
'#name' => $field_machine_name . '_remove_' . $entity_id, |
365
|
|
|
'#limit_validation_errors' => [], |
366
|
|
|
'#attributes' => ['data-entity-id' => $entity_id], |
367
|
|
|
'#access' => (bool) $widget_settings['field_widget_remove'], |
368
|
|
|
], |
369
|
|
|
'_weight' => [ |
370
|
|
|
'#type' => 'weight', |
371
|
|
|
'#title' => $this->t('Weight for row @number', ['@number' => $delta + 1]), |
372
|
|
|
'#title_display' => 'invisible', |
373
|
|
|
// Note: this 'delta' is the FAPI #type 'weight' element's property. |
374
|
|
|
'#delta' => count($entities), |
375
|
|
|
'#default_value' => $weight, |
376
|
|
|
'#attributes' => ['class' => [$order_class]], |
377
|
|
|
], |
378
|
|
|
]; |
379
|
|
|
|
380
|
|
|
$delta++; |
381
|
|
|
} |
382
|
|
|
|
383
|
|
|
return $current; |
384
|
|
|
} |
385
|
|
|
|
386
|
|
|
/** |
387
|
|
|
* {@inheritdoc} |
388
|
|
|
*/ |
389
|
|
|
public function massageFormValues(array $values, array $form, FormStateInterface $form_state) { |
390
|
|
|
$ids = empty($values['target_id']) ? [] : explode(' ', trim($values['target_id'])); |
391
|
|
|
$return = []; |
392
|
|
|
foreach ($ids as $id) { |
393
|
|
|
if (is_array($values['current']) && isset($values['current'][$id])) { |
394
|
|
|
$item_values = [ |
395
|
|
|
'target_id' => $id, |
396
|
|
|
'_weight' => $values['current'][$id]['_weight'], |
397
|
|
|
]; |
398
|
|
View Code Duplication |
if ($this->fieldDefinition->getType() == 'file') { |
|
|
|
|
399
|
|
|
if (isset($values['current'][$id]['meta']['description'])) { |
400
|
|
|
$item_values['description'] = $values['current'][$id]['meta']['description']; |
401
|
|
|
} |
402
|
|
|
if ($this->fieldDefinition->getSetting('display_field') && isset($values['current'][$id]['meta']['display_field'])) { |
403
|
|
|
$item_values['display'] = $values['current'][$id]['meta']['display_field']; |
404
|
|
|
} |
405
|
|
|
} |
406
|
|
View Code Duplication |
if ($this->fieldDefinition->getType() == 'image') { |
|
|
|
|
407
|
|
|
if (isset($values['current'][$id]['meta']['alt'])) { |
408
|
|
|
$item_values['alt'] = $values['current'][$id]['meta']['alt']; |
409
|
|
|
} |
410
|
|
|
if (isset($values['current'][$id]['meta']['title'])) { |
411
|
|
|
$item_values['title'] = $values['current'][$id]['meta']['title']; |
412
|
|
|
} |
413
|
|
|
} |
414
|
|
|
$return[] = $item_values; |
415
|
|
|
} |
416
|
|
|
} |
417
|
|
|
|
418
|
|
|
// Return ourself as the structure doesn't match the default. |
419
|
|
|
usort($return, function ($a, $b) { |
420
|
|
|
return SortArray::sortByKeyInt($a, $b, '_weight'); |
421
|
|
|
}); |
422
|
|
|
|
423
|
|
|
return array_values($return); |
424
|
|
|
} |
425
|
|
|
|
426
|
|
|
/** |
427
|
|
|
* Retrieves the upload validators for a file field. |
428
|
|
|
* |
429
|
|
|
* This is a combination of logic shared between the File and Image widgets. |
430
|
|
|
* |
431
|
|
|
* @return array |
432
|
|
|
* An array suitable for passing to file_save_upload() or the file field |
433
|
|
|
* element's '#upload_validators' property. |
434
|
|
|
*/ |
435
|
|
|
public function getFileValidators() { |
436
|
|
|
$validators = []; |
437
|
|
|
$settings = $this->fieldDefinition->getSettings(); |
438
|
|
|
|
439
|
|
|
// Cap the upload size according to the PHP limit. |
440
|
|
|
$max_filesize = Bytes::toInt(file_upload_max_size()); |
441
|
|
|
if (!empty($settings['max_filesize'])) { |
442
|
|
|
$max_filesize = min($max_filesize, Bytes::toInt($settings['max_filesize'])); |
443
|
|
|
} |
444
|
|
|
|
445
|
|
|
// There is always a file size limit due to the PHP server limit. |
446
|
|
|
$validators['file_validate_size'] = [$max_filesize]; |
447
|
|
|
|
448
|
|
|
// Images have expected defaults for file extensions. |
449
|
|
|
// See \Drupal\image\Plugin\Field\FieldWidget::formElement() for details. |
450
|
|
|
if ($this->fieldDefinition->getType() == 'image') { |
451
|
|
|
// If not using custom extension validation, ensure this is an image. |
452
|
|
|
$supported_extensions = ['png', 'gif', 'jpg', 'jpeg']; |
453
|
|
|
$extensions = isset($settings['file_extensions']) ? $settings['file_extensions'] : implode(' ', $supported_extensions); |
454
|
|
|
$extensions = array_intersect(explode(' ', $extensions), $supported_extensions); |
455
|
|
|
$validators['file_validate_extensions'] = [implode(' ', $extensions)]; |
456
|
|
|
} |
457
|
|
|
elseif (!empty($settings['file_extensions'])) { |
458
|
|
|
$validators['file_validate_extensions'] = [$settings['file_extensions']]; |
459
|
|
|
} |
460
|
|
|
|
461
|
|
|
// Add upload resolution validation. |
462
|
|
|
if ($settings['max_resolution'] || $settings['min_resolution']) { |
463
|
|
|
$validators['entity_browser_file_validate_image_resolution'] = [$settings['max_resolution'], $settings['min_resolution']]; |
464
|
|
|
} |
465
|
|
|
|
466
|
|
|
return $validators; |
467
|
|
|
} |
468
|
|
|
|
469
|
|
|
/** |
470
|
|
|
* {@inheritdoc} |
471
|
|
|
*/ |
472
|
|
|
protected function getPersistentData() { |
473
|
|
|
$data = parent::getPersistentData(); |
474
|
|
|
$settings = $this->fieldDefinition->getSettings(); |
475
|
|
|
// Add validators based on our current settings. |
476
|
|
|
$data['validators']['file'] = ['validators' => $this->getFileValidators()]; |
477
|
|
|
// Provide context for widgets to enhance their configuration. Currently |
478
|
|
|
// we only know that "upload_location" is used. |
479
|
|
|
$data['widget_context']['upload_location'] = $settings['uri_scheme'] . '://' . $settings['file_directory']; |
480
|
|
|
return $data; |
481
|
|
|
} |
482
|
|
|
|
483
|
|
|
} |
484
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.