contacts_events-8.x-1.x-dev/src/Controller/TicketsController.php
src/Controller/TicketsController.php
<?php
namespace Drupal\contacts_events\Controller;
use Drupal\contacts_events\Entity\EventInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\Query\QueryAggregateInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides ticket summary report.
*/
class TicketsController extends ControllerBase {
/**
* The controller constructor.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, ModuleHandlerInterface $module_handler) {
$this->entityTypeManager = $entity_type_manager;
$this->moduleHandler = $module_handler;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity_type.manager'),
$container->get('module_handler')
);
}
/**
* Render the Event tickets report page.
*
* @param \Drupal\contacts_events\Entity\EventInterface $contacts_event
* The Event to link to Tickets reports for.
*
* @return array
* Renderable ticket summary data.
*/
public function summary(EventInterface $contacts_event) {
// Ensure caches are cleared appropriately.
$build['#cache']['tags'] = [
'commerce_order_list',
'commerce_order_item_list',
];
// Get a total ticket count.
$counts = $this->getTicketsByStatus($contacts_event) + [
'cancelled' => 0,
'pending' => 0,
'paid_in_full' => 0,
];
$build['total'] = [
'#type' => 'item',
'#title' => $this->t('Total confirmed tickets'),
'#number' => array_sum($counts) - $counts['pending'] - $counts['cancelled'],
'#description_display' => 'after',
];
$build['paid_in_full'] = [
'#type' => 'item',
'#title' => $this->t('Fully paid tickets'),
'#markup' => $this->formatPlural($counts['paid_in_full'],
'@number ticket',
'@number tickets',
['@number' => number_format($counts['paid_in_full'], 0)]),
];
$build['pending'] = [
'#type' => 'item',
'#title' => $this->t('Pending tickets'),
'#markup' => $this->formatPlural($counts['pending'],
'@number ticket',
'@number tickets',
['@number' => number_format($counts['pending'], 0)]),
];
$build['cancelled'] = [
'#type' => 'item',
'#title' => $this->t('Cancelled tickets'),
'#markup' => $this->formatPlural($counts['cancelled'],
'@number ticket',
'@number tickets',
['@number' => number_format($counts['cancelled'], 0)]),
];
// Allow other modules to make changes.
$this->moduleHandler->alter('contacts_events_ticket_summary', $build, $contacts_event);
// Build the total markup and description.
$build['total']['#markup'] = $this->formatPlural($build['total']['#number'],
'@number ticket',
'@number tickets',
['@number' => number_format($build['total']['#number'], 0)]);
if ($contacts_event->hasField('capacity') && !$contacts_event->get('capacity')->isEmpty()) {
$capacity = $contacts_event->get('capacity')->value;
$build['total']['#description'] = $this->formatPlural($capacity,
'@percentage% of @spaces space.',
'@percentage% of @spaces spaces.',
[
'@percentage' => floor($build['total']['#number'] / $capacity * 100),
'@spaces' => number_format($capacity, 0),
]);
}
return $build;
}
/**
* Get counts of tickets by status.
*
* @param \Drupal\contacts_events\Entity\EventInterface $event
* The event.
*
* @return array
* An array of ticket counts by status.
*/
protected function getTicketsByStatus(EventInterface $event): array {
// Build our query.
$entity_type_manager = $this->entityTypeManager;
$query = self::getBaseStatsQuery($event, $entity_type_manager);
$query->groupBy('state');
// Build our result array.
$statuses = [];
foreach ($query->execute() as $row) {
$statuses[$row['state_value']] = $row['order_item_id_count'];
}
return $statuses;
}
/**
* Get a base query for ticket statistics.
*
* @param \Drupal\contacts_events\Entity\EventInterface $event
* The event.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface|null $entity_type_manager
* Optionally inject the entity type manager.
*
* @return \Drupal\Core\Entity\Query\QueryAggregateInterface
* The query.
*/
public static function getBaseStatsQuery(EventInterface $event, EntityTypeManagerInterface $entity_type_manager = NULL): QueryAggregateInterface {
if (!$entity_type_manager) {
$entity_type_manager = \Drupal::entityTypeManager();
}
// An aggregate query getting counts of ticket order items for the event.
$query = $entity_type_manager
->getStorage('commerce_order_item')
->getAggregateQuery();
$query->accessCheck(FALSE);
$query->addTag('contacts_events_ticket_stats');
$query->condition('order_id.entity.type', 'contacts_booking');
$query->condition('order_id.entity.event', $event->id());
$query->condition('type', 'contacts_ticket');
$query->aggregate('order_item_id', 'COUNT');
return $query;
}
}
