Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / web / core / modules / media / src / Entity / Media.php
index 6e58771938840cf3d772b54f8f08b2fd66df76a3..c21821077bcb23446f34ecaacccb236e8b90360d 100644 (file)
@@ -29,7 +29,7 @@ use Drupal\user\UserInterface;
  *   ),
  *   bundle_label = @Translation("Media type"),
  *   handlers = {
- *     "storage" = "Drupal\Core\Entity\Sql\SqlContentEntityStorage",
+ *     "storage" = "Drupal\media\MediaStorage",
  *     "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
  *     "list_builder" = "Drupal\media\MediaListBuilder",
  *     "access" = "Drupal\media\MediaAccessControlHandler",
@@ -38,6 +38,7 @@ use Drupal\user\UserInterface;
  *       "add" = "Drupal\media\MediaForm",
  *       "edit" = "Drupal\media\MediaForm",
  *       "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm",
+ *       "delete-multiple-confirm" = "Drupal\Core\Entity\Form\DeleteMultipleForm",
  *     },
  *     "translation" = "Drupal\content_translation\ContentTranslationHandler",
  *     "views_data" = "Drupal\media\MediaViewsData",
@@ -76,6 +77,7 @@ use Drupal\user\UserInterface;
  *     "canonical" = "/media/{media}",
  *     "collection" = "/admin/content/media",
  *     "delete-form" = "/media/{media}/delete",
+ *     "delete-multiple-form" = "/media/delete",
  *     "edit-form" = "/media/{media}/edit",
  *     "revision" = "/media/{media}/revisions/{media_revision}/view",
  *   }
@@ -89,15 +91,14 @@ class Media extends EditorialContentEntityBase implements MediaInterface {
    * {@inheritdoc}
    */
   public function getName() {
-    $name = $this->get('name');
+    $name = $this->getEntityKey('label');
 
-    if ($name->isEmpty()) {
+    if (empty($name)) {
       $media_source = $this->getSource();
       return $media_source->getMetadata($this, $media_source->getPluginDefinition()['default_name_metadata_attribute']);
     }
-    else {
-      return $name->value;
-    }
+
+    return $name;
   }
 
   /**
@@ -179,25 +180,7 @@ class Media extends EditorialContentEntityBase implements MediaInterface {
    *   https://www.drupal.org/node/2878119
    */
   protected function updateThumbnail($from_queue = FALSE) {
-    $file_storage = \Drupal::service('entity_type.manager')->getStorage('file');
-    $thumbnail_uri = $this->getThumbnailUri($from_queue);
-    $existing = $file_storage->getQuery()
-      ->condition('uri', $thumbnail_uri)
-      ->execute();
-
-    if ($existing) {
-      $this->thumbnail->target_id = reset($existing);
-    }
-    else {
-      /** @var \Drupal\file\FileInterface $file */
-      $file = $file_storage->create(['uri' => $thumbnail_uri]);
-      if ($owner = $this->getOwner()) {
-        $file->setOwner($owner);
-      }
-      $file->setPermanent();
-      $file->save();
-      $this->thumbnail->target_id = $file->id();
-    }
+    $this->thumbnail->target_id = $this->loadThumbnail($this->getThumbnailUri($from_queue))->id();
 
     // Set the thumbnail alt.
     $media_source = $this->getSource();
@@ -220,6 +203,52 @@ class Media extends EditorialContentEntityBase implements MediaInterface {
     return $this;
   }
 
+  /**
+   * Loads the file entity for the thumbnail.
+   *
+   * If the file entity does not exist, it will be created.
+   *
+   * @param string $thumbnail_uri
+   *   (optional) The URI of the thumbnail, used to load or create the file
+   *   entity. If omitted, the default thumbnail URI will be used.
+   *
+   * @return \Drupal\file\FileInterface
+   *   The thumbnail file entity.
+   */
+  protected function loadThumbnail($thumbnail_uri = NULL) {
+    $values = [
+      'uri' => $thumbnail_uri ?: $this->getDefaultThumbnailUri(),
+    ];
+
+    $file_storage = $this->entityTypeManager()->getStorage('file');
+
+    $existing = $file_storage->loadByProperties($values);
+    if ($existing) {
+      $file = reset($existing);
+    }
+    else {
+      /** @var \Drupal\file\FileInterface $file */
+      $file = $file_storage->create($values);
+      if ($owner = $this->getOwner()) {
+        $file->setOwner($owner);
+      }
+      $file->setPermanent();
+      $file->save();
+    }
+    return $file;
+  }
+
+  /**
+   * Returns the URI of the default thumbnail.
+   *
+   * @return string
+   *   The default thumbnail URI.
+   */
+  protected function getDefaultThumbnailUri() {
+    $default_thumbnail_filename = $this->getSource()->getPluginDefinition()['default_thumbnail_filename'];
+    return \Drupal::config('media.settings')->get('icon_base_uri') . '/' . $default_thumbnail_filename;
+  }
+
   /**
    * Updates the queued thumbnail for the media item.
    *
@@ -255,17 +284,14 @@ class Media extends EditorialContentEntityBase implements MediaInterface {
   protected function getThumbnailUri($from_queue) {
     $thumbnails_queued = $this->bundle->entity->thumbnailDownloadsAreQueued();
     if ($thumbnails_queued && $this->isNew()) {
-      $default_thumbnail_filename = $this->getSource()->getPluginDefinition()['default_thumbnail_filename'];
-      $thumbnail_uri = \Drupal::service('config.factory')->get('media.settings')->get('icon_base_uri') . '/' . $default_thumbnail_filename;
+      return $this->getDefaultThumbnailUri();
     }
     elseif ($thumbnails_queued && !$from_queue) {
-      $thumbnail_uri = $this->get('thumbnail')->entity->getFileUri();
-    }
-    else {
-      $thumbnail_uri = $this->getSource()->getMetadata($this, $this->getSource()->getPluginDefinition()['thumbnail_uri_metadata_attribute']);
+      return $this->get('thumbnail')->entity->getFileUri();
     }
 
-    return $thumbnail_uri;
+    $source = $this->getSource();
+    return $source->getMetadata($this, $source->getPluginDefinition()['thumbnail_uri_metadata_attribute']);
   }
 
   /**
@@ -303,30 +329,9 @@ class Media extends EditorialContentEntityBase implements MediaInterface {
   public function preSave(EntityStorageInterface $storage) {
     parent::preSave($storage);
 
-    $media_source = $this->getSource();
-    foreach ($this->translations as $langcode => $data) {
-      if ($this->hasTranslation($langcode)) {
-        $translation = $this->getTranslation($langcode);
-        // Try to set fields provided by the media source and mapped in
-        // media type config.
-        foreach ($translation->bundle->entity->getFieldMap() as $metadata_attribute_name => $entity_field_name) {
-          // Only save value in entity field if empty. Do not overwrite existing
-          // data.
-          if ($translation->hasField($entity_field_name) && ($translation->get($entity_field_name)->isEmpty() || $translation->hasSourceFieldChanged())) {
-            $translation->set($entity_field_name, $media_source->getMetadata($translation, $metadata_attribute_name));
-          }
-        }
-
-        // Try to set a default name for this media item if no name is provided.
-        if ($translation->get('name')->isEmpty()) {
-          $translation->setName($translation->getName());
-        }
-
-        // Set thumbnail.
-        if ($translation->shouldUpdateThumbnail()) {
-          $translation->updateThumbnail();
-        }
-      }
+    // If no thumbnail has been explicitly set, use the default thumbnail.
+    if ($this->get('thumbnail')->isEmpty()) {
+      $this->thumbnail->target_id = $this->loadThumbnail()->id();
     }
   }
 
@@ -367,6 +372,61 @@ class Media extends EditorialContentEntityBase implements MediaInterface {
     }
   }
 
+  /**
+   * Sets the media entity's field values from the source's metadata.
+   *
+   * Fetching the metadata could be slow (e.g., if requesting it from a remote
+   * API), so this is called by \Drupal\media\MediaStorage::save() prior to it
+   * beginning the database transaction, whereas static::preSave() executes
+   * after the transaction has already started.
+   *
+   * @internal
+   *   Expose this as an API in
+   *   https://www.drupal.org/project/drupal/issues/2992426.
+   */
+  public function prepareSave() {
+    // @todo If the source plugin talks to a remote API (e.g. oEmbed), this code
+    // might be performing a fair number of HTTP requests. This is dangerously
+    // brittle and should probably be handled by a queue, to avoid doing HTTP
+    // operations during entity save. See
+    // https://www.drupal.org/project/drupal/issues/2976875 for more.
+
+    // In order for metadata to be mapped correctly, $this->original must be
+    // set. However, that is only set once parent::save() is called, so work
+    // around that by setting it here.
+    if (!isset($this->original) && $id = $this->id()) {
+      $this->original = $this->entityTypeManager()
+        ->getStorage('media')
+        ->loadUnchanged($id);
+    }
+
+    $media_source = $this->getSource();
+    foreach ($this->translations as $langcode => $data) {
+      if ($this->hasTranslation($langcode)) {
+        $translation = $this->getTranslation($langcode);
+        // Try to set fields provided by the media source and mapped in
+        // media type config.
+        foreach ($translation->bundle->entity->getFieldMap() as $metadata_attribute_name => $entity_field_name) {
+          // Only save value in entity field if empty. Do not overwrite existing
+          // data.
+          if ($translation->hasField($entity_field_name) && ($translation->get($entity_field_name)->isEmpty() || $translation->hasSourceFieldChanged())) {
+            $translation->set($entity_field_name, $media_source->getMetadata($translation, $metadata_attribute_name));
+          }
+        }
+
+        // Try to set a default name for this media item if no name is provided.
+        if ($translation->get('name')->isEmpty()) {
+          $translation->setName($translation->getName());
+        }
+
+        // Set thumbnail.
+        if ($translation->shouldUpdateThumbnail($this->isNew())) {
+          $translation->updateThumbnail();
+        }
+      }
+    }
+  }
+
   /**
    * {@inheritdoc}
    */