contacts_events-8.x-1.x-dev/modules/villages/src/Controller/AllocatedVillageController.php
modules/villages/src/Controller/AllocatedVillageController.php
<?php
namespace Drupal\contacts_events_villages\Controller;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
use Drupal\user\UserInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Builds block showing allocated villages used on the user's dashboard.
*
* @see contacts_events_villages_contacts_user_dashboard_user_summary_blocks_alter
*/
class AllocatedVillageController implements ContainerInjectionInterface {
/**
* Entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
$self = new static();
$self->entityTypeManager = $container->get('entity_type.manager');
return $self;
}
/**
* Gets the IDs of open events where village allocation info is public.
*
* @return array
* Array of event ids.
*/
private function getOpenEventIds() {
$now = (new \DateTime())->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT);
$event_storage = $this->entityTypeManager->getStorage('contacts_event');
$query = $event_storage->getQuery();
$query->accessCheck(TRUE);
$query->condition('date.end_value', $now, '>');
$query->condition('make_village_allocation_public', TRUE);
$event_ids = $query->execute();
return $event_ids;
}
/**
* Gets tickets for the specified events for the user.
*
* Only includes confired/paid in full.
*
* @param array $event_ids
* Array of event ids.
* @param \Drupal\user\UserInterface $user
* The user.
*
* @return \Drupal\contacts_events\Entity\Ticket[]
* Array of ticket instances.
*/
private function getTickets(array $event_ids, UserInterface $user) {
// Check if the user is a ticket holder for any of these events.
$ticket_storage = $this->entityTypeManager->getStorage('contacts_ticket');
$query = $ticket_storage->getQuery();
$query->accessCheck(TRUE);
$query->condition('contact', $user->id());
$query->condition('event', $event_ids, 'IN');
$query->condition('order_item.entity.state', [
'confirmed',
'paid_in_full',
], 'IN');
$tickets = $ticket_storage->loadMultiple($query->execute());
return $tickets;
}
/**
* Builds info on allcoated villages to show on user dashboard.
*
* @param \Drupal\user\UserInterface $user
* Current user.
*
* @return array
* Render array.
*/
public function myAllocatedVillages(UserInterface $user) {
// Add a block to show the user's allocated village.
// Find all active events where village allocation info is public.
$allocated_events = [];
$event_ids = $this->getOpenEventIds();
if (!empty($event_ids)) {
$tickets = $this->getTickets($event_ids, $user);
$events_where_user_is_ticketholder = array_map(function ($ticket) {
return $ticket->getEvent();
}, $tickets);
$village_ids = $this->getVillagesWhereUserIsVillageHost($user, $events_where_user_is_ticketholder);
foreach ($tickets as $ticket) {
/** @var \Drupal\contacts_events\Entity\Ticket $ticket */
$order = $ticket->getOrderItem()->getOrder();
if ($village = $order->get('village')->entity) {
/** @var \Drupal\contacts_events_villages\Entity\Village $village*/
$allocated_events[$ticket->getEvent()->id()] = [
'event' => $ticket->getEvent(),
'village' => $village,
'is_village_host' => in_array($village->id(), $village_ids),
];
}
}
// Also check if the user is a booking manager for any bookings for these
// events where they might not be a ticketholder.
$orders = $this->getOrdersWhereUserIsBookingManager($user, $event_ids);
foreach ($orders as $order) {
/** @var \Drupal\commerce_order\Entity\Order $order */
/** @var \Drupal\contacts_events\Entity\Event $event */
$event = $order->get('event')->entity;
if ($order->get('village')->entity && !isset($allocated_events[$event->id()])) {
$allocated_events[$event->id()] = [
'event' => $event,
'village' => $order->get('village')->entity,
'is_village_host' => FALSE,
];
}
}
if (!empty($allocated_events)) {
$output = [
'#type' => 'table',
'#header' => [
new TranslatableMarkup('Event'),
new TranslatableMarkup('Camping Village'),
],
'#rows' => [],
];
foreach ($allocated_events as $allocated_event) {
/** @var \Drupal\contacts_events\Entity\Event $event */
/** @var \Drupal\contacts_events_villages\Entity\Village $village */
$event = $allocated_event['event'];
$village = $allocated_event['village'];
$row = [
'event' => $event->label(),
'village' => $village->label(),
];
if ($allocated_event['is_village_host']) {
$row['village'] = [
'data' => [
'#type' => 'link',
'#title' => $village->label(),
'#url' => Url::fromRoute('contacts_events_villages.host_info', [
'contacts_event' => $event->id(),
'village' => $village->id(),
]),
],
];
}
$output['#rows'][] = $row;
}
return $output;
}
}
return NULL;
}
/**
* Gets the villages that user is a Village Host for.
*
* @param \Drupal\user\UserInterface $user
* User.
* @param \Drupal\contacts_events\Entity\Event[] $events
* Events.
*
* @return int[]
* IDs of villages where the user is the village host.
*/
private function getVillagesWhereUserIsVillageHost(UserInterface $user, array $events) {
// Check if the user has been accepted onto the Village Host Team
// for any of the specified events.
$team_ids = [];
foreach ($events as $event) {
foreach ($event->get('village_host_teams') as $item) {
$team_ids[] = $item->target_id;
}
}
if (empty($team_ids)) {
return [];
}
$storage = $this->entityTypeManager->getStorage('c_events_team_app');
$query = $storage->getQuery();
$query->accessCheck(TRUE);
$query->condition('team', $team_ids, 'IN');
$query->condition('ticket.entity.contact', $user->id());
$query->condition('state', 'approved');
$team_apps = $storage->loadMultiple($query->execute());
$village_ids = [];
foreach ($team_apps as $team_app) {
/** @var \Drupal\contacts_events_teams\Entity\TeamApplication $team_app */
/** @var \Drupal\contacts_events_villages\Entity\Village $village */
$village = $team_app->getTicket()->getOrderItem()->getOrder()->get('village')->entity;
if ($village) {
$village_ids[] = $village->id();
}
}
return $village_ids;
}
/**
* Gets orders for the specified events where the user is the booking manager.
*
* Only Confirmed/paid in full/modified orders are inclded.
*
* @param \Drupal\user\UserInterface $user
* User.
* @param array $event_ids
* Array of event ids.
*
* @return \Drupal\commerce_order\Entity\Order[]
* Orders where user is booking manager.
*/
public function getOrdersWhereUserIsBookingManager(UserInterface $user, array $event_ids): array {
$order_storage = $this->entityTypeManager->getStorage('commerce_order');
$query = $order_storage->getQuery();
$query->accessCheck(TRUE);
$query->condition('event', $event_ids, 'IN');
$query->condition('uid', $user->id());
$query->condition('state', ['confirmed', 'paid_in_full', 'modified'], 'IN');
$orders = $order_storage->loadMultiple($query->execute());
return $orders;
}
}
