View source
<?php
namespace Drupal\bynder;
use Bynder\Api\BynderClient;
use Bynder\Api\Impl\PermanentTokens\Configuration;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\State\StateInterface;
use Drupal\Core\Url;
use League\OAuth2\Client\Token\AccessToken;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
class BynderApi implements BynderApiInterface {
const BYNDER_INTEGRATION_ID = 'a7129512-c6e3-47a3-be40-9a66503e82ed';
const CID_TAGS = 'bynder_tags';
const CID_METAPROPERTIES = 'bynder_metaproperties';
const CID_DERIVATIVES = 'bynder_derivatives';
const CACHED_CALLS = [
'getMetaproperties' => self::CID_METAPROPERTIES,
'getDerivatives' => self::CID_DERIVATIVES,
];
const AUTO_UPDATED_TAGS_QUERIES = [
NULL,
[
'limit' => 500,
'orderBy' => 'mediaCount desc',
'minCount' => 1,
],
];
protected $bynderApi;
protected $bynderConfig;
protected $configFactory;
protected $loggerFactory;
protected $session;
protected $state;
protected $cache;
protected $time;
protected $bynderConfiguration;
public function __construct(ConfigFactoryInterface $config_factory, LoggerChannelFactoryInterface $logger_factory, SessionInterface $session, StateInterface $state, CacheBackendInterface $cache, TimeInterface $time) {
$this->configFactory = $config_factory;
$this->loggerFactory = $logger_factory;
$this->session = $session;
$this->state = $state;
$this->cache = $cache;
$this->time = $time;
}
public function initiateOAuthTokenRetrieval() {
$bynder_settings = $this->configFactory
->get('bynder.settings');
if (!$bynder_settings
->get('client_id') || !$bynder_settings
->get('client_secret')) {
throw new \Exception('Client ID or secret configuration missing');
}
$query = [
'client_id' => $bynder_settings
->get('client_id'),
'redirect_uri' => $this
->getCallback(),
'scope' => 'offline asset:read asset:write asset.usage:read asset.usage:write current.user:read current.profile:read',
'response_type' => 'code',
'state' => 'state',
];
return Url::fromUri('https://' . $bynder_settings
->get('account_domain') . '/v6/authentication/oauth2/auth', array(
'query' => $query,
'auth' => null,
'allow_redirects' => false,
));
}
public function hasAccessToken() {
$session_data = $this->session
->get('bynder', []);
if (empty($session_data['access_token']) || !$session_data['access_token'] instanceof AccessToken) {
return FALSE;
}
if (empty($session_data['config_hash']) || $session_data['config_hash'] != $this->state
->get('bynder_config_hash')) {
return FALSE;
}
if ($session_data['access_token']
->getExpires() < $this->time
->getCurrentTime()) {
try {
$this
->hasUploadPermissions();
if ($this->bynderConfiguration instanceof \Bynder\Api\Impl\OAuth2\Configuration) {
$options = $this->bynderConfiguration
->getToken()
->jsonSerialize();
if (empty($data['refresh_token'])) {
$options['refresh_token'] = $session_data['access_token']
->getRefreshToken();
}
$session_data['access_token'] = new AccessToken($options);
$this->session
->set('bynder', $session_data);
return TRUE;
}
else {
$this->session
->set('bynder', []);
}
} catch (\Exception $e) {
$this->session
->set('bynder', []);
}
return FALSE;
}
return TRUE;
}
public function finishOAuthTokenRetrieval($code) {
$bynder_configuration = $this
->getOauthConfiguration();
$this->bynderApi = new BynderClient($bynder_configuration);
$session_data = $this->session
->get('bynder', []);
$session_data['access_token'] = $this->bynderApi
->getAccessToken($code);
$session_data['config_hash'] = $this->state
->get('bynder_config_hash');
$this->session
->set('bynder', $session_data);
}
public function hasUploadPermissions() {
$this
->getAssetBankManager();
$user = $this->bynderApi
->getCurrentUser()
->wait();
if (isset($user)) {
$profileId = $user['profileId'];
$userProfile = $this->bynderApi
->getSecurityProfile($profileId)
->wait();
foreach ($userProfile['roles'] as $role) {
if ($role == 'MEDIAUPLOAD' || $role == 'MEDIAUPLOADFORAPPROVAL') {
return $role;
}
}
}
return FALSE;
}
public function getAssetBankManager() {
$bynder_settings = $this->configFactory
->get('bynder.settings');
$request_options = [
'timeout' => $bynder_settings
->get('timeout'),
];
$session_data = \Drupal::service('session')
->get('bynder', []);
if ($this->bynderConfig) {
$this->bynderConfiguration = new Configuration($this->bynderConfig['baseUrl'], $this->bynderConfig['permanent_token'], $request_options);
}
elseif (!empty($session_data['access_token']) && !empty($session_data['config_hash']) && $session_data['config_hash'] == $this->state
->get('bynder_config_hash')) {
$this->bynderConfiguration = $this
->getOauthConfiguration();
$this->bynderConfiguration
->setToken($session_data['access_token']);
}
else {
$this->bynderConfiguration = new Configuration($bynder_settings
->get('account_domain'), $bynder_settings
->get('permanent_token'), $request_options);
}
$this->bynderApi = new BynderClient($this->bynderConfiguration);
return $this->bynderApi
->getAssetBankManager();
}
public function setBynderConfiguration(array $config) {
$this->bynderConfig = $config;
}
public function updateCachedData() {
$expire = $this->configFactory
->get('bynder.settings')
->get('cache_lifetime') + $this->time
->getRequestTime();
$items = [];
foreach (self::CACHED_CALLS as $method => $cid) {
if ($this->configFactory
->get('bynder.settings')
->get('debug')) {
$this->loggerFactory
->get('bynder')
->debug('Update cache: updating cached data for %method.', [
'%method' => $method,
]);
}
$items[$cid] = [
'data' => call_user_func_array([
$this
->getAssetBankManager(),
$method,
], [])
->wait(),
'expire' => $expire,
];
}
foreach (static::AUTO_UPDATED_TAGS_QUERIES as $query) {
$items[self::CID_TAGS . '_' . md5(serialize($query))] = [
'data' => $this
->getAssetBankManager()
->getTags($query)
->wait(),
'expire' => $expire,
];
}
$this->cache
->setMultiple($items);
$this->state
->set('bynder_cache_last_update', $this->time
->getRequestTime());
}
public function getTags($query = []) {
$bynder_configuration = $this->configFactory
->get('bynder.settings');
if ($bynder_configuration
->get('debug')) {
$this->loggerFactory
->get('bynder')
->debug('Method: %method is called with arguments: @args', [
'%method' => 'getTags',
'@args' => print_r($query, TRUE),
]);
}
try {
if (empty($args['keyword'])) {
$query_hash = md5(serialize($query));
$allow_expired = FALSE;
foreach (static::AUTO_UPDATED_TAGS_QUERIES as $candidate) {
if (md5(serialize($candidate)) === $query_hash) {
$allow_expired = TRUE;
break;
}
}
if ($cache_item = $this->cache
->get(self::CID_TAGS . '_' . $query_hash, $allow_expired)) {
return $cache_item->data;
}
else {
$result = [];
$query['page'] = 1;
if (!isset($query['limit'])) {
$query['limit'] = 50;
}
do {
$items = $this
->getAssetBankManager()
->getTags($query)
->wait();
$result = array_merge($result, $items);
$query['page']++;
} while (!empty($items) && count($items) == $query['limit']);
$this->cache
->set(self::CID_TAGS . '_' . $query_hash, $result, $this->configFactory
->get('bynder.settings')
->get('cache_lifetime') + $this->time
->getRequestTime());
return $result;
}
}
else {
$result = $this
->getAssetBankManager()
->getTags($query)
->wait();
}
if ($bynder_configuration
->get('debug')) {
$this->loggerFactory
->get('bynder')
->debug('Method: %method returns: @result', [
'%method' => 'getTags',
'@result' => print_r($result, TRUE),
]);
}
return $result;
} catch (\Exception $e) {
if ($bynder_configuration
->get('debug')) {
$this->loggerFactory
->get('bynder')
->error('Method: %method throws error with message: @message', [
'%method' => 'getTags',
'@message' => $e
->getMessage(),
]);
}
throw $e;
}
}
public function getIntegrationId() {
return self::BYNDER_INTEGRATION_ID;
}
public function addAssetUsage($asset_id, $usage_url, $creation_date, $additional_info = NULL) {
$usage_properties = [
'integration_id' => self::BYNDER_INTEGRATION_ID,
'asset_id' => $asset_id,
'timestamp' => $creation_date,
'uri' => $usage_url
->setAbsolute(TRUE)
->toString(),
'additional' => $additional_info,
];
return $this
->getAssetBankManager()
->createUsage($usage_properties)
->wait();
}
public function removeAssetUsage($asset_id, $usage_url = NULL) {
$usageProperties = [
'integration_id' => self::BYNDER_INTEGRATION_ID,
'asset_id' => $asset_id,
'uri' => $usage_url,
];
return $this
->getAssetBankManager()
->deleteUsage($usageProperties)
->wait();
}
public function getAssetUsages($asset_id) {
return $this
->getAssetBankManager()
->getUsage([
'asset_id' => $asset_id,
])
->wait();
}
public function __call($method, $args) {
$bynder_configuration = $this->configFactory
->get('bynder.settings');
if ($bynder_configuration
->get('debug')) {
$this->loggerFactory
->get('bynder')
->debug('Method: %method is called with arguments: @args', [
'%method' => $method,
'@args' => print_r($args, TRUE),
]);
}
try {
if (empty($args) && in_array($method, array_keys(self::CACHED_CALLS))) {
if ($cache_item = $this->cache
->get(self::CACHED_CALLS[$method], TRUE)) {
return $cache_item->data;
}
else {
$result = call_user_func_array([
$this
->getAssetBankManager(),
$method,
], $args)
->wait();
$this->cache
->set(self::CACHED_CALLS[$method], $result, $this->configFactory
->get('bynder.settings')
->get('cache_lifetime') + $this->time
->getRequestTime());
return $result;
}
}
else {
$result = call_user_func_array([
$this
->getAssetBankManager(),
$method,
], $args)
->wait();
}
if ($bynder_configuration
->get('debug')) {
$this->loggerFactory
->get('bynder')
->debug('Method: %method returns: @result', [
'%method' => $method,
'@result' => print_r($result, TRUE),
]);
}
return $result;
} catch (\Exception $e) {
if ($bynder_configuration
->get('debug')) {
$this->loggerFactory
->get('bynder')
->error('Method: %method throws error with message: @message', [
'%method' => $method,
'@message' => $e
->getMessage(),
]);
}
throw $e;
}
}
protected function getCallback() : string {
$callback = Url::fromRoute('bynder.oauth', [], [
'absolute' => TRUE,
'path_processing' => FALSE,
])
->toString(TRUE)
->getGeneratedUrl();
return $callback;
}
protected function getOauthConfiguration() : \Bynder\Api\Impl\OAuth2\Configuration {
$bynder_settings = $this->configFactory
->get('bynder.settings');
$bynder_configuration = new \Bynder\Api\Impl\OAuth2\Configuration($bynder_settings
->get('account_domain'), $this
->getCallback(), $bynder_settings
->get('client_id'), $bynder_settings
->get('client_secret'), NULL, [
'timeout' => $bynder_settings
->get('timeout'),
]);
return $bynder_configuration;
}
}