You are here

FacebookFetcher.php in Media entity facebook 3.x

Same filename and directory in other branches
  1. 8.2 src/FacebookFetcher.php
  2. 8 src/FacebookFetcher.php

File

src/FacebookFetcher.php
View source
<?php

namespace Drupal\media_entity_facebook;

use Drupal\Component\Utility\Crypt;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\GuzzleException;

/**
 * Class FacebookFetcher.
 */
class FacebookFetcher {

  /**
   * Stores logger.
   *
   * @var \Drupal\Core\Logger\LoggerChannel
   */
  protected $loggerChannel;

  /**
   * Guzzle HTTP client.
   *
   * @var \GuzzleHttp\ClientInterface
   */
  protected $httpClient;

  /**
   * The language manager.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * Tracks when an error has occurred when interacting with the API.
   *
   * @var bool
   */
  protected $apiErrorEncountered = FALSE;

  /**
   * The facebook config.
   *
   * @var \Drupal\Core\Config\ImmutableConfig
   */
  protected $config;

  /**
   * The cache service.
   *
   * @var \Drupal\Core\Cache\CacheBackendInterface
   */
  protected $cache;

  /**
   * Constructor for FacebookFetcher.
   *
   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_channel_factory
   *   The logger factory.
   * @param \GuzzleHttp\ClientInterface $client
   *   The Guzzle HTTP client.
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   *   The language manager.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory.
   * @param \Drupal\Core\Cache\CacheBackendInterface $cache
   *   The cache service.
   */
  public function __construct(LoggerChannelFactoryInterface $logger_channel_factory, ClientInterface $client, LanguageManagerInterface $language_manager, ConfigFactoryInterface $configFactory, CacheBackendInterface $cache) {
    $this->loggerChannel = $logger_channel_factory
      ->get('media_entity_facebook');
    $this->httpClient = $client;
    $this->languageManager = $language_manager;
    $this->config = $configFactory
      ->get('media_entity_facebook.settings');
    $this->cache = $cache;
  }

  /**
   * Fetch and return response from Facebook's oEmbed API endpoint.
   *
   * @param string $resource_url
   *   The URL to pass to Facebook's oembed API.
   */
  public function getOembedData($resource_url) {

    // If there was an error interacting with the Facebook API, like a network
    // timeout due to Facebook being down, we don't want to clog up the Drupal
    // site's resources by making lots of API requests that may all timeout.
    // To do this, we mark when a request exception occurred and back out of
    // subsequent requests if so. This of course only matters if there are many
    // embeds on a single page request.
    if ($this->apiErrorEncountered) {
      $this->loggerChannel
        ->error('Aborting Facebook oembed API request due to a previously encountered error on the same request.');
      return FALSE;
    }
    $appId = $this->config
      ->get('facebook_app_id') ?: '';
    $appSecret = $this->config
      ->get('facebook_app_secret') ?: '';
    if (empty($appId) || empty($appSecret)) {
      $this->loggerChannel
        ->error('Cannot retrieve Facebook embed as the Facebook app ID and/or app secret are missing from configuration. Visit /admin/config/media/facebook-settings to provide these values.');
      return FALSE;
    }
    $endpoint = $this
      ->getApiEndpointUrl($resource_url) . '?url=' . $resource_url . '&access_token=' . $appId . '|' . $appSecret;
    $cid = 'media_entity_facebook:' . Crypt::hashBase64(serialize($endpoint));
    $cacheItem = $this->cache
      ->get($cid);
    if ($cacheItem) {
      $oembedResponse = $cacheItem->data;
    }
    else {
      $options = [
        'timeout' => 5,
        'headers' => [
          'Accept-Language' => $this->languageManager
            ->getCurrentLanguage()
            ->getId(),
        ],
      ];
      try {
        $response = $this->httpClient
          ->request('GET', $endpoint, $options);
      } catch (GuzzleException $e) {
        $this->loggerChannel
          ->error('Error retrieving oEmbed data for a Facebook media entity: @error', [
          '@error' => $e
            ->getMessage(),
        ]);
        $this->apiErrorEncountered = TRUE;
        return FALSE;
      }
      $oembedResponse = json_decode((string) $response
        ->getBody(), TRUE);

      // Cache the result for 10 minutes.
      $cacheTime = \Drupal::time()
        ->getRequestTime() + 600;
      $this->cache
        ->set($cid, $oembedResponse, $cacheTime);
    }
    return $oembedResponse;
  }

  /**
   * Return the appropriate Facebook oEmbed API endpoint for the content URL.
   *
   * @param string $content_url
   *   The content URL contains the URL to the resource.
   *
   * @return string
   *   The oEmbed endpoint URL.
   */
  protected function getApiEndpointUrl($content_url) {
    if (preg_match('/\\/videos\\//', $content_url) || preg_match('/\\/video.php\\//', $content_url)) {
      return 'https://graph.facebook.com/v10.0/oembed_video';
    }
    else {
      return 'https://graph.facebook.com/v10.0/oembed_post';
    }
  }

}

Classes

Namesort descending Description
FacebookFetcher Class FacebookFetcher.