acquia_dam-1.0.0-rc1/src/Client/AcquiaDamClient.php
src/Client/AcquiaDamClient.php
<?php declare(strict_types=1); namespace Drupal\acquia_dam\Client; use Drupal\acquia_dam\Exception\DamClientException; use Drupal\acquia_dam\Exception\DamConnectException; use Drupal\acquia_dam\Exception\DamServerException; use Drupal\Component\Datetime\TimeInterface; use Drupal\Component\Serialization\Json; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Config\ImmutableConfig; use GuzzleHttp\Client; use GuzzleHttp\Exception\ClientException; use GuzzleHttp\Exception\ConnectException; use Psr\Log\LoggerInterface; /** * The client service for interacting with the DAM API. */ class AcquiaDamClient extends Client { /** * The cache backend. * * @var \Drupal\Core\Cache\CacheBackendInterface */ private $cacheBackend; /** * The time service. * * @var \Drupal\Component\Datetime\TimeInterface */ protected $time; /** * Acquia Dam Config. * * @var \Drupal\Core\Config\ImmutableConfig */ protected $acquiaDamConfig; /** * DAM logger channel. * * @var \Drupal\Core\Logger\LoggerChannelInterface */ protected $damLoggerChannel; /** * Constructs a new Client object. * * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * The cache backend. * @param \Drupal\Component\Datetime\TimeInterface $time * The time service. * @param \Drupal\Core\Config\ImmutableConfig $acquiaDamConfig * Acquia DAM config. * @param array $config * Client config array. * @param \Psr\Log\LoggerInterface $loggerChannel * DAM logger channel. */ public function __construct(CacheBackendInterface $cache_backend, TimeInterface $time, ImmutableConfig $acquiaDamConfig, array $config, LoggerInterface $loggerChannel) { $this->cacheBackend = $cache_backend; $this->time = $time; $this->acquiaDamConfig = $acquiaDamConfig; $this->damLoggerChannel = $loggerChannel; parent::__construct($config); } /** * Search assets. * * @param string $query * The query. * @param string $sort * The sort. * @param int $limit * The limit. * @param int $offset * The offset. * @param string[] $expand * The expands. * * @return array * The results. * * @throws \Drupal\acquia_dam\Exception\DamClientException * @throws \Drupal\acquia_dam\Exception\DamConnectException * @throws \Drupal\acquia_dam\Exception\DamServerException */ public function search(string $query, string $sort = '-created_date', int $limit = 10, int $offset = 0, array $expand = []): array { try { $query = \http_build_query([ 'query' => $query, 'sort' => $sort, 'limit' => $limit, 'offset' => $offset, 'expand' => implode(',', $expand), ]); $response = $this->get('/v2/assets/search?' . $query); $data = (string) $response->getBody(); } catch (\Exception $e) { $this->throwDamException($e); } return Json::decode($data); } /** * Get an asset object from the DAM. * * @param string $id * The asset ID. * @param string $version * The asset version. * * @return array * The asset, or null if not found. * * @throws \Drupal\acquia_dam\Exception\DamClientException * @throws \Drupal\acquia_dam\Exception\DamServerException * @throws \Drupal\acquia_dam\Exception\DamConnectException */ public function getAsset(string $id, string $version = ''): array { $cache_key = 'asset:' . $id; if ($version !== '') { $cache_key .= ':' . $version; } $cached = $this->cacheBackend->get($cache_key); if ($cached !== FALSE && property_exists($cached, 'data')) { return Json::decode($cached->data); } try { // @todo make this configurable, maybe? $expand = 'asset_properties,embeds,file_properties,metadata,metadata_info,metadata_vocabulary,security,thumbnails'; $response = $this->get('/v2/assets/' . $id . '?expand=' . $expand); $data = (string) $response->getBody(); $decoded_data = Json::decode($data); $thumbnail_details = reset($decoded_data['thumbnails']); $date = \DateTime::createFromFormat(\DateTimeInterface::ISO8601, $thumbnail_details['valid_until']); // Expiration time of cache should be same as the expiration time of the // asset thumbnail, otherwise it will lead to broken thumbnails. $this->cacheBackend->set($cache_key, $data, $date->getTimestamp(), [ 'acquia-dam-asset', 'acquia-dam-asset:' . $id, ]); } catch (\Exception $e) { $this->throwDamException($e); } return $decoded_data; } /** * Gets the versions list for an asset. * * @param string $id * The asset ID. * * @return array * The asset's version data. * * @throws \Drupal\acquia_dam\Exception\DamClientException * @throws \Drupal\acquia_dam\Exception\DamServerException * @throws \Drupal\acquia_dam\Exception\DamConnectException */ public function getAssetVersionList(string $id): array { try { $domain = $this->acquiaDamConfig->get('domain'); $response = $this->get("https://$domain/api/rest/asset/uuid/$id/assetversions"); $data = (string) $response->getBody(); } catch (\Exception $e) { $this->throwDamException($e); } return Json::decode($data); } /** * Sends an integration link create request to DAM. * * @param string $assetUuid * DAM asset id. * @param string $url * Url to set for the integration link. * @param string $description * Description for the integration link. * * @return array|null * Response body, or null. * * @throws \Drupal\acquia_dam\Exception\DamClientException * @throws \Drupal\acquia_dam\Exception\DamServerException * @throws \Drupal\acquia_dam\Exception\DamConnectException * @throws \GuzzleHttp\Exception\GuzzleException */ public function registerIntegrationLink(string $assetUuid, string $url, string $description): ?array { try { $domain = $this->acquiaDamConfig->get('domain'); $response = $this->request('POST', "https://$domain/api/rest/integrationlink", [ 'json' => [ 'assetUuid' => $assetUuid, 'description' => $description, 'url' => $url, ], ] ); $data = (string) $response->getBody(); } catch (\Exception $e) { $this->throwDamException($e); } return Json::decode($data); } /** * Removes integration link from DAM. * * @param string $uuid * Integration link uuid. * * @throws \Drupal\acquia_dam\Exception\DamClientException * @throws \Drupal\acquia_dam\Exception\DamConnectException * @throws \Drupal\acquia_dam\Exception\DamServerException * @throws \GuzzleHttp\Exception\GuzzleException */ public function removeIntegrationLink(string $uuid): void { try { $domain = $this->acquiaDamConfig->get('domain'); $this->request('DELETE', "https://$domain/api/rest/integrationlink/" . $uuid); } catch (\Exception $e) { $this->throwDamException($e); } } /** * Fetch the metadata according the field type. * * @param string $field_types * Field type of the metadata field. * * @return array|null * List of the field available under a particular field type. * * @throws \Drupal\acquia_dam\Exception\DamClientException * @throws \Drupal\acquia_dam\Exception\DamServerException * @throws \Drupal\acquia_dam\Exception\DamConnectException */ public function getDisplayKeys(string $field_types): ?array { try { $response = $this->get('/v2/metadata/fields/viewable?field_types=' . $field_types); $data = (string) $response->getBody(); } catch (\Exception $e) { $this->throwDamException($e); } return Json::decode($data); } /** * Fetch the vocabulary of a particular display key. * * @param string $display_key * Display key of the field. * * @return array|null * List of the available vocabulary items under the display key. * * @throws \Drupal\acquia_dam\Exception\DamClientException * @throws \Drupal\acquia_dam\Exception\DamServerException * @throws \Drupal\acquia_dam\Exception\DamConnectException */ public function getDisplayKeyVocabulary(string $display_key): ?array { try { $response = $this->get("/v2/metadata/$display_key/vocabulary"); $data = (string) $response->getBody(); } catch (\Exception $e) { $this->throwDamException($e); } return Json::decode($data); } /** * Fetches category information. * * @param string $category_path * Category path. * * @return array * List of the category items. * * @throws \Drupal\acquia_dam\Exception\DamClientException * @throws \Drupal\acquia_dam\Exception\DamServerException * @throws \Drupal\acquia_dam\Exception\DamConnectException */ public function getCategories(string $category_path = ''): array { try { $path = $category_path ? '/v2/categories/' . $category_path : '/v2/categories'; $response = $this->get($path); $data = (string) $response->getBody(); } catch (\Exception $e) { $this->throwDamException($e); } return Json::decode($data); } /** * Throws specific exception. * * @param \Exception $exception * Exception that occurred during request. * * @throws \Drupal\acquia_dam\Exception\DamClientException * @throws \Drupal\acquia_dam\Exception\DamConnectException * @throws \Drupal\acquia_dam\Exception\DamServerException */ protected function throwDamException(\Exception $exception): void { $this->damLoggerChannel->error($exception->getMessage()); if ($exception instanceof ClientException) { $response = $exception->getResponse(); $status = $response->getStatusCode(); $message = "API responded with status: $status. If the issue persist contact the site admin. Error message: {$exception->getMessage()}"; if ($status === 401) { $message = 'Unable to finish request due to authorization errors. If the issue persist contact the site admin.'; } if ($status === 408) { $message = 'Request timed out while trying to connect DAM API. If the issue persist contact the site admin.'; } throw new DamClientException($message, $status, $exception); } if ($exception instanceof ConnectException) { throw new DamConnectException('Unable to complete network request.', $exception->getCode(), $exception); } throw new DamServerException($exception->getMessage(), $exception->getCode(), $exception); } }