Updating Media dependent modules to versions compatible with core Media.
[yaffs-website] / web / modules / contrib / media_entity_twitter / src / Plugin / media / Source / Twitter.php
similarity index 58%
rename from web/modules/contrib/media_entity_twitter/src/Plugin/MediaEntity/Type/Twitter.php
rename to web/modules/contrib/media_entity_twitter/src/Plugin/media/Source/Twitter.php
index ce93d30b0a114cd6dbc7d24bec4730dfa6fd9c15..38fdf83324aeae75f710b7acd779e59ef929a90e 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 
-namespace Drupal\media_entity_twitter\Plugin\MediaEntity\Type;
+namespace Drupal\media_entity_twitter\Plugin\media\Source;
 
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Entity\EntityFieldManagerInterface;
@@ -8,29 +8,26 @@ use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Logger\LoggerChannelInterface;
 use Drupal\Core\Render\RendererInterface;
-use Drupal\media_entity\MediaInterface;
-use Drupal\media_entity\MediaTypeBase;
-use Drupal\media_entity\MediaTypeException;
+use Drupal\media\MediaInterface;
+use Drupal\media\MediaSourceBase;
+use Drupal\media\MediaTypeInterface;
 use Drupal\media_entity_twitter\TweetFetcherInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\Core\Field\FieldTypePluginManagerInterface;
+use Drupal\media\MediaSourceFieldConstraintsInterface;
 
 /**
- * Provides media type plugin for Twitter.
+ * Twitter entity media source.
  *
- * @MediaType(
+ * @MediaSource(
  *   id = "twitter",
  *   label = @Translation("Twitter"),
+ *   allowed_field_types = {"string", "string_long", "link"},
+ *   default_thumbnail_filename = "twitter.png",
  *   description = @Translation("Provides business logic and metadata for Twitter.")
  * )
  */
-class Twitter extends MediaTypeBase {
-
-  /**
-   * Config factory service.
-   *
-   * @var \Drupal\Core\Config\ConfigFactoryInterface
-   */
-  protected $configFactory;
+class Twitter extends MediaSourceBase implements MediaSourceFieldConstraintsInterface {
 
   /**
    * The renderer.
@@ -63,6 +60,7 @@ class Twitter extends MediaTypeBase {
       $plugin_definition,
       $container->get('entity_type.manager'),
       $container->get('entity_field.manager'),
+      $container->get('plugin.manager.field.field_type'),
       $container->get('config.factory'),
       $container->get('renderer'),
       $container->get('media_entity_twitter.tweet_fetcher'),
@@ -75,9 +73,9 @@ class Twitter extends MediaTypeBase {
    *
    * @var array
    */
-  public static $validationRegexp = array(
+  public static $validationRegexp = [
     '@((http|https):){0,1}//(www\.){0,1}twitter\.com/(?<user>[a-z0-9_-]+)/(status(es){0,1})/(?<id>[\d]+)@i' => 'id',
-  );
+  ];
 
   /**
    * Constructs a new class instance.
@@ -92,6 +90,8 @@ class Twitter extends MediaTypeBase {
    *   Entity type manager service.
    * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
    *   Entity field manager service.
+   * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager
+   *   Config field type manager service.
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
    *   Config factory service.
    * @param \Drupal\Core\Render\RendererInterface $renderer
@@ -101,9 +101,8 @@ class Twitter extends MediaTypeBase {
    * @param \Drupal\Core\Logger\LoggerChannelInterface $logger
    *   The logger channel.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, ConfigFactoryInterface $config_factory, RendererInterface $renderer, TweetFetcherInterface $tweet_fetcher, LoggerChannelInterface $logger) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $entity_field_manager, $config_factory->get('media_entity.settings'));
-    $this->configFactory = $config_factory;
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, FieldTypePluginManagerInterface $field_type_manager, ConfigFactoryInterface $config_factory, RendererInterface $renderer, TweetFetcherInterface $tweet_fetcher, LoggerChannelInterface $logger) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $entity_field_manager, $field_type_manager, $config_factory);
     $this->renderer = $renderer;
     $this->tweetFetcher = $tweet_fetcher;
     $this->logger = $logger;
@@ -114,74 +113,107 @@ class Twitter extends MediaTypeBase {
    */
   public function defaultConfiguration() {
     return [
+      'source_field' => '',
       'use_twitter_api' => FALSE,
       'generate_thumbnails' => FALSE,
+      'consumer_key' => '',
+      'consumer_secret' => '',
+      'oauth_access_token' => '',
+      'oauth_access_token_secret' => '',
     ];
   }
 
   /**
    * {@inheritdoc}
    */
-  public function providedFields() {
-    $fields = array(
+  public function getMetadataAttributes() {
+    $attributes = [
       'id' => $this->t('Tweet ID'),
       'user' => $this->t('Twitter user information'),
-    );
+    ];
 
     if ($this->configuration['use_twitter_api']) {
-      $fields += array(
+      $attributes += [
         'image' => $this->t('Link to the twitter image'),
         'image_local' => $this->t('Copies tweet image to the local filesystem and returns the URI.'),
         'image_local_uri' => $this->t('Gets URI of the locally saved image.'),
         'content' => $this->t('This tweet content'),
         'retweet_count' => $this->t('Retweet count for this tweet'),
-        'profile_image_url_https' => $this->t('Link to profile image')
-      );
+        'profile_image_url_https' => $this->t('Link to profile image'),
+      ];
     }
 
-    return $fields;
+    return $attributes;
   }
 
   /**
    * {@inheritdoc}
    */
-  public function getField(MediaInterface $media, $name) {
+  public function getMetadata(MediaInterface $media, $attribute_name) {
     $matches = $this->matchRegexp($media);
 
     if (!$matches['id']) {
-      return FALSE;
+      return NULL;
     }
 
     // First we return the fields that are available from regex.
-    switch ($name) {
+    switch ($attribute_name) {
       case 'id':
         return $matches['id'];
 
       case 'user':
-        if ($matches['user']) {
-          return $matches['user'];
+        return $matches['user'] ?: NULL;
+
+      case 'thumbnail_uri':
+        // If there's already a local image, use it.
+        if ($local_image = $this->getMetadata($media, 'image_local')) {
+          return $local_image;
+        }
+
+        // If thumbnail generation is disabled, use the default thumbnail.
+        if (empty($this->configuration['generate_thumbnails'])) {
+          return parent::getMetadata($media, $attribute_name);
+        }
+
+        // We might need to generate a thumbnail...
+        $id = $this->getMetadata($media, 'id');
+        $thumbnail_uri = $this->getLocalImageUri($id, $media);
+
+        // ...unless we already have, in which case, use it.
+        if (file_exists($thumbnail_uri)) {
+          return $thumbnail_uri;
         }
-        return FALSE;
+
+        // Render the thumbnail SVG using the theme system.
+        $thumbnail = [
+          '#theme' => 'media_entity_twitter_tweet_thumbnail',
+          '#content' => $this->getMetadata($media, 'content'),
+          '#author' => $this->getMetadata($media, 'user'),
+          '#avatar' => $this->getMetadata($media, 'profile_image_url_https'),
+        ];
+        $svg = $this->renderer->renderRoot($thumbnail);
+
+        return file_unmanaged_save_data($svg, $thumbnail_uri, FILE_EXISTS_ERROR) ?: parent::getMetadata($media, $attribute_name);
     }
 
     // If we have auth settings return the other fields.
     if ($this->configuration['use_twitter_api'] && $tweet = $this->fetchTweet($matches['id'])) {
-      switch ($name) {
+      switch ($attribute_name) {
         case 'image':
           if (isset($tweet['extended_entities']['media'][0]['media_url'])) {
             return $tweet['extended_entities']['media'][0]['media_url'];
           }
-          return FALSE;
+          return NULL;
 
         case 'image_local':
-          $local_uri = $this->getField($media, 'image_local_uri');
+          $local_uri = $this->getMetadata($media, 'image_local_uri');
 
           if ($local_uri) {
             if (file_exists($local_uri)) {
               return $local_uri;
             }
             else {
-              $image_url = $this->getField($media, 'image');
+              $image_url = $this->getMetadata($media, 'image');
               // @TODO: Use Guzzle, possibly in a service, for this.
               $image_data = file_get_contents($image_url);
               if ($image_data) {
@@ -189,115 +221,107 @@ class Twitter extends MediaTypeBase {
               }
             }
           }
-          return FALSE;
+          return NULL;
 
         case 'image_local_uri':
-          $image_url = $this->getField($media, 'image');
+          $image_url = $this->getMetadata($media, 'image');
           if ($image_url) {
-            return $this->getLocalImageUri($matches['id'], $image_url);
+            return $this->getLocalImageUri($matches['id'], $media, $image_url);
           }
-          return FALSE;
+          return NULL;
 
         case 'content':
           if (isset($tweet['text'])) {
             return $tweet['text'];
           }
-          return FALSE;
+          return NULL;
 
         case 'retweet_count':
           if (isset($tweet['retweet_count'])) {
             return $tweet['retweet_count'];
           }
-          return FALSE;
+          return NULL;
 
         case 'profile_image_url_https':
           if (isset($tweet['user']['profile_image_url_https'])) {
             return $tweet['user']['profile_image_url_https'];
           }
-          return FALSE;
+          return NULL;
+
+        case 'default_name':
+          $user = $this->getMetadata($media, 'user');
+          $id = $this->getMetadata($media, 'id');
+          if (!empty($user) && !empty($id)) {
+            return $user . ' - ' . $id;
+          }
+          return NULL;
       }
     }
 
-    return FALSE;
+    return NULL;
   }
 
   /**
    * {@inheritdoc}
    */
   public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
-    $options = [];
-    $allowed_field_types = ['string', 'string_long', 'link'];
-    /** @var \Drupal\media_entity\MediaBundleInterface $bundle */
-    $bundle = $form_state->getFormObject()->getEntity();
-    foreach ($this->entityFieldManager->getFieldDefinitions('media', $bundle->id()) as $field_name => $field) {
-      if (in_array($field->getType(), $allowed_field_types) && !$field->getFieldStorageDefinition()->isBaseField()) {
-        $options[$field_name] = $field->getLabel();
-      }
-    }
+    $form = parent::buildConfigurationForm($form, $form_state);
 
-    $form['source_field'] = array(
-      '#type' => 'select',
-      '#title' => $this->t('Field with source information'),
-      '#description' => $this->t('Field on media entity that stores Twitter embed code or URL. You can create a bundle without selecting a value for this dropdown initially. This dropdown can be populated after adding fields to the bundle.'),
-      '#default_value' => empty($this->configuration['source_field']) ? NULL : $this->configuration['source_field'],
-      '#options' => $options,
-    );
-
-    $form['use_twitter_api'] = array(
+    $form['use_twitter_api'] = [
       '#type' => 'select',
       '#title' => $this->t('Whether to use Twitter api to fetch tweets or not.'),
       '#description' => $this->t("In order to use Twitter's api you have to create a developer account and an application. For more information consult the readme file."),
       '#default_value' => empty($this->configuration['use_twitter_api']) ? 0 : $this->configuration['use_twitter_api'],
-      '#options' => array(
+      '#options' => [
         0 => $this->t('No'),
         1 => $this->t('Yes'),
-      ),
-    );
+      ],
+    ];
 
-    // @todo Evauate if this should be a site-wide configuration.
-    $form['consumer_key'] = array(
+    // @todo: Evaluate if this should be a site-wide configuration.
+    $form['consumer_key'] = [
       '#type' => 'textfield',
       '#title' => $this->t('Consumer key'),
       '#default_value' => empty($this->configuration['consumer_key']) ? NULL : $this->configuration['consumer_key'],
-      '#states' => array(
-        'visible' => array(
-          ':input[name="type_configuration[twitter][use_twitter_api]"]' => array('value' => '1'),
-        ),
-      ),
-    );
+      '#states' => [
+        'visible' => [
+          ':input[name="source_configuration[use_twitter_api]"]' => ['value' => '1'],
+        ],
+      ],
+    ];
 
-    $form['consumer_secret'] = array(
+    $form['consumer_secret'] = [
       '#type' => 'textfield',
       '#title' => $this->t('Consumer secret'),
       '#default_value' => empty($this->configuration['consumer_secret']) ? NULL : $this->configuration['consumer_secret'],
-      '#states' => array(
-        'visible' => array(
-          ':input[name="type_configuration[twitter][use_twitter_api]"]' => array('value' => '1'),
-        ),
-      ),
-    );
+      '#states' => [
+        'visible' => [
+          ':input[name="source_configuration[use_twitter_api]"]' => ['value' => '1'],
+        ],
+      ],
+    ];
 
-    $form['oauth_access_token'] = array(
+    $form['oauth_access_token'] = [
       '#type' => 'textfield',
       '#title' => $this->t('Oauth access token'),
       '#default_value' => empty($this->configuration['oauth_access_token']) ? NULL : $this->configuration['oauth_access_token'],
-      '#states' => array(
-        'visible' => array(
-          ':input[name="type_configuration[twitter][use_twitter_api]"]' => array('value' => '1'),
-        ),
-      ),
-    );
+      '#states' => [
+        'visible' => [
+          ':input[name="source_configuration[use_twitter_api]"]' => ['value' => '1'],
+        ],
+      ],
+    ];
 
-    $form['oauth_access_token_secret'] = array(
+    $form['oauth_access_token_secret'] = [
       '#type' => 'textfield',
       '#title' => $this->t('Oauth access token secret'),
       '#default_value' => empty($this->configuration['oauth_access_token_secret']) ? NULL : $this->configuration['oauth_access_token_secret'],
-      '#states' => array(
-        'visible' => array(
-          ':input[name="type_configuration[twitter][use_twitter_api]"]' => array('value' => '1'),
-        ),
-      ),
-    );
+      '#states' => [
+        'visible' => [
+          ':input[name="source_configuration[use_twitter_api]"]' => ['value' => '1'],
+        ],
+      ],
+    ];
 
     $form['generate_thumbnails'] = [
       '#type' => 'checkbox',
@@ -305,7 +329,7 @@ class Twitter extends MediaTypeBase {
       '#default_value' => $this->configuration['generate_thumbnails'],
       '#states' => [
         'visible' => [
-          ':input[name="type_configuration[twitter][use_twitter_api]"]' => [
+          ':input[name="source_configuration[use_twitter_api]"]' => [
             'checked' => TRUE,
           ],
         ],
@@ -321,20 +345,18 @@ class Twitter extends MediaTypeBase {
   /**
    * {@inheritdoc}
    */
-  public function attachConstraints(MediaInterface $media) {
-    parent::attachConstraints($media);
-
-    if (isset($this->configuration['source_field'])) {
-      $source_field_name = $this->configuration['source_field'];
-      if ($media->hasField($source_field_name)) {
-        foreach ($media->get($source_field_name) as &$embed_code) {
-          /** @var \Drupal\Core\TypedData\DataDefinitionInterface $typed_data */
-          $typed_data = $embed_code->getDataDefinition();
-          $typed_data->addConstraint('TweetEmbedCode');
-          $typed_data->addConstraint('TweetVisible');
-        }
-      }
-    }
+  public function getSourceFieldConstraints() {
+    return [
+      'TweetEmbedCode' => [],
+      'TweetVisible' => [],
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function createSourceField(MediaTypeInterface $type) {
+    return parent::createSourceField($type)->set('label', 'Tweet URL');
   }
 
   /**
@@ -342,6 +364,8 @@ class Twitter extends MediaTypeBase {
    *
    * @param mixed $id
    *   The tweet ID.
+   * @param \Drupal\media\MediaInterface $media
+   *   The media entity.
    * @param string|null $media_url
    *   The URL of the media (i.e., photo, video, etc.) associated with the
    *   tweet.
@@ -349,7 +373,7 @@ class Twitter extends MediaTypeBase {
    * @return string
    *   The desired local URI.
    */
-  protected function getLocalImageUri($id, $media_url = NULL) {
+  protected function getLocalImageUri($id, MediaInterface $media, $media_url = NULL) {
     $directory = $this->configFactory
       ->get('media_entity_twitter.settings')
       ->get('local_images');
@@ -361,7 +385,7 @@ class Twitter extends MediaTypeBase {
       $this->logger->warning('Could not prepare thumbnail destination directory @dir', [
         '@dir' => $directory,
       ]);
-      return $this->getDefaultThumbnail();
+      return parent::getMetadata($media, 'thumbnail_uri');
     }
 
     $local_uri = $directory . '/' . $id . '.';
@@ -377,52 +401,10 @@ class Twitter extends MediaTypeBase {
     return $local_uri;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getDefaultThumbnail() {
-    return $this->config->get('icon_base') . '/twitter.png';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function thumbnail(MediaInterface $media) {
-    // If there's already a local image, use it.
-    if ($local_image = $this->getField($media, 'image_local')) {
-      return $local_image;
-    }
-
-    // If thumbnail generation is disabled, use the default thumbnail.
-    if (empty($this->configuration['generate_thumbnails'])) {
-      return $this->getDefaultThumbnail();
-    }
-
-    // We might need to generate a thumbnail...
-    $id = $this->getField($media, 'id');
-    $thumbnail_uri = $this->getLocalImageUri($id);
-
-    // ...unless we already have, in which case, use it.
-    if (file_exists($thumbnail_uri)) {
-      return $thumbnail_uri;
-    }
-
-    // Render the thumbnail SVG using the theme system.
-    $thumbnail = [
-      '#theme' => 'media_entity_twitter_tweet_thumbnail',
-      '#content' => $this->getField($media, 'content'),
-      '#author' => $this->getField($media, 'user'),
-      '#avatar' => $this->getField($media, 'profile_image_url_https'),
-    ];
-    $svg = $this->renderer->renderRoot($thumbnail);
-
-    return file_unmanaged_save_data($svg, $thumbnail_uri, FILE_EXISTS_ERROR) ?: $this->getDefaultThumbnail();
-  }
-
   /**
    * Runs preg_match on embed code/URL.
    *
-   * @param MediaInterface $media
+   * @param \Drupal\media\MediaInterface $media
    *   Media object.
    *
    * @return array|bool
@@ -431,16 +413,14 @@ class Twitter extends MediaTypeBase {
    * @see preg_match()
    */
   protected function matchRegexp(MediaInterface $media) {
-    $matches = array();
-
-    if (isset($this->configuration['source_field'])) {
-      $source_field = $this->configuration['source_field'];
-      if ($media->hasField($source_field)) {
-        $property_name = $media->{$source_field}->first()->mainPropertyName();
-        foreach (static::$validationRegexp as $pattern => $key) {
-          if (preg_match($pattern, $media->{$source_field}->{$property_name}, $matches)) {
-            return $matches;
-          }
+    $matches = [];
+
+    $source_field = $this->getSourceFieldDefinition($media->bundle->entity)->getName();
+    if ($media->hasField($source_field)) {
+      $property_name = $media->get($source_field)->first()->mainPropertyName();
+      foreach (static::$validationRegexp as $pattern => $key) {
+        if (preg_match($pattern, $media->get($source_field)->{$property_name}, $matches)) {
+          return $matches;
         }
       }
     }
@@ -452,7 +432,10 @@ class Twitter extends MediaTypeBase {
    * Get a single tweet.
    *
    * @param int $id
-   *   The tweet id.
+   *   The tweet ID.
+   *
+   * @return array
+   *   The tweet information.
    */
   protected function fetchTweet($id) {
     $this->tweetFetcher->setCredentials(
@@ -462,27 +445,7 @@ class Twitter extends MediaTypeBase {
       $this->configuration['oauth_access_token_secret']
     );
 
-    try {
-      return $this->tweetFetcher->fetchTweet($id);
-    }
-    catch (\Exception $e) {
-      throw new MediaTypeException(NULL, $e->getMessage());
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getDefaultName(MediaInterface $media) {
-    // The default name will be the twitter username of the author + the
-    // tweet ID.
-    $user = $this->getField($media, 'user');
-    $id = $this->getField($media, 'id');
-    if (!empty($user) && !empty($id)) {
-      return $user . ' - ' . $id;
-    }
-
-    return parent::getDefaultName($media);
+    return $this->tweetFetcher->fetchTweet($id);
   }
 
 }