View source
<?php
namespace Drupal\oembed_providers\OEmbed;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\media\OEmbed\Provider;
use Drupal\media\OEmbed\ProviderException;
use Drupal\media\OEmbed\ProviderRepositoryInterface;
use Drupal\oembed_providers\Entity\OembedProvider;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\TransferException;
final class ProviderRepositoryDecorator implements ProviderRepositoryInterface {
protected $decorated;
protected $oembedProviderStorage;
protected $maxAge;
protected $httpClient;
protected $providersUrl;
protected $externalFetch;
protected $time;
protected $keyValue;
protected $logger;
protected $moduleHandler;
public function __construct(ProviderRepositoryInterface $decorated, EntityTypeManagerInterface $entity_type_manager, ClientInterface $http_client, ConfigFactoryInterface $config_factory, TimeInterface $time, KeyValueFactoryInterface $key_value_factory = NULL, LoggerChannelFactoryInterface $logger_factory = NULL, ModuleHandlerInterface $module_handler, $max_age = 604800) {
$this->decorated = $decorated;
$this->oembedProviderStorage = $entity_type_manager
->getStorage('oembed_provider');
$this->httpClient = $http_client;
$this->providersUrl = $config_factory
->get('media.settings')
->get('oembed_providers_url');
$this->externalFetch = $config_factory
->get('oembed_providers.settings')
->get('external_fetch');
$this->time = $time;
$this->keyValue = $key_value_factory
->get('media');
$this->logger = $logger_factory
->get('media');
$this->moduleHandler = $module_handler;
$this->maxAge = (int) $max_age;
}
public function getAll() {
$current_time = $this->time
->getCurrentTime();
$stored = $this->keyValue
->get('oembed_providers');
if ($stored && $stored['expires'] > $current_time) {
return $stored['data'];
}
$custom_providers = $this
->getCustomProviders();
if ($this->externalFetch) {
try {
$response = $this->httpClient
->request('GET', $this->providersUrl);
} catch (TransferException $e) {
if (isset($stored['data'])) {
$this->logger
->warning('Remote oEmbed providers could not be retrieved due to error: @error. Using previously stored data. This may contain out of date information.', [
'@error' => $e
->getMessage(),
]);
return $stored['data'];
}
throw new ProviderException("Could not retrieve the oEmbed provider database from {$this->providersUrl}", NULL, $e);
}
$providers = Json::decode((string) $response
->getBody());
if (!is_array($providers) || empty($providers)) {
if (isset($stored['data'])) {
$this->logger
->warning('Remote oEmbed providers database returned invalid or empty list. Using previously stored data. This may contain out of date information.');
return $stored['data'];
}
throw new ProviderException('Remote oEmbed providers database returned invalid or empty list.');
}
$providers = array_merge($custom_providers, $providers);
}
else {
$providers = $custom_providers;
}
usort($providers, function ($a, $b) {
return strcasecmp($a['provider_name'], $b['provider_name']);
});
$this->moduleHandler
->alter('oembed_providers', $providers);
$keyed_providers = [];
foreach ($providers as $provider) {
try {
$name = (string) $provider['provider_name'];
$keyed_providers[$name] = new Provider($provider['provider_name'], $provider['provider_url'], $provider['endpoints']);
} catch (ProviderException $e) {
}
}
$this->keyValue
->set('oembed_providers', [
'data' => $keyed_providers,
'expires' => $current_time + $this->maxAge,
]);
return $keyed_providers;
}
public function get($provider_name) {
$providers = $this
->getAll();
if (!isset($providers[$provider_name])) {
throw new \InvalidArgumentException("Unknown provider '{$provider_name}'");
}
return $providers[$provider_name];
}
public function getCustomProviders() {
return array_map(function (OembedProvider $custom_provider) {
$endpoints = array_map(function (array $endpointData) {
$endpoint = [
'schemes' => $endpointData['schemes'],
'url' => $endpointData['url'],
'formats' => array_keys(array_filter($endpointData['formats'])),
];
if ($endpointData['discovery']) {
$endpoint['discovery'] = $endpointData['discovery'];
}
return $endpoint;
}, $custom_provider
->get('endpoints'));
return [
'provider_name' => $custom_provider
->get('label'),
'provider_url' => $custom_provider
->get('provider_url'),
'endpoints' => $endpoints,
];
}, $this->oembedProviderStorage
->loadMultiple());
}
}