class ContentHubConnectionManager in Acquia Content Hub 8.2
Responsible for connection management actions.
@package Drupal\acquia_contenthub
Hierarchy
- class \Drupal\acquia_contenthub\ContentHubConnectionManager
Expanded class hierarchy of ContentHubConnectionManager
4 files declare their use of ContentHubConnectionManager
- AcquiaContentHubSiteCommands.php in src/
Commands/ AcquiaContentHubSiteCommands.php - AcquiaContentHubWebhookInterestCommands.php in src/
Commands/ AcquiaContentHubWebhookInterestCommands.php - ContentHubDeleteClientConfirmForm.php in src/
Form/ ContentHubDeleteClientConfirmForm.php - ContentHubSettingsForm.php in src/
Form/ ContentHubSettingsForm.php
1 string reference to 'ContentHubConnectionManager'
1 service uses ContentHubConnectionManager
File
- src/
ContentHubConnectionManager.php, line 19
Namespace
Drupal\acquia_contenthubView source
class ContentHubConnectionManager {
/**
* Default cloud filter prefix.
*
* @var string
*/
const DEFAULT_FILTER = 'default_filter_';
/**
* Error code received when trying to create a webhook that already exists.
*
* @var integer
*/
const WEBHOOK_ALREADY_EXISTS = 4010;
/**
* The Config Factory Interface.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* The ContentHub client factory.
*
* @var \Drupal\acquia_contenthub\Client\ClientFactory
*/
protected $factory;
/**
* The Content Hub Client.
*
* @var \Acquia\ContentHubClient\ContentHubClient
*/
protected $client;
/**
* The acquia_contenthub logger channel.
*
* @var \Drupal\Core\Logger\LoggerChannelInterface
*/
protected $logger;
/**
* The Content Hub settings.
*
* @var \Acquia\ContentHubClient\Settings
*/
protected $settings;
/**
* ContentHubConnectionManager constructor.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The Config Factory.
* @param \Drupal\acquia_contenthub\Client\ClientFactory $factory
* The ContentHub client factory.
* @param \Psr\Log\LoggerInterface $logger
* The logger channel.
* @param \Acquia\ContentHubClient\Settings $settings
* The settings object constructed from Content Hub settings form.
*/
public function __construct(ConfigFactoryInterface $config_factory, ClientFactory $factory, LoggerInterface $logger, Settings $settings) {
$this->configFactory = $config_factory;
$this->factory = $factory;
$this->logger = $logger;
$this->settings = $settings;
}
/**
* Initializes the Connection Manager.
*/
public function initialize() {
if (empty($this->client)) {
$client = $this->factory
->getClient();
$this
->setClient($client);
}
}
/**
* Sets the client.
*
* It is acquired through ClientFactory:getClient() method.
* However this can also be FALSE, therefore it is recommended to make sure
* the client is bootstrapped before the connection manager is being used.
*
* @param \Acquia\ContentHubClient\ContentHubClient|false $client
* The Content Hub client if it's already been configured, FALSE otherwise.
*/
public function setClient($client) {
$this->client = $client;
}
/**
* Obtains the Content Hub Admin Settings Configuration.
*
* @return \Drupal\Core\Config\Config
* The Editable Content Hub Admin Settings Configuration.
*/
protected function getContentHubConfig() {
return $this->configFactory
->getEditable('acquia_contenthub.admin_settings');
}
/**
* Registers a webhook if it has not been registered already.
*
* @param string $webhook_url
* The webhook url with to register. Provide the full route
* (/acquia-contenthub/webhook).
*
* @return array
* The response of the attempt.
*
* @throws \Exception
*/
public function registerWebhook(string $webhook_url) : array {
$this
->initialize();
$response = $this->client
->addWebhook($webhook_url);
if (isset($response['success']) && $response['success'] === FALSE) {
if (isset($response['error']['code']) && $response['error']['code'] === self::WEBHOOK_ALREADY_EXISTS) {
$wh = $this->client
->getWebHook($webhook_url);
$response['uuid'] = $wh
->getUuid();
}
else {
$this->logger
->error('Unable to register Webhook URL = @url, Error @e_code: "@e_message".', [
'@url' => $webhook_url,
'@e_code' => $response['error']['code'],
'@e_message' => $response['error']['message'],
]);
return [];
}
}
$this
->addDefaultFilterToWebhook($response['uuid']);
// Save Webhook Configuration.
$this
->saveWebhookConfig($response['uuid'], $webhook_url);
return $response;
}
/**
* Adds default filter to a Webhook.
*
* @param string $webhook_uuid
* The webhook UUID.
*
* @throws \Exception
*/
public function addDefaultFilterToWebhook(string $webhook_uuid) : void {
$this
->initialize();
$filter_name = self::DEFAULT_FILTER . $this->client
->getSettings()
->getName();
$filter = $this
->createDefaultFilter($filter_name);
$list = $this->client
->listFiltersForWebhook($webhook_uuid);
if (isset($filter['uuid']) && is_array($list['data']) && in_array($filter['uuid'], $list['data'], TRUE)) {
// The default filter is already attached to the current webhook.
return;
}
// Default Filter for the current client exists but is not attached to this
// client's webhook.
if (!isset($filter['uuid'])) {
return;
}
$response = $this->client
->addFilterToWebhook($filter['uuid'], $webhook_uuid);
if (isset($response['success']) && $response['success'] === FALSE) {
$this->logger
->error('Could not add default filter "@d_filter" to Webhook UUID = "@whuuid". Reason: "@reason"', [
'@d_filter' => $filter_name,
'@whuuid' => $webhook_uuid,
'@reason' => $response['error']['message'],
]);
return;
}
$this->logger
->notice('Added filter "@filter" (@uuid) to Webhook UUID = "@whuuid".', [
'@filter' => $filter_name,
'@uuid' => $filter['uuid'],
'@whuuid' => $webhook_uuid,
]);
}
/**
* Updates the specified webhook on Content Hub.
*
* @param string $webhook_url
* The webhook to update.
*
* @return array
* The response of the attempt.
*
* @throws \Exception
*/
public function updateWebhook(string $webhook_url) : array {
$this
->initialize();
if (!$this
->webhookIsRegistered($this->settings
->getWebhook('url'))) {
return $this
->registerWebhook($webhook_url);
}
if ($this
->webhookIsRegistered($webhook_url)) {
$this->logger
->error('The webhook @webhook has already been registered!', [
'@webhook' => $webhook_url,
]);
return [];
}
$options['url'] = $webhook_url;
$response = $this
->handleResponse($this->client
->updateWebhook($this->settings
->getWebhook('uuid'), $options));
if (!isset($response['success'])) {
$this->logger
->error('Unexpected error occurred during webhook update. Response: @resp', [
'@resp' => print_r($response),
]);
return [];
}
if ($response['success'] === FALSE) {
if (!isset($response['error']['message'])) {
$this->logger
->error('Unable to update URL %url, Unable to connect to Content Hub.', [
'%url' => $webhook_url,
]);
return [];
}
$this->logger
->error('Unable to update URL %url, Error %error: %error_message.', [
'%url' => $webhook_url,
'%error' => $response['error']['code'],
'%error_message' => $response['error']['message'],
]);
return [];
}
$this->logger
->notice('Webhook url @old has been successfully updated to @new', [
'@old' => $this->settings
->getWebhook('settings_url'),
'@new' => $webhook_url,
]);
$this
->saveWebhookConfig($response['uuid'], $webhook_url);
return $response['data'] ?? $response;
}
/**
* Unregisters the client.
*
* @param \Drupal\acquia_contenthub\Event\AcquiaContentHubUnregisterEvent $event
* ACH unregister event.
*
* @return bool
* TRUE if unregister is successful, FALSE otherwise.
*
* @throws \Exception
*/
public function unregister(AcquiaContentHubUnregisterEvent $event) : bool {
$this
->initialize();
$this->settings = $this->client
->getSettings();
$success = $this
->unregisterWebhook($event, TRUE);
if (!$success) {
$this->logger
->error('Some error occurred during webhook deletion.');
return FALSE;
}
$client_uuid = empty($event
->getOriginUuid()) ? $this->settings
->getUuid() : $event
->getOriginUuid();
$client_name = $event
->getClientName();
$resp = $this->client
->deleteClient($client_uuid);
if ($resp instanceof ResponseInterface && $resp
->getStatusCode() !== Response::HTTP_OK) {
$this->logger
->error('Could not delete client: @e_message', [
'@e_message' => $resp
->getReasonPhrase(),
]);
return FALSE;
}
$this->logger
->notice('Successfully unregistered client @client', [
'@client' => $client_name,
]);
// If origin is set, then we unregister a different site, do not delete
// the config on this.
if (!$event
->getOriginUuid()) {
$this
->getContentHubConfig()
->delete();
}
return TRUE;
}
/**
* Unregisters the webhook url assigned to this site.
*
* @param \Drupal\acquia_contenthub\Event\AcquiaContentHubUnregisterEvent $event
* AcquiaContentHubUnregisterEvent instance.
* @param bool $delete_orphaned_filters
* TRUE if orphaned filters should be deleted, FALSE otherwise.
*
* @return bool
* TRUE, if un-registration is successful, FALSE otherwise.
*/
public function unregisterWebhook(AcquiaContentHubUnregisterEvent $event, bool $delete_orphaned_filters = FALSE) : bool {
$this
->initialize();
$resp = $this->client
->deleteWebhook($event
->getWebhookUuid());
if ($resp instanceof ResponseInterface && $resp
->getStatusCode() !== Response::HTTP_OK) {
$this->logger
->error('Could not unregister webhook: @e_message', [
'@e_message' => $resp
->getReasonPhrase(),
]);
return FALSE;
}
// Clears the webhook configuration.
$this
->getContentHubConfig()
->clear('webhook')
->save();
$resp = $this->client
->deleteFilter($event
->getDefaultFilter());
if ($resp instanceof ResponseInterface && $resp
->getStatusCode() !== Response::HTTP_OK) {
$this->logger
->error('Could not delete default filter for webhook: @e_message', [
'@e_message' => $resp
->getReasonPhrase(),
]);
return FALSE;
}
if ($delete_orphaned_filters) {
foreach ($event
->getOrphanedFilters() as $filter_id) {
if ($this->client
->deleteFilter($filter_id) instanceof ResponseInterface && $resp
->getStatusCode() !== Response::HTTP_OK) {
$this->logger
->error('
Could not delete orphaned filter (@filter) for webhook: @e_message', [
'@e_message' => $resp
->getReasonPhrase(),
'@filter' => $filter_id,
]);
return FALSE;
}
}
}
return TRUE;
}
/**
* Check if client successfully registered.
*
* Check client first if needed before any action.
*
* @return $this
* Returns itself for the sake of chainability.
*
* @throws \RuntimeException
* @throws \Exception
*/
public function checkClient() : self {
$this
->initialize();
if (is_null($this->client)) {
throw new \RuntimeException('Client is not configured.');
}
$resp = $this->client
->ping();
if (!empty($resp)) {
throw new \RuntimeException('Client could not reach Content Hub.');
}
return $this;
}
/**
* Creates default filter for the site.
*
* @param string $filter_name
* The name of the filter.
*
* @return array
* The response of the attempt.
*
* @throws \Exception
*/
protected function createDefaultFilter(string $filter_name) {
$this
->initialize();
$filter = $this->client
->getFilterByName($filter_name);
// Only create default filter if it does not exist yet for the current
// client.
if (empty($filter['uuid'])) {
$site_origin = $this->client
->getSettings()
->getUuid();
$filter_query = [
'bool' => [
'should' => [
[
'match' => [
'data.attributes.channels.value.und' => $site_origin,
],
],
[
'match' => [
'data.origin' => $site_origin,
],
],
],
],
];
$filter = $this->client
->putFilter($filter_query, $filter_name);
}
return $filter;
}
/**
* Checks whether the webhook has already been registered.
*
* @param string $webhook_url
* The webhook's url.
*
* @return bool
* TRUE if the webhook is registered.
*
* @throws \Exception
*/
public function webhookIsRegistered(string $webhook_url) : bool {
$this
->initialize();
$resp = $this->client
->getWebHook($webhook_url);
return !empty($resp);
}
/**
* Remove webhook suppression.
*
* @param string $webhook_uuid
* Webhook uuid.
*
* @return bool
* TRUE if we get the response with success TRUE value.
*/
public function removeWebhookSuppression(string $webhook_uuid) : bool {
$this
->initialize();
$response_body = $this->client
->unSuppressWebhook($webhook_uuid);
if (!empty($response_body) && $response_body['success'] === TRUE) {
return TRUE;
}
if (empty($response_body)) {
$this->logger
->error('DELETE request against webhook suppression endpoint returned with an empty body.');
return FALSE;
}
$this->logger
->error('Could not register with environment variables: @e_message', [
'@e_message' => $response_body['error']['message'],
]);
return FALSE;
}
/**
* Suppress webhook.
*
* @param string $webhook_uuid
* Webhook uuid.
*
* @return bool
* TRUE if we get the response with success TRUE value.
*/
public function suppressWebhook(string $webhook_uuid) : bool {
$this
->initialize();
$response_body = $this->client
->suppressWebhook($webhook_uuid);
if (!empty($response_body) && $response_body['success'] === TRUE) {
return TRUE;
}
if (empty($response_body)) {
$this->logger
->error('PUT request against webhook suppression endpoint returned with an empty body.');
return FALSE;
}
$this->logger
->error('Something went wrong during webhook suppression: @e_message', [
'@e_message' => $response_body['error']['message'],
]);
return FALSE;
}
/**
* Handles incoming response.
*
* A response can either contain a json body which has the data,
* or a reason phrase containing the error message. In some cases the latter
* one can also come in an array structure.
*
* @param \Psr\Http\Message\ResponseInterface $response
* The response object.
*
* @return array
* The response decoded into array.
*/
protected function handleResponse(ResponseInterface $response) : array {
$body = json_decode((string) $response
->getBody(), TRUE);
if (empty($body)) {
return [
'success' => FALSE,
'error' => [
'message' => $response
->getReasonPhrase(),
],
];
}
return $body;
}
/**
* Saves webhook modifications to configuration.
*
* @param string $uuid
* Webhook uuid.
* @param string $url
* Webhook url.
*/
protected function saveWebhookConfig(string $uuid, string $url) : void {
$this
->initialize();
$wh_path = Url::fromRoute('acquia_contenthub.webhook')
->toString();
$settings_url = str_replace($wh_path, '', $url);
$webhook = [
'uuid' => $uuid,
'url' => $url,
'settings_url' => $settings_url,
];
$this
->getContentHubConfig()
->set('webhook', $webhook)
->save();
}
/**
* Synchronizes this webhook's interest list with tracking table.
*/
public function syncWebhookInterestListWithTrackingTables() {
$this
->initialize();
$database = \Drupal::database();
$module_handler = \Drupal::moduleHandler();
$config = $this
->getContentHubConfig();
$webhook_uuid = $config
->get("webhook.uuid");
$send_update = $config
->get('send_contenthub_updates') ?? TRUE;
// If subscriber.
if ($module_handler
->moduleExists('acquia_contenthub_subscriber')) {
$query = $database
->select('acquia_contenthub_subscriber_import_tracking', 't')
->fields('t', [
'entity_uuid',
]);
$query
->condition('status', 'imported');
$results = $query
->execute()
->fetchAll();
$uuids = [];
foreach ($results as $result) {
$uuids[] = $result->entity_uuid;
}
if (!empty($uuids) && $send_update) {
$this->client
->addEntitiesToInterestList($webhook_uuid, $uuids);
$this->logger
->notice('Added @count imported entities to interest list for webhook uuid = "@webhook_uuid".', [
'@count' => count($uuids),
'@webhook_uuid' => $webhook_uuid,
]);
}
}
// If publisher.
if ($module_handler
->moduleExists('acquia_contenthub_publisher')) {
$query = $database
->select('acquia_contenthub_publisher_export_tracking', 't')
->fields('t', [
'entity_uuid',
]);
$query
->condition('status', [
'imported',
'confirmed',
], 'IN');
$results = $query
->execute()
->fetchAll();
$uuids = [];
foreach ($results as $result) {
$uuids[] = $result->entity_uuid;
}
if (!empty($uuids) && $send_update) {
$this->client
->addEntitiesToInterestList($webhook_uuid, $uuids);
$this->logger
->notice('Added @count exported entities to interest list for webhook uuid = "@webhook_uuid".', [
'@count' => count($uuids),
'@webhook_uuid' => $webhook_uuid,
]);
}
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
ContentHubConnectionManager:: |
protected | property | The Content Hub Client. | |
ContentHubConnectionManager:: |
protected | property | The Config Factory Interface. | |
ContentHubConnectionManager:: |
protected | property | The ContentHub client factory. | |
ContentHubConnectionManager:: |
protected | property | The acquia_contenthub logger channel. | |
ContentHubConnectionManager:: |
protected | property | The Content Hub settings. | |
ContentHubConnectionManager:: |
public | function | Adds default filter to a Webhook. | |
ContentHubConnectionManager:: |
public | function | Check if client successfully registered. | |
ContentHubConnectionManager:: |
protected | function | Creates default filter for the site. | |
ContentHubConnectionManager:: |
constant | Default cloud filter prefix. | ||
ContentHubConnectionManager:: |
protected | function | Obtains the Content Hub Admin Settings Configuration. | |
ContentHubConnectionManager:: |
protected | function | Handles incoming response. | |
ContentHubConnectionManager:: |
public | function | Initializes the Connection Manager. | |
ContentHubConnectionManager:: |
public | function | Registers a webhook if it has not been registered already. | |
ContentHubConnectionManager:: |
public | function | Remove webhook suppression. | |
ContentHubConnectionManager:: |
protected | function | Saves webhook modifications to configuration. | |
ContentHubConnectionManager:: |
public | function | Sets the client. | |
ContentHubConnectionManager:: |
public | function | Suppress webhook. | |
ContentHubConnectionManager:: |
public | function | Synchronizes this webhook's interest list with tracking table. | |
ContentHubConnectionManager:: |
public | function | Unregisters the client. | |
ContentHubConnectionManager:: |
public | function | Unregisters the webhook url assigned to this site. | |
ContentHubConnectionManager:: |
public | function | Updates the specified webhook on Content Hub. | |
ContentHubConnectionManager:: |
public | function | Checks whether the webhook has already been registered. | |
ContentHubConnectionManager:: |
constant | Error code received when trying to create a webhook that already exists. | ||
ContentHubConnectionManager:: |
public | function | ContentHubConnectionManager constructor. |