Mercurial > hg > isophonics-drupal-site
comparison core/modules/media/src/Entity/Media.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 7a779792577d |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\media\Entity; | |
4 | |
5 use Drupal\Core\Entity\EditorialContentEntityBase; | |
6 use Drupal\Core\Entity\EntityStorageInterface; | |
7 use Drupal\Core\Entity\EntityTypeInterface; | |
8 use Drupal\Core\Field\BaseFieldDefinition; | |
9 use Drupal\Core\StringTranslation\StringTranslationTrait; | |
10 use Drupal\media\MediaInterface; | |
11 use Drupal\media\MediaSourceEntityConstraintsInterface; | |
12 use Drupal\media\MediaSourceFieldConstraintsInterface; | |
13 use Drupal\user\UserInterface; | |
14 | |
15 /** | |
16 * Defines the media entity class. | |
17 * | |
18 * @todo Remove default/fallback entity form operation when #2006348 is done. | |
19 * @see https://www.drupal.org/node/2006348. | |
20 * | |
21 * @ContentEntityType( | |
22 * id = "media", | |
23 * label = @Translation("Media"), | |
24 * label_singular = @Translation("media item"), | |
25 * label_plural = @Translation("media items"), | |
26 * label_count = @PluralTranslation( | |
27 * singular = "@count media item", | |
28 * plural = "@count media items" | |
29 * ), | |
30 * bundle_label = @Translation("Media type"), | |
31 * handlers = { | |
32 * "storage" = "Drupal\Core\Entity\Sql\SqlContentEntityStorage", | |
33 * "view_builder" = "Drupal\Core\Entity\EntityViewBuilder", | |
34 * "list_builder" = "Drupal\Core\Entity\EntityListBuilder", | |
35 * "access" = "Drupal\media\MediaAccessControlHandler", | |
36 * "form" = { | |
37 * "default" = "Drupal\media\MediaForm", | |
38 * "add" = "Drupal\media\MediaForm", | |
39 * "edit" = "Drupal\media\MediaForm", | |
40 * "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm", | |
41 * }, | |
42 * "translation" = "Drupal\content_translation\ContentTranslationHandler", | |
43 * "views_data" = "Drupal\media\MediaViewsData", | |
44 * "route_provider" = { | |
45 * "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider", | |
46 * } | |
47 * }, | |
48 * base_table = "media", | |
49 * data_table = "media_field_data", | |
50 * revision_table = "media_revision", | |
51 * revision_data_table = "media_field_revision", | |
52 * translatable = TRUE, | |
53 * show_revision_ui = TRUE, | |
54 * entity_keys = { | |
55 * "id" = "mid", | |
56 * "revision" = "vid", | |
57 * "bundle" = "bundle", | |
58 * "label" = "name", | |
59 * "langcode" = "langcode", | |
60 * "uuid" = "uuid", | |
61 * "published" = "status", | |
62 * }, | |
63 * revision_metadata_keys = { | |
64 * "revision_user" = "revision_user", | |
65 * "revision_created" = "revision_created", | |
66 * "revision_log_message" = "revision_log_message", | |
67 * }, | |
68 * bundle_entity_type = "media_type", | |
69 * permission_granularity = "entity_type", | |
70 * admin_permission = "administer media", | |
71 * field_ui_base_route = "entity.media_type.edit_form", | |
72 * common_reference_target = TRUE, | |
73 * links = { | |
74 * "add-page" = "/media/add", | |
75 * "add-form" = "/media/add/{media_type}", | |
76 * "canonical" = "/media/{media}", | |
77 * "delete-form" = "/media/{media}/delete", | |
78 * "edit-form" = "/media/{media}/edit", | |
79 * "revision" = "/media/{media}/revisions/{media_revision}/view", | |
80 * } | |
81 * ) | |
82 */ | |
83 class Media extends EditorialContentEntityBase implements MediaInterface { | |
84 | |
85 use StringTranslationTrait; | |
86 | |
87 /** | |
88 * {@inheritdoc} | |
89 */ | |
90 public function getName() { | |
91 $name = $this->get('name'); | |
92 | |
93 if ($name->isEmpty()) { | |
94 $media_source = $this->getSource(); | |
95 return $media_source->getMetadata($this, $media_source->getPluginDefinition()['default_name_metadata_attribute']); | |
96 } | |
97 else { | |
98 return $name->value; | |
99 } | |
100 } | |
101 | |
102 /** | |
103 * {@inheritdoc} | |
104 */ | |
105 public function label() { | |
106 return $this->getName(); | |
107 } | |
108 | |
109 /** | |
110 * {@inheritdoc} | |
111 */ | |
112 public function setName($name) { | |
113 return $this->set('name', $name); | |
114 } | |
115 | |
116 /** | |
117 * {@inheritdoc} | |
118 */ | |
119 public function getCreatedTime() { | |
120 return $this->get('created')->value; | |
121 } | |
122 | |
123 /** | |
124 * {@inheritdoc} | |
125 */ | |
126 public function setCreatedTime($timestamp) { | |
127 return $this->set('created', $timestamp); | |
128 } | |
129 | |
130 /** | |
131 * {@inheritdoc} | |
132 */ | |
133 public function getOwner() { | |
134 return $this->get('uid')->entity; | |
135 } | |
136 | |
137 /** | |
138 * {@inheritdoc} | |
139 */ | |
140 public function setOwner(UserInterface $account) { | |
141 return $this->set('uid', $account->id()); | |
142 } | |
143 | |
144 /** | |
145 * {@inheritdoc} | |
146 */ | |
147 public function getOwnerId() { | |
148 return $this->get('uid')->target_id; | |
149 } | |
150 | |
151 /** | |
152 * {@inheritdoc} | |
153 */ | |
154 public function setOwnerId($uid) { | |
155 return $this->set('uid', $uid); | |
156 } | |
157 | |
158 /** | |
159 * {@inheritdoc} | |
160 */ | |
161 public function getSource() { | |
162 return $this->bundle->entity->getSource(); | |
163 } | |
164 | |
165 /** | |
166 * Update the thumbnail for the media item. | |
167 * | |
168 * @param bool $from_queue | |
169 * Specifies whether the thumbnail update is triggered from the queue. | |
170 * | |
171 * @return \Drupal\media\MediaInterface | |
172 * The updated media item. | |
173 * | |
174 * @internal | |
175 * | |
176 * @todo There has been some disagreement about how to handle updates to | |
177 * thumbnails. We need to decide on what the API will be for this. | |
178 * https://www.drupal.org/node/2878119 | |
179 */ | |
180 protected function updateThumbnail($from_queue = FALSE) { | |
181 $file_storage = \Drupal::service('entity_type.manager')->getStorage('file'); | |
182 $thumbnail_uri = $this->getThumbnailUri($from_queue); | |
183 $existing = $file_storage->getQuery() | |
184 ->condition('uri', $thumbnail_uri) | |
185 ->execute(); | |
186 | |
187 if ($existing) { | |
188 $this->thumbnail->target_id = reset($existing); | |
189 } | |
190 else { | |
191 /** @var \Drupal\file\FileInterface $file */ | |
192 $file = $file_storage->create(['uri' => $thumbnail_uri]); | |
193 if ($owner = $this->getOwner()) { | |
194 $file->setOwner($owner); | |
195 } | |
196 $file->setPermanent(); | |
197 $file->save(); | |
198 $this->thumbnail->target_id = $file->id(); | |
199 } | |
200 | |
201 // Set the thumbnail alt. | |
202 $media_source = $this->getSource(); | |
203 $plugin_definition = $media_source->getPluginDefinition(); | |
204 if (!empty($plugin_definition['thumbnail_alt_metadata_attribute'])) { | |
205 $this->thumbnail->alt = $media_source->getMetadata($this, $plugin_definition['thumbnail_alt_metadata_attribute']); | |
206 } | |
207 else { | |
208 $this->thumbnail->alt = $this->t('Thumbnail', [], ['langcode' => $this->langcode->value]); | |
209 } | |
210 | |
211 // Set the thumbnail title. | |
212 if (!empty($plugin_definition['thumbnail_title_metadata_attribute'])) { | |
213 $this->thumbnail->title = $media_source->getMetadata($this, $plugin_definition['thumbnail_title_metadata_attribute']); | |
214 } | |
215 else { | |
216 $this->thumbnail->title = $this->label(); | |
217 } | |
218 | |
219 return $this; | |
220 } | |
221 | |
222 /** | |
223 * Updates the queued thumbnail for the media item. | |
224 * | |
225 * @return \Drupal\media\MediaInterface | |
226 * The updated media item. | |
227 * | |
228 * @internal | |
229 * | |
230 * @todo If the need arises in contrib, consider making this a public API, | |
231 * by adding an interface that extends MediaInterface. | |
232 */ | |
233 public function updateQueuedThumbnail() { | |
234 $this->updateThumbnail(TRUE); | |
235 return $this; | |
236 } | |
237 | |
238 /** | |
239 * Gets the URI for the thumbnail of a media item. | |
240 * | |
241 * If thumbnail fetching is queued, new media items will use the default | |
242 * thumbnail, and existing media items will use the current thumbnail, until | |
243 * the queue is processed and the updated thumbnail has been fetched. | |
244 * Otherwise, the new thumbnail will be fetched immediately. | |
245 * | |
246 * @param bool $from_queue | |
247 * Specifies whether the thumbnail is being fetched from the queue. | |
248 * | |
249 * @return string | |
250 * The file URI for the thumbnail of the media item. | |
251 * | |
252 * @internal | |
253 */ | |
254 protected function getThumbnailUri($from_queue) { | |
255 $thumbnails_queued = $this->bundle->entity->thumbnailDownloadsAreQueued(); | |
256 if ($thumbnails_queued && $this->isNew()) { | |
257 $default_thumbnail_filename = $this->getSource()->getPluginDefinition()['default_thumbnail_filename']; | |
258 $thumbnail_uri = \Drupal::service('config.factory')->get('media.settings')->get('icon_base_uri') . '/' . $default_thumbnail_filename; | |
259 } | |
260 elseif ($thumbnails_queued && !$from_queue) { | |
261 $thumbnail_uri = $this->get('thumbnail')->entity->getFileUri(); | |
262 } | |
263 else { | |
264 $thumbnail_uri = $this->getSource()->getMetadata($this, $this->getSource()->getPluginDefinition()['thumbnail_uri_metadata_attribute']); | |
265 } | |
266 | |
267 return $thumbnail_uri; | |
268 } | |
269 | |
270 /** | |
271 * Determines if the source field value has changed. | |
272 * | |
273 * @return bool | |
274 * TRUE if the source field value changed, FALSE otherwise. | |
275 * | |
276 * @internal | |
277 */ | |
278 protected function hasSourceFieldChanged() { | |
279 $source_field_name = $this->getSource()->getConfiguration()['source_field']; | |
280 $current_items = $this->get($source_field_name); | |
281 return isset($this->original) && !$current_items->equals($this->original->get($source_field_name)); | |
282 } | |
283 | |
284 /** | |
285 * Determines if the thumbnail should be updated for a media item. | |
286 * | |
287 * @param bool $is_new | |
288 * Specifies whether the media item is new. | |
289 * | |
290 * @return bool | |
291 * TRUE if the thumbnail should be updated, FALSE otherwise. | |
292 */ | |
293 protected function shouldUpdateThumbnail($is_new = FALSE) { | |
294 // Update thumbnail if we don't have a thumbnail yet or when the source | |
295 // field value changes. | |
296 return !$this->get('thumbnail')->entity || $is_new || $this->hasSourceFieldChanged(); | |
297 } | |
298 | |
299 /** | |
300 * {@inheritdoc} | |
301 */ | |
302 public function preSave(EntityStorageInterface $storage) { | |
303 parent::preSave($storage); | |
304 | |
305 $media_source = $this->getSource(); | |
306 foreach ($this->translations as $langcode => $data) { | |
307 if ($this->hasTranslation($langcode)) { | |
308 $translation = $this->getTranslation($langcode); | |
309 // Try to set fields provided by the media source and mapped in | |
310 // media type config. | |
311 foreach ($translation->bundle->entity->getFieldMap() as $metadata_attribute_name => $entity_field_name) { | |
312 // Only save value in entity field if empty. Do not overwrite existing | |
313 // data. | |
314 if ($translation->hasField($entity_field_name) && ($translation->get($entity_field_name)->isEmpty() || $translation->hasSourceFieldChanged())) { | |
315 $translation->set($entity_field_name, $media_source->getMetadata($translation, $metadata_attribute_name)); | |
316 } | |
317 } | |
318 | |
319 // Try to set a default name for this media item if no name is provided. | |
320 if ($translation->get('name')->isEmpty()) { | |
321 $translation->setName($translation->getName()); | |
322 } | |
323 | |
324 // Set thumbnail. | |
325 if ($translation->shouldUpdateThumbnail()) { | |
326 $translation->updateThumbnail(); | |
327 } | |
328 } | |
329 } | |
330 } | |
331 | |
332 /** | |
333 * {@inheritdoc} | |
334 */ | |
335 public function postSave(EntityStorageInterface $storage, $update = TRUE) { | |
336 parent::postSave($storage, $update); | |
337 $is_new = !$update; | |
338 foreach ($this->translations as $langcode => $data) { | |
339 if ($this->hasTranslation($langcode)) { | |
340 $translation = $this->getTranslation($langcode); | |
341 if ($translation->bundle->entity->thumbnailDownloadsAreQueued() && $translation->shouldUpdateThumbnail($is_new)) { | |
342 \Drupal::queue('media_entity_thumbnail')->createItem(['id' => $translation->id()]); | |
343 } | |
344 } | |
345 } | |
346 } | |
347 | |
348 /** | |
349 * {@inheritdoc} | |
350 */ | |
351 public function preSaveRevision(EntityStorageInterface $storage, \stdClass $record) { | |
352 parent::preSaveRevision($storage, $record); | |
353 | |
354 $is_new_revision = $this->isNewRevision(); | |
355 if (!$is_new_revision && isset($this->original) && empty($record->revision_log_message)) { | |
356 // If we are updating an existing media item without adding a | |
357 // new revision, we need to make sure $entity->revision_log_message is | |
358 // reset whenever it is empty. | |
359 // Therefore, this code allows us to avoid clobbering an existing log | |
360 // entry with an empty one. | |
361 $record->revision_log_message = $this->original->revision_log_message->value; | |
362 } | |
363 | |
364 if ($is_new_revision) { | |
365 $record->revision_created = self::getRequestTime(); | |
366 } | |
367 } | |
368 | |
369 /** | |
370 * {@inheritdoc} | |
371 */ | |
372 public function validate() { | |
373 $media_source = $this->getSource(); | |
374 | |
375 if ($media_source instanceof MediaSourceEntityConstraintsInterface) { | |
376 $entity_constraints = $media_source->getEntityConstraints(); | |
377 $this->getTypedData()->getDataDefinition()->setConstraints($entity_constraints); | |
378 } | |
379 | |
380 if ($media_source instanceof MediaSourceFieldConstraintsInterface) { | |
381 $source_field_name = $media_source->getConfiguration()['source_field']; | |
382 $source_field_constraints = $media_source->getSourceFieldConstraints(); | |
383 $this->get($source_field_name)->getDataDefinition()->setConstraints($source_field_constraints); | |
384 } | |
385 | |
386 return parent::validate(); | |
387 } | |
388 | |
389 /** | |
390 * {@inheritdoc} | |
391 */ | |
392 public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { | |
393 $fields = parent::baseFieldDefinitions($entity_type); | |
394 | |
395 $fields['name'] = BaseFieldDefinition::create('string') | |
396 ->setLabel(t('Name')) | |
397 ->setRequired(TRUE) | |
398 ->setTranslatable(TRUE) | |
399 ->setRevisionable(TRUE) | |
400 ->setDefaultValue('') | |
401 ->setSetting('max_length', 255) | |
402 ->setDisplayOptions('form', [ | |
403 'type' => 'string_textfield', | |
404 'weight' => -5, | |
405 ]) | |
406 ->setDisplayConfigurable('form', TRUE) | |
407 ->setDisplayOptions('view', [ | |
408 'label' => 'hidden', | |
409 'type' => 'string', | |
410 'weight' => -5, | |
411 ]); | |
412 | |
413 $fields['thumbnail'] = BaseFieldDefinition::create('image') | |
414 ->setLabel(t('Thumbnail')) | |
415 ->setDescription(t('The thumbnail of the media item.')) | |
416 ->setRevisionable(TRUE) | |
417 ->setTranslatable(TRUE) | |
418 ->setDisplayOptions('view', [ | |
419 'type' => 'image', | |
420 'weight' => 5, | |
421 'label' => 'hidden', | |
422 'settings' => [ | |
423 'image_style' => 'thumbnail', | |
424 ], | |
425 ]) | |
426 ->setDisplayConfigurable('view', TRUE) | |
427 ->setReadOnly(TRUE); | |
428 | |
429 $fields['uid'] = BaseFieldDefinition::create('entity_reference') | |
430 ->setLabel(t('Authored by')) | |
431 ->setDescription(t('The user ID of the author.')) | |
432 ->setRevisionable(TRUE) | |
433 ->setDefaultValueCallback(static::class . '::getCurrentUserId') | |
434 ->setSetting('target_type', 'user') | |
435 ->setTranslatable(TRUE) | |
436 ->setDisplayOptions('form', [ | |
437 'type' => 'entity_reference_autocomplete', | |
438 'weight' => 5, | |
439 'settings' => [ | |
440 'match_operator' => 'CONTAINS', | |
441 'size' => '60', | |
442 'autocomplete_type' => 'tags', | |
443 'placeholder' => '', | |
444 ], | |
445 ]) | |
446 ->setDisplayConfigurable('form', TRUE) | |
447 ->setDisplayOptions('view', [ | |
448 'label' => 'hidden', | |
449 'type' => 'author', | |
450 'weight' => 0, | |
451 ]) | |
452 ->setDisplayConfigurable('view', TRUE); | |
453 | |
454 $fields['status'] | |
455 ->setDisplayOptions('form', [ | |
456 'type' => 'boolean_checkbox', | |
457 'settings' => [ | |
458 'display_label' => TRUE, | |
459 ], | |
460 'weight' => 100, | |
461 ]) | |
462 ->setDisplayConfigurable('form', TRUE); | |
463 | |
464 $fields['created'] = BaseFieldDefinition::create('created') | |
465 ->setLabel(t('Authored on')) | |
466 ->setDescription(t('The time the media item was created.')) | |
467 ->setTranslatable(TRUE) | |
468 ->setRevisionable(TRUE) | |
469 ->setDefaultValueCallback(static::class . '::getRequestTime') | |
470 ->setDisplayOptions('form', [ | |
471 'type' => 'datetime_timestamp', | |
472 'weight' => 10, | |
473 ]) | |
474 ->setDisplayConfigurable('form', TRUE) | |
475 ->setDisplayOptions('view', [ | |
476 'label' => 'hidden', | |
477 'type' => 'timestamp', | |
478 'weight' => 0, | |
479 ]) | |
480 ->setDisplayConfigurable('view', TRUE); | |
481 | |
482 $fields['changed'] = BaseFieldDefinition::create('changed') | |
483 ->setLabel(t('Changed')) | |
484 ->setDescription(t('The time the media item was last edited.')) | |
485 ->setTranslatable(TRUE) | |
486 ->setRevisionable(TRUE); | |
487 | |
488 return $fields; | |
489 } | |
490 | |
491 /** | |
492 * Default value callback for 'uid' base field definition. | |
493 * | |
494 * @see ::baseFieldDefinitions() | |
495 * | |
496 * @return int[] | |
497 * An array of default values. | |
498 */ | |
499 public static function getCurrentUserId() { | |
500 return [\Drupal::currentUser()->id()]; | |
501 } | |
502 | |
503 /** | |
504 * {@inheritdoc} | |
505 */ | |
506 public static function getRequestTime() { | |
507 return \Drupal::time()->getRequestTime(); | |
508 } | |
509 | |
510 } |