farm-2.x-dev/modules/core/data_stream/modules/notification/src/EventSubscriber/DataStreamEventSubscriber.php
modules/core/data_stream/modules/notification/src/EventSubscriber/DataStreamEventSubscriber.php
<?php
namespace Drupal\data_stream_notification\EventSubscriber;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\data_stream\Event\DataStreamEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Event subscriber for data stream events.
*
* Dispatches data stream notifications.
*/
class DataStreamEventSubscriber implements EventSubscriberInterface {
/**
* The data stream notification entity storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $notificationStorage;
/**
* Constructs a DataStreamEventSubscriber object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager service.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->notificationStorage = $entity_type_manager->getStorage('data_stream_notification');
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
DataStreamEvent::DATA_RECEIVE => 'onDataReceive',
];
}
/**
* Trigger notifications when data is received.
*
* @param \Drupal\data_stream\Event\DataStreamEvent $event
* The data stream event.
*/
public function onDataReceive(DataStreamEvent $event) {
// Load any notifications configured for the data stream.
/** @var \Drupal\data_stream_notification\Entity\DataStreamNotificationInterface[] $notifications */
$notifications = $this->notificationStorage->loadByProperties([
'status' => TRUE,
'data_stream' => $event->dataStream->id(),
]);
// Bail if there are none.
if (empty($notifications)) {
return;
}
// Execute all notifications.
foreach ($notifications as $notification) {
$conditions_met = FALSE;
// Include the notification in the event context.
$event->context['data_stream_notification'] = $notification;
// Save the configured operator.
$operator = $notification->get('condition_operator') ?? 'or';
// Test each condition plugin and collect the result.
$results = [];
$summaries = [];
$collections = $notification->getPluginCollections();
/** @var \Drupal\data_stream_notification\Plugin\DataStream\NotificationCondition\NotificationConditionInterface $condition */
foreach ($collections['condition'] as $condition) {
// Set the event context values on the plugin.
$contexts = $condition->getContextDefinitions();
foreach ($event->context as $name => $value) {
if (array_key_exists($name, $contexts)) {
$condition->setContextValue($name, $value);
}
}
// Evaluate the condition.
$result = $condition->execute();
// Collect the summary of successful conditions.
if ($result) {
$summaries[] = $condition->summary();
}
// If success, and the 'or' operator, stop checking conditions.
if ($result && $operator === 'or') {
$conditions_met = TRUE;
break;
}
$results[] = $result;
}
// Check if the 'and' operator passes.
if ($operator === 'and') {
$conditions_met = array_product($results);
}
$state_key = $conditions_met ? 'activate_count' : 'deactivate_count';
$new_state = $notification->incrementState($state_key);
// Bail if the notification is not in an active state.
if (!$conditions_met || empty($new_state['active'])) {
return;
}
// Determine if the notification delivery needs to be executed.
// This is based on the notification's configured delivery interval.
$execute_delivery = FALSE;
$delivery_interval = $notification->get('delivery_interval');
$activate_count = $new_state['activate_count'];
// Always execute delivery when the notification first becomes active.
if ($activate_count === 1) {
$execute_delivery = TRUE;
}
// Use modulus arithmetic to determine if the delivery_interval applies.
elseif ($delivery_interval > 0 && ($activate_count - 1) % $delivery_interval === 0) {
$execute_delivery = TRUE;
}
// Bail if not executing delivery.
if (empty($execute_delivery)) {
return;
}
// Include the condition summaries.
$event->context['condition_summaries'] = $summaries;
// Else execute all configured delivery plugins.
/** @var \Drupal\data_stream_notification\Plugin\DataStream\NotificationDelivery\NotificationDeliveryInterface $delivery */
foreach ($collections['delivery'] as $delivery) {
// Set the event context values on the plugin.
$contexts = $delivery->getContextDefinitions();
foreach ($event->context as $name => $value) {
if (array_key_exists($name, $contexts)) {
$delivery->setContextValue($name, $value);
}
}
// Execute the delivery plugin.
$delivery->execute();
}
}
}
}
