View source
<?php
namespace Drupal\acquia_contenthub\Client;
use Acquia\ContentHubClient\CDF\ClientCDFObject;
use Acquia\ContentHubClient\ContentHubClient;
use Acquia\ContentHubClient\Settings;
use Acquia\Hmac\Exception\KeyNotFoundException;
use Acquia\Hmac\KeyLoader;
use Acquia\Hmac\RequestAuthenticator;
use Drupal\acquia_contenthub\AcquiaContentHubEvents;
use Drupal\acquia_contenthub\Event\AcquiaContentHubSettingsEvent;
use Drupal\acquia_contenthub\Event\BuildClientCdfEvent;
use Drupal\Component\Uuid\Uuid;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\ModuleExtensionList;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Laminas\Diactoros\ResponseFactory;
use Laminas\Diactoros\ServerRequestFactory;
use Laminas\Diactoros\StreamFactory;
use Laminas\Diactoros\UploadedFileFactory;
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
class ClientFactory {
protected $dispatcher;
protected $client;
protected $settingsProvider;
protected $settings;
protected $loggerFactory;
protected $clientCDFObject;
protected $moduleList;
protected $config;
public function __construct(EventDispatcherInterface $dispatcher, LoggerChannelFactoryInterface $logger_factory, ModuleExtensionList $module_list, ConfigFactoryInterface $config_factory) {
$this->dispatcher = $dispatcher;
$this->loggerFactory = $logger_factory;
$this->moduleList = $module_list;
$this->config = $config_factory
->get('acquia_contenthub.admin_settings');
$this
->populateSettings();
}
protected function populateSettings() {
$event = new AcquiaContentHubSettingsEvent();
$this->dispatcher
->dispatch(AcquiaContentHubEvents::GET_SETTINGS, $event);
$this->settings = $event
->getSettings();
$this->settingsProvider = $event
->getProvider();
}
public function isConfigurationSet(Settings $settings = NULL) : bool {
$settings = $settings ?? $this
->getSettings();
if (!$settings || !Uuid::isValid($settings
->getUuid()) || empty($settings
->getName()) || empty($settings
->getUrl()) || empty($settings
->getApiKey()) || empty($settings
->getSecretKey())) {
return FALSE;
}
return TRUE;
}
public function getClient(Settings $settings = NULL) {
$validate = (bool) (!$settings);
if (!$settings) {
if (isset($this->client)) {
return $this->client;
}
$settings = $this
->getSettings();
}
if (!$this
->isConfigurationSet($settings)) {
return FALSE;
}
$languages_ids = array_keys(\Drupal::languageManager()
->getLanguages());
array_push($languages_ids, ClientCDFObject::LANGUAGE_UNDETERMINED);
$config = [
'base_url' => $settings
->getUrl(),
'client-languages' => $languages_ids,
'client-user-agent' => $this
->getClientUserAgent(),
];
$this->client = new ContentHubClient($config, $this->loggerFactory
->get('acquia_contenthub'), $settings, $settings
->getMiddleware(), $this->dispatcher);
$send_update = $this->config
->get('send_contenthub_updates') ?? TRUE;
if ($validate && $send_update && $this->client
->getRemoteSettings()) {
$event = new BuildClientCdfEvent(ClientCDFObject::create($settings
->getUuid(), [
'settings' => $settings
->toArray(),
]));
$this->dispatcher
->dispatch(AcquiaContentHubEvents::BUILD_CLIENT_CDF, $event);
$this->clientCDFObject = $event
->getCdf();
$this
->updateClientCdf();
}
return $this->client;
}
protected function getClientUserAgent() {
$module_info = $this->moduleList
->getExtensionInfo('acquia_contenthub');
$module_version = isset($module_info['version']) ? $module_info['version'] : '0.0.0';
$drupal_version = isset($module_info['core']) ? $module_info['core'] : '0.0.0';
return 'AcquiaContentHub/' . $drupal_version . '-' . $module_version;
}
public function getProvider() {
return $this->settingsProvider;
}
public function getSettings() {
return $this->settings;
}
public function authenticate(Request $request) {
if (!$this
->getClient()) {
return FALSE;
}
$keys = [
$this->client
->getSettings()
->getApiKey() => $this->client
->getSettings()
->getSecretKey(),
'Webhook' => $this->client
->getSettings()
->getSharedSecret(),
];
$keyLoader = new KeyLoader($keys);
$authenticator = new RequestAuthenticator($keyLoader);
if (class_exists(DiactorosFactory::class)) {
$httpMessageFactory = new DiactorosFactory();
}
else {
$httpMessageFactory = new PsrHttpFactory(new ServerRequestFactory(), new StreamFactory(), new UploadedFileFactory(), new ResponseFactory());
}
$psr7_request = $httpMessageFactory
->createRequest($request);
try {
return $authenticator
->authenticate($psr7_request);
} catch (KeyNotFoundException $exception) {
$this->loggerFactory
->get('acquia_contenthub')
->debug('HMAC validation failed. [authorization_header = %authorization_header]', [
'%authorization_header' => $request->headers
->get('authorization'),
]);
}
return FALSE;
}
public function updateClientCdf() {
$remote_cdf = $this->client
->getEntity($this->settings
->getUuid());
if ($remote_cdf instanceof ClientCDFObject && $remote_cdf
->getAttribute('hash') && $remote_cdf
->getAttribute('hash')
->getValue()['und'] === $this->clientCDFObject
->getAttribute('hash')
->getValue()['und']) {
return TRUE;
}
$response = $this->client
->putEntities($this->clientCDFObject);
if ($response
->getStatusCode() === 202) {
return TRUE;
}
else {
$this->loggerFactory
->get('acquia_contenthub')
->debug('Updating clientCDF failed with http status %error', [
'%error' => $response
->getStatusCode(),
]);
return FALSE;
}
}
public function registerClient(string $name, string $url, string $api_key, string $secret, string $api_version = 'v2') {
return ContentHubClient::register($this->loggerFactory
->get('acquia_contenthub'), $this->dispatcher, $name, $url, $api_key, $secret, $api_version);
}
}