ww_publish-8.x-1.x-dev/src/Event/SnsNotificationSubscriber.php
src/Event/SnsNotificationSubscriber.php
<?php
namespace Drupal\ww_publish\Event;
use Aws\Sns\Message;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\DestructableInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Utility\Error;
use Drupal\user\Entity\User;
use Drupal\ww_publish\Entity\SnsMessageEntity;
use Drupal\ww_publish\Entity\SnsMessageEntityInterface;
use Drupal\ww_publish\Job;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\amazon_sns\Event\SnsEvents as AmazonSnsEvents;
use Drupal\amazon_sns\Event\SnsMessageEvent as AmazonSnsMessageEvent;
/**
* Class SnsNotificationSubscriber.
*
* Subscribe to SNS notification events. These are in response to events
* dispatched by NotificationController::receive(). This file is based on
* \Drupal\amazon_sns\Event\SnsNotificationSubscriber.
*
* @package Drupal\ww_publish\Event
*/
class SnsNotificationSubscriber implements EventSubscriberInterface, DestructableInterface {
/**
* A logger instance.
*
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* Configuration of the ww_publish module.
*
* @var \Drupal\Core\Config\Config
*/
protected $config;
/**
* The job importer service.
*
* @var \Drupal\ww_publish\Job
*/
protected $job;
/**
* Event messages to be imported in the destruct method.
*
* @var \Drupal\ww_publish\Entity\SnsMessageEntityInterface[]
*/
protected $eventMessages = [];
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array {
return [
AmazonSnsEvents::NOTIFICATION => 'processSnsMessageEvent',
];
}
/**
* SnsNotificationSubscriber constructor.
*
* @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_factory
* The logger factory service.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* A config factory.
* @param \Drupal\ww_publish\Job $job
* The job importer service.
*/
public function __construct(LoggerChannelFactoryInterface $logger_factory, ConfigFactoryInterface $config_factory, Job $job) {
$this->logger = $logger_factory->get('ww_publish');
$this->config = $config_factory->get('ww_publish.settings');
// Set user for logger.
if ($userId = $this->config->get('ww_user')) {
$currentUser = User::load($userId);
$this->logger->setCurrentUser($currentUser);
}
$this->job = $job;
}
/**
* Process the SNS message event.
*
* @param \Drupal\amazon_sns\Event\SnsMessageEvent $event
* Publish message received from Amazon SNS.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
public function processSnsMessageEvent(AmazonSnsMessageEvent $event) {
$eventMessage = $event->getMessage();
if ($this->isValidMessage($eventMessage)) {
$eventMessage = json_decode($eventMessage['Message']);
if ($this->config->get('debug_mode'))
$this->logger->debug('Amazon SNS message event: <pre><code>' . print_r($eventMessage, TRUE) . '</code></pre>');
if (!($snsMessageEntity = SnsMessageEntity::load($eventMessage->id))) {
$snsMessageEntity = SnsMessageEntity::create(['id' => $eventMessage->id]);
}
$keyPropertyMap = [
'name' => 'name',
'url' => 'url',
'metadata_url' => 'metadataUrl',
'article_json_url' => 'articleJsonUrl',
'tenant_id' => 'tenantId',
'brand' => 'brand'
];
foreach ($keyPropertyMap as $setKey => $objProperty) {
if (property_exists($eventMessage, $objProperty)) {
$snsMessageEntity->set($setKey, $eventMessage->{$objProperty});
}
}
$snsMessageEntity->set('status', SnsMessageEntityInterface::NEW);
$snsMessageEntity->save();
if (!$this->config->get('cron_mode')) {
$this->eventMessages[] = $snsMessageEntity;
}
}
}
/**
* Check that the message is valid to be sent.
*
* @param \Aws\Sns\Message $eventMessage
* The message received from Amazon SNS.
*
* @return bool
* TRUE if this is a valid message that should be imported, FALSE if not.
*/
protected function isValidMessage(Message $eventMessage) {
if ($this->config->get('topic_arn')) {
foreach ($this->config->get('topic_arn') as $topic_arn) {
if (\strpos($eventMessage['TopicArn'], $topic_arn) === 0) {
return TRUE;
}
}
}
if (!$this->config->get('topic_arn') && strpos($eventMessage['TopicArn'], 'ecs-export-topic') > 0) {
$this->logger->warning('Accepted unconfirmed sns message from TopicArn @topicarn.', ['@topicarn' => $eventMessage['TopicArn']]);
return TRUE;
}
// Log an error message if a topic arn is configured and it does not
// match the explicitly configured topic but does match the ecs-export-topic
// pattern or no topic is configured.
if (!$this->config->get('topic_arn') || strpos($eventMessage['TopicArn'], 'ecs-export-topic') > 0) {
$this->logger->error('Not processing Amazon SNS message with TopicArn @topicarn.', ['@topicarn' => $eventMessage['TopicArn']]);
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function destruct() {
foreach ($this->eventMessages as $eventMessage) {
try {
$this->job->publishArticle($eventMessage->id());
}
catch (\Throwable $e) {
$variables = Error::decodeException($e);
$this->logger->error('%type: @message in %function (line %line of %file).', $variables);
}
}
}
}
