Pull merge.
[yaffs-website] / web / modules / contrib / media_entity_instagram / src / InstagramEmbedFetcher.php
1 <?php
2
3 namespace Drupal\media_entity_instagram;
4
5 use Drupal\Component\Serialization\Json;
6 use Drupal\Core\Cache\CacheBackendInterface;
7 use Drupal\Component\Utility\UrlHelper;
8 use Drupal\Core\Logger\LoggerChannelFactoryInterface;
9 use Drupal\Core\Utility\Error;
10 use GuzzleHttp\Client;
11 use GuzzleHttp\Exception\RequestException;
12
13 /**
14  * Fetches instagram post via oembed.
15  *
16  * Fetches (and caches) instagram post data from free to use Instagram's oEmbed
17  * call.
18  */
19 class InstagramEmbedFetcher implements InstagramEmbedFetcherInterface {
20
21   const INSTAGRAM_URL = 'http://instagr.am/p/';
22
23   const INSTAGRAM_API = 'http://api.instagram.com/oembed';
24
25   /**
26    * The optional cache backend.
27    *
28    * @var \Drupal\Core\Cache\CacheBackendInterface
29    */
30   protected $cache;
31
32   /**
33    * Guzzle client.
34    *
35    * @var \GuzzleHttp\Client
36    */
37   protected $httpClient;
38
39   /**
40    * Logger.
41    *
42    * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
43    */
44   protected $loggerFactory;
45
46   /**
47    * InstagramEmbedFetcher constructor.
48    *
49    * @param \GuzzleHttp\Client $client
50    *   A HTTP Client.
51    * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $loggerFactory
52    *   A logger factory.
53    * @param \Drupal\Core\Cache\CacheBackendInterface|null $cache
54    *   (optional) A cache bin for storing fetched instagram posts.
55    */
56   public function __construct(Client $client, LoggerChannelFactoryInterface $loggerFactory, CacheBackendInterface $cache = NULL) {
57     $this->httpClient = $client;
58     $this->loggerFactory = $loggerFactory;
59     $this->cache = $cache;
60   }
61
62   /**
63    * {@inheritdoc}
64    */
65   public function fetchInstagramEmbed($shortcode, $hidecaption = FALSE, $maxWidth = NULL) {
66
67     $options = [
68       'url' => self::INSTAGRAM_URL . $shortcode . '/',
69       'hidecaption' => (int) $hidecaption,
70       'omitscript' => 1,
71     ];
72
73     if ($maxWidth) {
74       $options['maxwidth'] = $maxWidth;
75     }
76
77     // Tweets don't change much, so pull it out of the cache (if we have one)
78     // if this one has already been fetched.
79     $cacheKey = md5(serialize($options));
80     if ($this->cache && $cached_instagram_post = $this->cache->get($cacheKey)) {
81       return $cached_instagram_post->data;
82     }
83
84     $queryParameter = UrlHelper::buildQuery($options);
85
86     try {
87       $response = $this->httpClient->request(
88         'GET',
89         self::INSTAGRAM_API . '?' . $queryParameter,
90         ['timeout' => 5]
91       );
92       if ($response->getStatusCode() === 200) {
93         $data = Json::decode($response->getBody()->getContents());
94       }
95     }
96     catch (RequestException $e) {
97       $this->loggerFactory->get('media_entity_instagram')->error("Could not retrieve Instagram post $shortcode.", Error::decodeException($e));
98     }
99
100     // If we got data from Instagram oEmbed request, return data.
101     if (isset($data)) {
102
103       // If we have a cache, store the response for future use.
104       if ($this->cache) {
105         // Instagram posts don't change often, so the response should expire
106         // from the cache on its own in 90 days.
107         $this->cache->set($cacheKey, $data, time() + (86400 * 90));
108       }
109
110       return $data;
111     }
112     return FALSE;
113   }
114
115 }