SmsMessageProcessor.php in SMS Framework 2.1.x
File
src/EventSubscriber/SmsMessageProcessor.php
View source
<?php
declare (strict_types=1);
namespace Drupal\sms\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\sms\Entity\SmsGatewayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\sms\Direction;
use Drupal\sms\Event\RecipientGatewayEvent;
use Drupal\sms\Event\SmsMessageEvent;
use Drupal\sms\Exception\RecipientRouteException;
use Drupal\sms\Exception\SmsException;
use Drupal\sms\Exception\SmsPluginReportException;
use Drupal\sms\Entity\SmsGateway;
use Drupal\sms\Event\SmsEvents;
use Drupal\sms\Message\SmsDeliveryReportInterface;
use Drupal\sms\Message\SmsMessageInterface;
use Drupal\sms\Message\SmsMessageResultInterface;
class SmsMessageProcessor implements EventSubscriberInterface {
protected $eventDispatcher;
protected $configFactory;
public function __construct(EventDispatcherInterface $event_dispatcher, ConfigFactoryInterface $config_factory) {
$this->eventDispatcher = $event_dispatcher;
$this->configFactory = $config_factory;
}
public function ensureIncomingSupport(SmsMessageEvent $event) {
$sms_messages = $event
->getMessages();
foreach ($sms_messages as $sms_message) {
if ($sms_message
->getDirection() == Direction::INCOMING) {
$gateway = $sms_message
->getGateway();
if (!$gateway instanceof SmsGatewayInterface) {
throw new SmsException('Gateway not set on incoming message');
}
if (!$gateway
->supportsIncoming()) {
throw new SmsException(sprintf('Gateway `%s` does not support incoming messages.', $gateway
->id()));
}
}
}
}
public function ensureReportsPreprocess(SmsMessageEvent $event) {
$sms_messages = $event
->getMessages();
foreach ($sms_messages as $sms_message) {
if ($sms_message
->getDirection() == Direction::INCOMING) {
$this
->ensureReports($sms_message);
}
}
}
public function ensureReportsPostprocess(SmsMessageEvent $event) {
$sms_messages = $event
->getMessages();
foreach ($sms_messages as $sms_message) {
$this
->ensureReports($sms_message);
}
}
protected function ensureReports(SmsMessageInterface $sms_message) {
$result = $sms_message
->getResult();
if (!$result instanceof SmsMessageResultInterface) {
throw new SmsPluginReportException('Missing result for message.');
}
$message_recipients = $sms_message
->getRecipients();
$result_recipients = array_map(function (SmsDeliveryReportInterface $report) {
return $report
->getRecipient();
}, $result
->getReports());
$difference_count = count(array_diff($message_recipients, $result_recipients));
if ($difference_count) {
throw new SmsPluginReportException(sprintf('Missing reports for %s recipient(s).', $difference_count));
}
}
public function ensureRecipients(SmsMessageEvent $event) {
$sms_messages = $event
->getMessages();
foreach ($sms_messages as $sms_message) {
if ($sms_message
->getDirection() == Direction::OUTGOING) {
$recipients = $sms_message
->getRecipients();
if (!count($recipients)) {
throw new RecipientRouteException(sprintf('There are no recipients.'));
}
}
}
}
public function ensureGateways(SmsMessageEvent $event) {
$sms_messages = $event
->getMessages();
$result = [];
foreach ($sms_messages as $k => $sms_message) {
if ($sms_message
->getGateway() instanceof SmsGatewayInterface) {
unset($sms_messages[$k]);
$result[] = $sms_message;
}
}
foreach ($sms_messages as $sms_message) {
$gateways = [];
$recipients_all = $sms_message
->getRecipients();
foreach ($recipients_all as $recipient) {
$gateway = $this
->getGatewayForPhoneNumber($recipient);
if ($gateway instanceof SmsGatewayInterface) {
$gateways[$gateway
->id()][] = $recipient;
}
else {
$event
->stopPropagation();
throw new RecipientRouteException(sprintf('Unable to determine gateway for recipient %s.', $recipient));
}
}
$base = $sms_message instanceof EntityInterface ? $sms_message
->createDuplicate() : clone $sms_message;
$base
->removeRecipients($recipients_all);
foreach ($gateways as $gateway_id => $recipients) {
$new = $base instanceof EntityInterface ? $base
->createDuplicate() : clone $base;
$result[] = $new
->addRecipients($recipients)
->setGateway(SmsGateway::load($gateway_id));
}
}
$event
->setMessages($result);
}
protected function getGatewayForPhoneNumber($recipient) {
$event = new RecipientGatewayEvent($recipient);
$event = $this->eventDispatcher
->dispatch(SmsEvents::MESSAGE_GATEWAY, $event);
$gateways = $event
->getGatewaysSorted();
$gateway = array_shift($gateways);
if ($gateway instanceof SmsGatewayInterface) {
return $gateway;
}
$gateway_id = $this->configFactory
->get('sms.settings')
->get('fallback_gateway');
return isset($gateway_id) ? SmsGateway::load($gateway_id) : NULL;
}
public function deliveryReportUrl(SmsMessageEvent $event) {
foreach ($event
->getMessages() as &$sms_message) {
if (!$sms_message
->getOption('delivery_report_url')) {
$url = $sms_message
->getGateway()
->getPushReportUrl();
try {
$url = $url
->setAbsolute()
->toString();
$sms_message
->setOption('delivery_report_url', $url);
} catch (RouteNotFoundException $e) {
}
}
}
}
public function chunkMaxRecipients(SmsMessageEvent $event) {
$result = [];
foreach ($event
->getMessages() as $sms_message) {
if ($sms_message
->getDirection() == Direction::OUTGOING) {
$max = $sms_message
->getGateway()
->getMaxRecipientsOutgoing();
$result = array_merge($result, $sms_message
->chunkByRecipients($max));
}
else {
$result[] = $sms_message;
}
}
$event
->setMessages($result);
}
public static function getSubscribedEvents() {
$events[SmsEvents::MESSAGE_PRE_PROCESS][] = [
'ensureIncomingSupport',
1024,
];
$events[SmsEvents::MESSAGE_PRE_PROCESS][] = [
'ensureReportsPreprocess',
1024,
];
$events[SmsEvents::MESSAGE_PRE_PROCESS][] = [
'ensureRecipients',
1024,
];
$events[SmsEvents::MESSAGE_PRE_PROCESS][] = [
'ensureGateways',
1024,
];
$events[SmsEvents::MESSAGE_PRE_PROCESS][] = [
'deliveryReportUrl',
];
$events[SmsEvents::MESSAGE_PRE_PROCESS][] = [
'chunkMaxRecipients',
-1024,
];
$events[SmsEvents::MESSAGE_OUTGOING_POST_PROCESS][] = [
'ensureReportsPostprocess',
1024,
];
return $events;
}
}