feeds_youtube-8.x-1.x-dev/src/Feeds/Fetcher/FeedsYouTubeFetcher.php

src/Feeds/Fetcher/FeedsYouTubeFetcher.php
<?php

namespace Drupal\feeds_youtube\Feeds\Fetcher;

use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Url;
use Drupal\feeds\FeedInterface;
use Drupal\feeds\Plugin\Type\Fetcher\FetcherInterface;
use Drupal\feeds\Plugin\Type\ClearableInterface;
use Drupal\feeds\Plugin\Type\PluginBase;
use Drupal\feeds\Result\RawFetcherResult;
use Drupal\feeds\StateInterface;
use GuzzleHttp\Exception\RequestException;

/**
 * Constructs FeedsYouTubeFetcher object.
 *
 * @FeedsFetcher(
 *   id = "feeds_youtube_fetcher",
 *   title = @Translation("YouTube"),
 *   description = @Translation("Fetch videos from a YouTube user"),
 *   form = {
 *     "configuration" = "Drupal\feeds_youtube\Feeds\Fetcher\Form\FeedsYouTubeFetcherForm",
 *     "feed" = "Drupal\feeds_youtube\Feeds\Fetcher\Form\FeedsYouTubeFetcherFeedForm",
 *   }
 * )
 */
class FeedsYouTubeFetcher extends PluginBase implements ClearableInterface, FetcherInterface {

  /**
   * {@inheritdoc}
   */
  public function fetch(FeedInterface $feed, StateInterface $state) {
    $result = $this->get($feed->getSource(), $feed->id());
    if ($result !== FALSE) {
      return new RawFetcherResult($result);
    }
    else {
      return new RawFetcherResult('');
    }
  }

  /**
   * Helper function to get client factory.
   *
   * @param string $id
   *   The feed Id.
   *
   * @return Google_Client|null
   */
  public function getClientFactory($id) {
    $config = $this->getConfiguration();
    $cid = $this->getAccessTokenCacheId($id);
    $google_access_token = \Drupal::service('cache.feeds_youtube_tokens')->get($cid);

    if (!empty($config['google_oauth_client_id']) &&
      !empty($config['google_oauth_client_secret']) &&
      !empty($config['google_developer_key'])) {
      $client = new \Google_Client();
      $client->setClientId($config['google_oauth_client_id']);
      $client->setClientSecret($config['google_oauth_client_secret']);
      $client->setApprovalPrompt('force');
      $client->setAccessType('offline');
      $client->setDeveloperKey($config['google_developer_key']);
      $client->setScopes('https://www.googleapis.com/auth/youtube.readonly');
      $current_path = \Drupal::service('path.current')->getPath();
      $path_alias = \Drupal::service('path_alias.manager')->getAliasByPath($current_path);
      $current_url = Url::fromUserInput($path_alias, ['absolute' => TRUE])->toString();
      $redirect = filter_var($current_url, FILTER_SANITIZE_URL);
      $client->setRedirectUri($redirect);

      if (!empty($google_access_token->data)) {
        $client->setAccessToken($google_access_token->data);
        if ($client->isAccessTokenExpired()) {
          $client->refreshToken($client->getRefreshToken());

          // Save refreshed access token.
          $cache_tags = [
            'feeds_youtube:google_access_token',
          ];
          \Drupal::service('cache.feeds_youtube_tokens')->set($cid, $client->getAccessToken(), CacheBackendInterface::CACHE_PERMANENT, $cache_tags);
        }
      }
      return $client;
    }
    else {
      \Drupal::messenger()->addWarning($this->t('Google API access is not configured.'));
    }
  }

  /**
   * Make the API queries to get the data the parser needs.
   *
   * @param string $source
   *   The URL source.
   * @param string $id
   *   The feed Id.
   *
   * @return string
   *   Returns a JSON-encoded array of stdClass objects.
   */
  public function get(String $source, $id) {
    $client = $this->getClientFactory($id);
    $youtube = new \Google_Service_YouTube($client);

    $number_of_pages = $this->getConfiguration('import_video_limit');
    if ($number_of_pages < 1) {
      $number_of_pages = 1;
    }

    $result = [];
    $next_page_token = '';
    for ($i = 0; $i < $number_of_pages; $i++) {
      $api_request_result = $this->requestNextPage($source, $next_page_token, $client, $youtube);
      $next_page_token = (!empty($api_request_result['next_page_token'])) ? $api_request_result['next_page_token'] : '';
      if (!empty($api_request_result['result'])) {
        $result = array_merge($result, $api_request_result['result']);
      }
    }

    return json_encode($result);
  }

  /**
   * Convert YouTube video duration to time interval.
   *
   * @param string $duration
   *   YouTube video duration.
   *
   * @return string
   */
  private function timeToDuration($duration) {
    $di = new \DateInterval($duration);
    $string = '';
    if ($di->h > 0) {
      $string .= $di->h . ':';
    }
    return $string . $di->i . ':' . $di->s;
  }

  /**
   * Parse a YouTube video feed.
   *
   * @param array $video_items
   *
   * @return array
   */
  private function parseVideoItems($video_items) {
    $items = [];

    foreach ($video_items['items'] as $key => $video) {
      $item = [
        'video_id' => '',
        'video_url' => '',
        'title' => '',
        'description' => '',
        'thumbnail_default' => '',
        'thumbnail_medium' => '',
        'thumbnail_high' => '',
        'thumbnail_standard' => '',
        'thumbnail_maxres' => '',
        'category' => '',
        'tags' => '',
        'duration' => '',
        'duration_raw' => '',
        'published_datetime' => '',
        'published_timestamp' => '',
        'view_count' => '',
        'fav_count' => '',
        'likes' => '',
        'dislikes' => '',
        'favorites' => '',
        'embedded_player' => '',
      ];

      if (isset($video['id']) && is_array($video['id']) && isset($video['id']['videoId'])) {
        $item['video_id'] = $video['id']['videoId'];
      }
      elseif (isset($video['contentDetails']) && isset($video['contentDetails']['videoId'])) {
        $item['video_id'] = $video['contentDetails']['videoId'];
      }
      elseif (isset($video['snippet']) && isset($video['snippet']['resourceId']) && isset($video['snippet']['resourceId']['videoId'])) {
        $item['video_id'] = $video['snippet']['resourceId']['videoId'];
      }

      if (!empty($item['video_id'])) {
        $item['video_url'] = 'https://www.youtube.com/watch?v=' . $item['video_id'];
      }

      if (isset($video['snippet'])) {
        $item['title'] = $video['snippet']['title'];
        $item['description'] = $video['snippet']['description'];

        if (isset($video['snippet']['thumbnails']['default'])) {
          $item['thumbnail_default'] = $video['snippet']['thumbnails']['default']['url'];
        }
        if (isset($video['snippet']['thumbnails']['standard'])) {
          $item['thumbnail_standard'] = $video['snippet']['thumbnails']['standard']['url'];
        }
        if (isset($video['snippet']['thumbnails']['medium'])) {
          $item['thumbnail_medium'] = $video['snippet']['thumbnails']['medium']['url'];
        }
        if (isset($video['snippet']['thumbnails']['high'])) {
          $item['thumbnail_high'] = $video['snippet']['thumbnails']['high']['url'];
        }
        if (isset($video['snippet']['thumbnails']['maxres'])) {
          $item['thumbnail_maxres'] = $video['snippet']['thumbnails']['maxres']['url'];
        }

        if (isset($video['snippet']['categoryId'])) {
          $item['category'] = $video['snippet']['categoryId'];
        }

        if (isset($video['snippet']['tags'])) {
          $item['tags'] = implode(', ', $video['snippet']['tags']);
        }

        $published_timestamp = strtotime($video['snippet']['publishedAt']);
      }

      if (isset($video['contentDetails'])) {
        if (isset($video['contentDetails']['duration'])) {
          $item['duration'] = $this->timeToDuration($video['contentDetails']['duration']);
          $item['duration_raw'] = $video['contentDetails']['duration'];
        }

        if (!isset($published_timestamp) && isset($video['contentDetails']['videoPublishedAt'])) {
          $published_timestamp = strtotime($video['snippet']['publishedAt']);
        }
      }

      if (isset($video['statistics'])) {
        $item['view_count'] = $video['statistics']['viewCount'];
        $item['fav_count'] = $video['statistics']['favoriteCount'];
        $item['likes'] = $video['statistics']['likeCount'];
        $item['dislikes'] = $video['statistics']['dislikeCount'];
        $item['favorites'] = $video['statistics']['favoriteCount'];
      }

      if (isset($video['player'])) {
        $item['embedded_player'] = $video['player']['embedHtml'];
      }

      if (isset($published_timestamp)) {
        $item['published_datetime'] = date('Y-m-d H:i:s', $published_timestamp);
        $item['published_timestamp'] = $published_timestamp;
      }

      $items[] = $item;
    }

    return $items;
  }

  /**
   * Request URL.
   *
   * @param string $url
   *   The URL to request.
   * @param string $page_token
   *   The page token for the request.
   *
   * @return array|null
   */
  public function requestUrl($url, $page_token = '') {
    try {
      $url .= '&maxResults=' . $this->getConfiguration('results_per_page');
      $url .= ($page_token != '') ? '&pageToken=' . $page_token : '';
      $api_request_result = \Drupal::httpClient()->get($url);
      $data = (string) $api_request_result->getBody();
      return json_decode($data, TRUE);
    }
    catch (RequestException $e) {
      \Drupal::messenger()->addError($this->t('Request Error: @message', ['@message' => $e->getMessage()]));
    }
  }

  /**
   * Perform API request to YouTube API and retrieve search result.
   *
   * @param string $url
   *   The URL to request.
   * @param string $page_token
   *   The page token for the request.
   * @param Google_Client $client
   *   A Google client to use.
   * @param Google_Service_YouTube $youtube
   *   A Google YouTube service to use.
   *
   * @return array|null
   */
  private function requestNextPage($url, $page_token = '', $client, $youtube) {
    $result = [];
    $response = $this->requestUrl($url, $page_token);

    if (!empty($response['items'])) {
      $result = $this->parseVideoItems($response);
    }
    else {
      \Drupal::messenger()->addStatus($this->t('No videos found.'));
    }

    return [
      'result' => $result,
      'next_page_token' => isset($search_response['nextPageToken']) ? $search_response['nextPageToken'] : '',
    ];
  }

  /**
   * Get access token cache ID.
   *
   * @param string $id
   *   The feed Id.
   *
   * @return string
   */
  public function getAccessTokenCacheId($id) {
    return 'feeds_youtube:google_access_token:' . $id;
  }

  /**
   * {@inheritdoc}
   */
  public function clear(FeedInterface $feed, StateInterface $state) {
    $this->onFeedDeleteMultiple([$feed]);
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'google_developer_key' => '',
      'google_oauth_client_id' => '',
      'google_oauth_client_secret' => '',
      'import_video_limit' => 50,
      'results_per_page' => 50,
    ];
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc