bee-8.x-1.1/src/EventSubscriber/OrderEventSubscriber.php
src/EventSubscriber/OrderEventSubscriber.php
<?php
namespace Drupal\bee\EventSubscriber;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\node\Entity\NodeType;
use Drupal\state_machine\Event\WorkflowTransitionEvent;
use RRule\RRule;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Interact with Orders.
*/
class OrderEventSubscriber implements EventSubscriberInterface {
use StringTranslationTrait;
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The config factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* The node type storage.
*
* @var Drupal\node\Entity\NodeType
*/
protected $nodetypeStorage;
/**
* Constructs a new OrderEventSubscriber object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_manager
* The entity manager.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory.
*/
public function __construct(EntityTypeManagerInterface $entity_manager, ConfigFactoryInterface $config_factory) {
$this->entityTypeManager = $entity_manager;
$this->configFactory = $config_factory;
$this->nodetypeStorage = $this->entityTypeManager->getStorage('node_type');
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array {
$events = ['commerce_order.place.pre_transition' => 'finalizeCart'];
return $events;
}
/**
* Finalizes the cart when the order is placed.
*
* @param \Drupal\state_machine\Event\WorkflowTransitionEvent $event
* The workflow transition event.
*/
public function finalizeCart(WorkflowTransitionEvent $event) {
$order = $event->getEntity();
foreach ($order->getItems() as $order_item) {
if ($order_item->bundle() == 'bee') {
if ($booking = $order_item->get('field_booking')->entity) {
$booking_event_reference = $booking->get("booking_event_reference")->target_id;
if (!isset($booking_event_reference)) {
$node = $order_item->get('field_node')->entity;
$start_date = new \DateTime($booking->get('booking_start_date')->value);
$end_date = new \DateTime($booking->get('booking_end_date')->value);
$node_type = $this->nodetypeStorage->load($node->bundle());
assert($node_type instanceof NodeType);
$bee_settings = $node_type->getThirdPartySetting('bee', 'bee');
if ($bee_settings['bookable_type'] == 'daily') {
$booked_state = bat_event_load_state_by_machine_name('bee_daily_booked');
$event_type = 'availability_daily';
}
else {
$booked_state = bat_event_load_state_by_machine_name('bee_hourly_booked');
$event_type = 'availability_hourly';
}
$events = [];
$repeat_frequency = $booking->get('booking_repeat_frequency')->value;
$repeat_until = $booking->get('booking_repeat_until')->value;
if ($repeat_frequency && $repeat_until) {
$repeat_until_object = new \DateTime($repeat_until);
$label = $this->getEventSeriesLabel($node, $bee_settings['bookable_type'], $start_date, $end_date, $repeat_frequency, $repeat_until_object);
$rrule = new RRule([
'FREQ' => strtoupper($repeat_frequency),
'UNTIL' => $repeat_until . 'T235959Z',
]);
$event_series = bat_event_series_create([
'type' => $event_type,
'label' => $label,
'rrule' => $rrule->rfcString(),
]);
$event_dates = [
'value' => $start_date->format('Y-m-d\TH:i:00'),
'end_value' => $end_date->format('Y-m-d\TH:i:00'),
];
$event_series->set('event_dates', $event_dates);
$event_series->set('event_state_reference', $booked_state->id());
$available_units = $this->getAvailableUnits($node, $start_date, $end_date);
$event_series->set('event_bat_unit_reference', reset($available_units));
$event_series->save();
$booking->set('booking_event_series_reference', $event_series->id());
$query = $this->entityTypeManager->getStorage('bat_event')->getQuery()
->condition('event_series.target_id', $event_series->id());
$events_created = $query->accessCheck(FALSE)->execute();
foreach ($events_created as $event_id) {
$event = bat_event_load($event_id);
$events[] = $event;
}
}
else {
$capacity = ($booking->get('booking_capacity')->value) ? ($booking->get('booking_capacity')->value) : 1;
for ($i = 0; $i < $capacity; $i++) {
$event = bat_event_create(['type' => $event_type]);
$event_dates = [
'value' => $start_date->format('Y-m-d\TH:i:00'),
'end_value' => $end_date->format('Y-m-d\TH:i:00'),
];
$event->set('event_dates', $event_dates);
$event->set('event_state_reference', $booked_state->id());
if ($event_series = $booking->get('booking_event_series_reference')->target_id) {
$event->set('event_series', $event_series);
}
$available_units = $this->getAvailableUnits($node, $start_date, $end_date);
$event->set('event_bat_unit_reference', reset($available_units));
$event->save();
$events[] = $event;
}
}
$booking->set('booking_event_reference', $events);
$booking->save();
}
}
}
}
}
/**
* Get available Units.
*
* @param object $node
* A Node object.
* @param object $start_date
* A DateTime object.
* @param object $end_date
* A DateTime object.
*
* @return array
* An array.
*/
protected function getAvailableUnits($node, $start_date, $end_date) {
$node_type = $this->nodetypeStorage->load($node->bundle());
$bee_settings = $node_type->getThirdPartySetting('bee', 'bee');
$units_ids = [];
foreach ($node->get('field_availability_' . $bee_settings['bookable_type']) as $unit) {
if ($unit->entity) {
$units_ids[] = $unit->entity->id();
}
}
$temp_end_date = clone($end_date);
$temp_end_date->sub(new \DateInterval('PT1M'));
if ($bee_settings['bookable_type'] == 'daily') {
$available_units_ids = bat_event_get_matching_units($start_date, $temp_end_date, ['bee_daily_available'], [$bee_settings['type_id']], 'availability_daily');
}
else {
$available_units_ids = bat_event_get_matching_units($start_date, $temp_end_date, ['bee_hourly_available'], [$bee_settings['type_id']], 'availability_hourly');
}
return array_intersect($units_ids, $available_units_ids);
}
/**
* Get label for a event Serie.
*
* @param object $node
* A BEE node.
* @param string $bookable_type
* A string.
* @param object $start_date
* A DateTime object.
* @param object $end_date
* A DateTime object.
* @param string $repeat_frequency
* A string.
* @param object $repeat_until
* A DateTime object.
*
* @return string
* A string.
*/
protected function getEventSeriesLabel($node, $bookable_type, $start_date, $end_date, $repeat_frequency, $repeat_until) {
$frequency = $this->t('Day');
if ($repeat_frequency == 'weekly') {
$frequency = $start_date->format('l');
}
elseif ($repeat_frequency == 'monthly') {
$frequency = $this->t('@day of Month', ['@day' => $start_date->format('jS')]);
}
if ($bookable_type == 'daily') {
$label = $this->t('Reservations for @node Every @frequency from @start_date -> @end_date', [
'@node' => $node->label(),
'@frequency' => $frequency,
'@start_date' => $start_date->format('M j Y'),
'@end_date' => $repeat_until->format('M j Y'),
]);
}
else {
$label = $this->t('Reservations for @node Every @frequency from @start_time-@end_time from @start_date -> @end_date', [
'@node' => $node->label(),
'@frequency' => $frequency,
'@start_time' => $start_date->format('gA'),
'@end_time' => $end_date->format('gA'),
'@start_date' => $start_date->format('M j Y'),
'@end_date' => $repeat_until->format('M j Y'),
]);
}
return $label;
}
}
