comparison core/modules/media/src/Entity/Media.php @ 17:129ea1e6d783

Update, including to Drupal core 8.6.10
author Chris Cannam
date Thu, 28 Feb 2019 13:21:36 +0000
parents 1fec387a4317
children af1871eacc83
comparison
equal deleted inserted replaced
16:c2387f117808 17:129ea1e6d783
27 * singular = "@count media item", 27 * singular = "@count media item",
28 * plural = "@count media items" 28 * plural = "@count media items"
29 * ), 29 * ),
30 * bundle_label = @Translation("Media type"), 30 * bundle_label = @Translation("Media type"),
31 * handlers = { 31 * handlers = {
32 * "storage" = "Drupal\Core\Entity\Sql\SqlContentEntityStorage", 32 * "storage" = "Drupal\media\MediaStorage",
33 * "view_builder" = "Drupal\Core\Entity\EntityViewBuilder", 33 * "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
34 * "list_builder" = "Drupal\media\MediaListBuilder", 34 * "list_builder" = "Drupal\media\MediaListBuilder",
35 * "access" = "Drupal\media\MediaAccessControlHandler", 35 * "access" = "Drupal\media\MediaAccessControlHandler",
36 * "form" = { 36 * "form" = {
37 * "default" = "Drupal\media\MediaForm", 37 * "default" = "Drupal\media\MediaForm",
38 * "add" = "Drupal\media\MediaForm", 38 * "add" = "Drupal\media\MediaForm",
39 * "edit" = "Drupal\media\MediaForm", 39 * "edit" = "Drupal\media\MediaForm",
40 * "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm", 40 * "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm",
41 * "delete-multiple-confirm" = "Drupal\Core\Entity\Form\DeleteMultipleForm",
41 * }, 42 * },
42 * "translation" = "Drupal\content_translation\ContentTranslationHandler", 43 * "translation" = "Drupal\content_translation\ContentTranslationHandler",
43 * "views_data" = "Drupal\media\MediaViewsData", 44 * "views_data" = "Drupal\media\MediaViewsData",
44 * "route_provider" = { 45 * "route_provider" = {
45 * "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider", 46 * "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider",
74 * "add-page" = "/media/add", 75 * "add-page" = "/media/add",
75 * "add-form" = "/media/add/{media_type}", 76 * "add-form" = "/media/add/{media_type}",
76 * "canonical" = "/media/{media}", 77 * "canonical" = "/media/{media}",
77 * "collection" = "/admin/content/media", 78 * "collection" = "/admin/content/media",
78 * "delete-form" = "/media/{media}/delete", 79 * "delete-form" = "/media/{media}/delete",
80 * "delete-multiple-form" = "/media/delete",
79 * "edit-form" = "/media/{media}/edit", 81 * "edit-form" = "/media/{media}/edit",
80 * "revision" = "/media/{media}/revisions/{media_revision}/view", 82 * "revision" = "/media/{media}/revisions/{media_revision}/view",
81 * } 83 * }
82 * ) 84 * )
83 */ 85 */
87 89
88 /** 90 /**
89 * {@inheritdoc} 91 * {@inheritdoc}
90 */ 92 */
91 public function getName() { 93 public function getName() {
92 $name = $this->get('name'); 94 $name = $this->getEntityKey('label');
93 95
94 if ($name->isEmpty()) { 96 if (empty($name)) {
95 $media_source = $this->getSource(); 97 $media_source = $this->getSource();
96 return $media_source->getMetadata($this, $media_source->getPluginDefinition()['default_name_metadata_attribute']); 98 return $media_source->getMetadata($this, $media_source->getPluginDefinition()['default_name_metadata_attribute']);
97 } 99 }
98 else { 100
99 return $name->value; 101 return $name;
100 }
101 } 102 }
102 103
103 /** 104 /**
104 * {@inheritdoc} 105 * {@inheritdoc}
105 */ 106 */
177 * @todo There has been some disagreement about how to handle updates to 178 * @todo There has been some disagreement about how to handle updates to
178 * thumbnails. We need to decide on what the API will be for this. 179 * thumbnails. We need to decide on what the API will be for this.
179 * https://www.drupal.org/node/2878119 180 * https://www.drupal.org/node/2878119
180 */ 181 */
181 protected function updateThumbnail($from_queue = FALSE) { 182 protected function updateThumbnail($from_queue = FALSE) {
182 $file_storage = \Drupal::service('entity_type.manager')->getStorage('file'); 183 $this->thumbnail->target_id = $this->loadThumbnail($this->getThumbnailUri($from_queue))->id();
183 $thumbnail_uri = $this->getThumbnailUri($from_queue); 184
184 $existing = $file_storage->getQuery() 185 // Set the thumbnail alt.
185 ->condition('uri', $thumbnail_uri) 186 $media_source = $this->getSource();
186 ->execute(); 187 $plugin_definition = $media_source->getPluginDefinition();
187 188
189 $this->thumbnail->alt = '';
190 if (!empty($plugin_definition['thumbnail_alt_metadata_attribute'])) {
191 $this->thumbnail->alt = $media_source->getMetadata($this, $plugin_definition['thumbnail_alt_metadata_attribute']);
192 }
193
194 return $this;
195 }
196
197 /**
198 * Loads the file entity for the thumbnail.
199 *
200 * If the file entity does not exist, it will be created.
201 *
202 * @param string $thumbnail_uri
203 * (optional) The URI of the thumbnail, used to load or create the file
204 * entity. If omitted, the default thumbnail URI will be used.
205 *
206 * @return \Drupal\file\FileInterface
207 * The thumbnail file entity.
208 */
209 protected function loadThumbnail($thumbnail_uri = NULL) {
210 $values = [
211 'uri' => $thumbnail_uri ?: $this->getDefaultThumbnailUri(),
212 ];
213
214 $file_storage = $this->entityTypeManager()->getStorage('file');
215
216 $existing = $file_storage->loadByProperties($values);
188 if ($existing) { 217 if ($existing) {
189 $this->thumbnail->target_id = reset($existing); 218 $file = reset($existing);
190 } 219 }
191 else { 220 else {
192 /** @var \Drupal\file\FileInterface $file */ 221 /** @var \Drupal\file\FileInterface $file */
193 $file = $file_storage->create(['uri' => $thumbnail_uri]); 222 $file = $file_storage->create($values);
194 if ($owner = $this->getOwner()) { 223 if ($owner = $this->getOwner()) {
195 $file->setOwner($owner); 224 $file->setOwner($owner);
196 } 225 }
197 $file->setPermanent(); 226 $file->setPermanent();
198 $file->save(); 227 $file->save();
199 $this->thumbnail->target_id = $file->id(); 228 }
200 } 229 return $file;
201 230 }
202 // Set the thumbnail alt. 231
203 $media_source = $this->getSource(); 232 /**
204 $plugin_definition = $media_source->getPluginDefinition(); 233 * Returns the URI of the default thumbnail.
205 if (!empty($plugin_definition['thumbnail_alt_metadata_attribute'])) { 234 *
206 $this->thumbnail->alt = $media_source->getMetadata($this, $plugin_definition['thumbnail_alt_metadata_attribute']); 235 * @return string
207 } 236 * The default thumbnail URI.
208 else { 237 */
209 $this->thumbnail->alt = $this->t('Thumbnail', [], ['langcode' => $this->langcode->value]); 238 protected function getDefaultThumbnailUri() {
210 } 239 $default_thumbnail_filename = $this->getSource()->getPluginDefinition()['default_thumbnail_filename'];
211 240 return \Drupal::config('media.settings')->get('icon_base_uri') . '/' . $default_thumbnail_filename;
212 // Set the thumbnail title.
213 if (!empty($plugin_definition['thumbnail_title_metadata_attribute'])) {
214 $this->thumbnail->title = $media_source->getMetadata($this, $plugin_definition['thumbnail_title_metadata_attribute']);
215 }
216 else {
217 $this->thumbnail->title = $this->label();
218 }
219
220 return $this;
221 } 241 }
222 242
223 /** 243 /**
224 * Updates the queued thumbnail for the media item. 244 * Updates the queued thumbnail for the media item.
225 * 245 *
253 * @internal 273 * @internal
254 */ 274 */
255 protected function getThumbnailUri($from_queue) { 275 protected function getThumbnailUri($from_queue) {
256 $thumbnails_queued = $this->bundle->entity->thumbnailDownloadsAreQueued(); 276 $thumbnails_queued = $this->bundle->entity->thumbnailDownloadsAreQueued();
257 if ($thumbnails_queued && $this->isNew()) { 277 if ($thumbnails_queued && $this->isNew()) {
258 $default_thumbnail_filename = $this->getSource()->getPluginDefinition()['default_thumbnail_filename']; 278 return $this->getDefaultThumbnailUri();
259 $thumbnail_uri = \Drupal::service('config.factory')->get('media.settings')->get('icon_base_uri') . '/' . $default_thumbnail_filename;
260 } 279 }
261 elseif ($thumbnails_queued && !$from_queue) { 280 elseif ($thumbnails_queued && !$from_queue) {
262 $thumbnail_uri = $this->get('thumbnail')->entity->getFileUri(); 281 return $this->get('thumbnail')->entity->getFileUri();
263 } 282 }
264 else { 283
265 $thumbnail_uri = $this->getSource()->getMetadata($this, $this->getSource()->getPluginDefinition()['thumbnail_uri_metadata_attribute']); 284 $source = $this->getSource();
266 } 285 return $source->getMetadata($this, $source->getPluginDefinition()['thumbnail_uri_metadata_attribute']);
267
268 return $thumbnail_uri;
269 } 286 }
270 287
271 /** 288 /**
272 * Determines if the source field value has changed. 289 * Determines if the source field value has changed.
273 * 290 *
300 /** 317 /**
301 * {@inheritdoc} 318 * {@inheritdoc}
302 */ 319 */
303 public function preSave(EntityStorageInterface $storage) { 320 public function preSave(EntityStorageInterface $storage) {
304 parent::preSave($storage); 321 parent::preSave($storage);
322
323 // If no thumbnail has been explicitly set, use the default thumbnail.
324 if ($this->get('thumbnail')->isEmpty()) {
325 $this->thumbnail->target_id = $this->loadThumbnail()->id();
326 }
327 }
328
329 /**
330 * {@inheritdoc}
331 */
332 public function postSave(EntityStorageInterface $storage, $update = TRUE) {
333 parent::postSave($storage, $update);
334 $is_new = !$update;
335 foreach ($this->translations as $langcode => $data) {
336 if ($this->hasTranslation($langcode)) {
337 $translation = $this->getTranslation($langcode);
338 if ($translation->bundle->entity->thumbnailDownloadsAreQueued() && $translation->shouldUpdateThumbnail($is_new)) {
339 \Drupal::queue('media_entity_thumbnail')->createItem(['id' => $translation->id()]);
340 }
341 }
342 }
343 }
344
345 /**
346 * {@inheritdoc}
347 */
348 public function preSaveRevision(EntityStorageInterface $storage, \stdClass $record) {
349 parent::preSaveRevision($storage, $record);
350
351 $is_new_revision = $this->isNewRevision();
352 if (!$is_new_revision && isset($this->original) && empty($record->revision_log_message)) {
353 // If we are updating an existing media item without adding a
354 // new revision, we need to make sure $entity->revision_log_message is
355 // reset whenever it is empty.
356 // Therefore, this code allows us to avoid clobbering an existing log
357 // entry with an empty one.
358 $record->revision_log_message = $this->original->revision_log_message->value;
359 }
360
361 if ($is_new_revision) {
362 $record->revision_created = self::getRequestTime();
363 }
364 }
365
366 /**
367 * Sets the media entity's field values from the source's metadata.
368 *
369 * Fetching the metadata could be slow (e.g., if requesting it from a remote
370 * API), so this is called by \Drupal\media\MediaStorage::save() prior to it
371 * beginning the database transaction, whereas static::preSave() executes
372 * after the transaction has already started.
373 *
374 * @internal
375 * Expose this as an API in
376 * https://www.drupal.org/project/drupal/issues/2992426.
377 */
378 public function prepareSave() {
379 // @todo If the source plugin talks to a remote API (e.g. oEmbed), this code
380 // might be performing a fair number of HTTP requests. This is dangerously
381 // brittle and should probably be handled by a queue, to avoid doing HTTP
382 // operations during entity save. See
383 // https://www.drupal.org/project/drupal/issues/2976875 for more.
384
385 // In order for metadata to be mapped correctly, $this->original must be
386 // set. However, that is only set once parent::save() is called, so work
387 // around that by setting it here.
388 if (!isset($this->original) && $id = $this->id()) {
389 $this->original = $this->entityTypeManager()
390 ->getStorage('media')
391 ->loadUnchanged($id);
392 }
305 393
306 $media_source = $this->getSource(); 394 $media_source = $this->getSource();
307 foreach ($this->translations as $langcode => $data) { 395 foreach ($this->translations as $langcode => $data) {
308 if ($this->hasTranslation($langcode)) { 396 if ($this->hasTranslation($langcode)) {
309 $translation = $this->getTranslation($langcode); 397 $translation = $this->getTranslation($langcode);
321 if ($translation->get('name')->isEmpty()) { 409 if ($translation->get('name')->isEmpty()) {
322 $translation->setName($translation->getName()); 410 $translation->setName($translation->getName());
323 } 411 }
324 412
325 // Set thumbnail. 413 // Set thumbnail.
326 if ($translation->shouldUpdateThumbnail()) { 414 if ($translation->shouldUpdateThumbnail($this->isNew())) {
327 $translation->updateThumbnail(); 415 $translation->updateThumbnail();
328 } 416 }
329 } 417 }
330 }
331 }
332
333 /**
334 * {@inheritdoc}
335 */
336 public function postSave(EntityStorageInterface $storage, $update = TRUE) {
337 parent::postSave($storage, $update);
338 $is_new = !$update;
339 foreach ($this->translations as $langcode => $data) {
340 if ($this->hasTranslation($langcode)) {
341 $translation = $this->getTranslation($langcode);
342 if ($translation->bundle->entity->thumbnailDownloadsAreQueued() && $translation->shouldUpdateThumbnail($is_new)) {
343 \Drupal::queue('media_entity_thumbnail')->createItem(['id' => $translation->id()]);
344 }
345 }
346 }
347 }
348
349 /**
350 * {@inheritdoc}
351 */
352 public function preSaveRevision(EntityStorageInterface $storage, \stdClass $record) {
353 parent::preSaveRevision($storage, $record);
354
355 $is_new_revision = $this->isNewRevision();
356 if (!$is_new_revision && isset($this->original) && empty($record->revision_log_message)) {
357 // If we are updating an existing media item without adding a
358 // new revision, we need to make sure $entity->revision_log_message is
359 // reset whenever it is empty.
360 // Therefore, this code allows us to avoid clobbering an existing log
361 // entry with an empty one.
362 $record->revision_log_message = $this->original->revision_log_message->value;
363 }
364
365 if ($is_new_revision) {
366 $record->revision_created = self::getRequestTime();
367 } 418 }
368 } 419 }
369 420
370 /** 421 /**
371 * {@inheritdoc} 422 * {@inheritdoc}