contacts_events-8.x-1.x-dev/src/Cron/BookingWindowCronBase.php
src/Cron/BookingWindowCronBase.php
<?php namespace Drupal\contacts_events\Cron; use Drupal\Component\Datetime\Time; use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\State\StateInterface; use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem; use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface; /** * A base class for performing actions based on booking window transistions. */ abstract class BookingWindowCronBase extends CronBase { /** * Event entity storage. * * @var \Drupal\Core\Entity\EntityStorageInterface */ protected $eventStorage; /** * The entity field manager. * * @var \Drupal\Core\Entity\EntityFieldManagerInterface */ protected $entityFieldManager; /** * An offset to apply when checking booking windows. * * A positive offset will mean the action is performed that interval before * the deadline change. * * @var \DateInterval|null */ protected $dateOffset; /** * Construct the booking window transition cron base class. * * @param \Drupal\Core\State\StateInterface $state * The state service. * @param \Drupal\Component\Datetime\Time $time * The time service. * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager * The entity field manager. * * @throws \Exception * Thrown if the STATE_LAST_RUN constant is not set. */ public function __construct(StateInterface $state, Time $time, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager) { parent::__construct($state, $time); $this->eventStorage = $entity_type_manager->getStorage('contacts_event'); $this->entityFieldManager = $entity_field_manager; } /** * {@inheritdoc} * * @todo Refactor this so multiple order item types get handle as one action. */ protected function doInvoke() { // Get the booking window fields and the order item types they affect. $window_fields = []; $field_map = $this->entityFieldManager->getFieldMapByFieldType('price_map'); if (isset($field_map['contacts_event'])) { foreach ($field_map['contacts_event'] as $field_name => $field_info) { foreach ($field_info['bundles'] as $bundle) { $definition = $this->entityFieldManager ->getFieldDefinitions('contacts_event', $bundle)[$field_name]; if ($window_field = $definition->getSetting('booking_window_field')) { $window_definition = $this->entityFieldManager ->getFieldDefinitions('contacts_event', $bundle)[$window_field]; $order_item_type = $definition->getSetting('order_item_type'); $window_fields[$window_field][$order_item_type] = $window_definition->getSetting('datetime_type'); } } } } // If we have no fields, there's nothing to do. if (empty($window_fields)) { return; } // Look for any events which have passed a booking window. $now = $this->getCurrentTime(); $last_run = $this->getLastRunTime(); // Apply an offset if there is one. if ($this->dateOffset) { $now->add($this->dateOffset); if ($last_run) { $last_run->add($this->dateOffset); } } foreach ($window_fields as $field_name => $order_item_types) { foreach ($order_item_types as $order_item_type => $date_type) { $query = $this->eventStorage->getQuery(); $query->accessCheck(FALSE); // Get the database date format. if ($date_type == DateTimeItem::DATETIME_TYPE_DATE) { $format = DateTimeItemInterface::DATE_STORAGE_FORMAT; } else { $format = DateTimeItemInterface::DATETIME_STORAGE_FORMAT; } // Put the two cut off checks in an OR condition group. $or = $query->orConditionGroup(); $query->condition($or); $cut_off_condition = $query->andConditionGroup(); $or->condition($cut_off_condition); $cut_off_confirmed_condition = $query->andConditionGroup(); $or->condition($cut_off_confirmed_condition); // Check the cut off is before now. $cut_off_condition->condition("{$field_name}.cut_off", $now->format($format), '<'); $cut_off_confirmed_condition->condition("{$field_name}.cut_off_confirmed", $now->format($format), '<'); // If we have a last run, only look more recent than that. if ($last_run) { $cut_off_condition->condition("{$field_name}.cut_off", $last_run->format($format), '>='); $cut_off_confirmed_condition->condition("{$field_name}.cut_off_confirmed", $last_run->format($format), '>='); } // Queue up any orders for recalculation. $event_ids = $query->execute(); if (!empty($event_ids)) { $this->runActionsForEvents($event_ids, [$order_item_type]); } } } } /** * Run the actions for given events/order item types. * * @param int[] $event_ids * An array of event IDs to perform an action for. * @param string[] $order_item_types * The order item types the action is relevant for. */ abstract protected function runActionsForEvents(array $event_ids, array $order_item_types): void; }