smsplatform-1.0.x-dev/src/Provider/DefaultSmsProvider.php
src/Provider/DefaultSmsProvider.php
<?php
declare(strict_types=1);
namespace Drupal\smsplatform\Provider;
use Drupal\smsplatform\Direction;
use Drupal\smsplatform\Entity\SmsGatewayInterface;
use Drupal\smsplatform\Entity\SmsMessage;
use Drupal\smsplatform\Entity\SmsMessageInterface as SmsMessageEntityInterface;
use Drupal\smsplatform\Event\SmsDeliveryReportEvent;
use Drupal\smsplatform\Event\SmsEvents;
use Drupal\smsplatform\Event\SmsMessageEvent;
use Drupal\smsplatform\Exception\SmsDirectionException;
use Drupal\smsplatform\Exception\SmsException;
use Drupal\smsplatform\Message\SmsMessageInterface;
use Drupal\smsplatform\Plugin\SmsGateway\SmsIncomingEventProcessorInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* The SMS provider that provides default messaging functionality.
*/
class DefaultSmsProvider implements SmsProviderInterface {
/**
* Creates a new instance of the default SMS provider.
*
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher
* The event dispatcher.
*/
public function __construct(
protected EventDispatcherInterface $eventDispatcher,
) {
}
/**
* {@inheritdoc}
*/
public function queue(SmsMessageInterface $sms_message) {
if (!$sms_message->getDirection()) {
throw new SmsDirectionException('Missing direction for message.');
}
$sms_messages = $this->dispatchEvent(SmsEvents::MESSAGE_PRE_PROCESS, [$sms_message])->getMessages();
$sms_messages = $this->dispatchEvent(SmsEvents::MESSAGE_QUEUE_PRE_PROCESS, $sms_messages)->getMessages();
foreach ($sms_messages as &$sms_message) {
// Tag so SmsEvents::MESSAGE_PRE_PROCESS is not dispatched again.
$sms_message->setOption('_skip_preprocess_event', TRUE);
// Validate SMS message entities.
if ($sms_message instanceof SmsMessageEntityInterface) {
$errors = [];
$violations = $sms_message->validate();
foreach ($violations->getFieldNames() as $field_name) {
foreach ($violations->getByField($field_name) as $violation) {
$errors[] = "[$field_name]: " . strip_tags((string) $violation->getMessage());
}
}
if ($errors) {
throw new SmsException(sprintf('Can not queue SMS message because there are %s validation error(s): %s', count($errors), implode(' ', $errors)));
}
}
if ($sms_message->getGateway()->getSkipQueue()) {
switch ($sms_message->getDirection()) {
case Direction::INCOMING:
$this->incoming($sms_message);
break;
case Direction::OUTGOING:
$this->send($sms_message);
break;
}
continue;
}
$sms_message = SmsMessage::convertFromSmsMessage($sms_message);
$sms_message->save();
}
// Queue has different post-process events because there is no result.
return $this->dispatchEvent(SmsEvents::MESSAGE_QUEUE_POST_PROCESS, $sms_messages)->getMessages();
}
/**
* {@inheritdoc}
*/
public function send(SmsMessageInterface $sms) {
$sms->setDirection(Direction::OUTGOING);
$dispatch = !$sms->getOption('_skip_preprocess_event');
$sms_messages = $dispatch ? $this->dispatchEvent(SmsEvents::MESSAGE_PRE_PROCESS, [$sms])->getMessages() : [$sms];
$sms_messages = $this->dispatchEvent(SmsEvents::MESSAGE_OUTGOING_PRE_PROCESS, $sms_messages)->getMessages();
// Iterate over messages individually since pre-process can modify the
// gateway used.
foreach ($sms_messages as $sms_message) {
$plugin = $sms_message->getGateway()->getPlugin();
$result = $plugin->send($sms_message);
if ($result === NULL) {
// @codingStandardsIgnoreLine
@trigger_error('Gateway plugins returning NULL is deprecated in smsplatform:2.1.0 and will be removed in smsplatform:3.0.0. The contract for \Drupal\smsplatform\Plugin\SmsGatewayPluginInterface::send does not permit returning NULL. See https://www.drupal.org/node/3262679', E_USER_DEPRECATED);
}
$sms_message->setResult($result);
$this->dispatchEvent(SmsEvents::MESSAGE_OUTGOING_POST_PROCESS, [$sms_message]);
$this->dispatchEvent(SmsEvents::MESSAGE_POST_PROCESS, [$sms_message]);
}
return $sms_messages;
}
/**
* {@inheritdoc}
*/
public function incoming(SmsMessageInterface $sms_message) {
$sms_message->setDirection(Direction::INCOMING);
// Do not iterate over messages individually like outgoing, changing gateway
// in pre-process events do not apply to incoming.
$plugin = $sms_message->getGateway()->getPlugin();
$dispatch = !$sms_message->getOption('_skip_preprocess_event');
$sms_messages = $dispatch ? $this->dispatchEvent(SmsEvents::MESSAGE_PRE_PROCESS, [$sms_message])->getMessages() : [$sms_message];
$sms_messages = $this->dispatchEvent(SmsEvents::MESSAGE_INCOMING_PRE_PROCESS, $sms_messages)->getMessages();
if ($plugin instanceof SmsIncomingEventProcessorInterface) {
$event = new SmsMessageEvent($sms_messages);
$plugin->incomingEvent($event);
}
$this->dispatchEvent(SmsEvents::MESSAGE_INCOMING_POST_PROCESS, $sms_messages);
$this->dispatchEvent(SmsEvents::MESSAGE_POST_PROCESS, $sms_messages);
return $sms_messages;
}
/**
* {@inheritdoc}
*/
public function processDeliveryReport(Request $request, SmsGatewayInterface $sms_gateway) {
$response = new Response();
$reports = $sms_gateway->getPlugin()
->parseDeliveryReports($request, $response);
$event = new SmsDeliveryReportEvent();
$event
->setResponse($response)
->setReports($reports);
$this->eventDispatcher
->dispatch($event, SmsEvents::DELIVERY_REPORT_POST_PROCESS);
return $event->getResponse();
}
/**
* Dispatch an SmsMessageEvent event for messages.
*
* @param string $event_name
* The event to trigger.
* @param \Drupal\smsplatform\Message\SmsMessageInterface[] $sms_messages
* The messages to dispatch.
*
* @return \Drupal\smsplatform\Event\SmsMessageEvent
* The dispatched event.
*/
protected function dispatchEvent($event_name, array $sms_messages) {
$event = new SmsMessageEvent($sms_messages);
return $this->eventDispatcher
->dispatch($event, $event_name);
}
}
