contacts_events-8.x-1.x-dev/modules/teams/src/TeamQueries.php
modules/teams/src/TeamQueries.php
<?php
namespace Drupal\contacts_events_teams;
use Drupal\contacts_events\Entity\Event;
use Drupal\contacts_events\Entity\TicketInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
/**
* Queries related to teams and applications.
*
* @package Drupal\contacts_events_teams
*/
class TeamQueries {
/**
* Entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* TeamQueries constructor.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* Entity type manager.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->entityTypeManager = $entity_type_manager;
}
/**
* Get the team counts for an event.
*
* @param \Drupal\contacts_events\Entity\Event $event
* The event.
*
* @return array
* Containing:
* - public: The number of public teams.
* - private: The number of private teams.
* - total: The total number of teams.
*/
public function getTeamCounts(Event $event) {
$team_storage = $this->entityTypeManager->getStorage('c_events_team');
$stats = [
'public' => 0,
'private' => 0,
'total' => 0,
];
// Query teams for the event, grouped by visibility.
$query = $team_storage->getAggregateQuery();
$query->aggregate('id', 'COUNT');
$query->groupBy('public');
$query->condition('event', $event->id());
foreach ($query->execute() as $row) {
$stats[$row['public'] ? 'public' : 'private'] = $row['id_count'];
$stats['total'] += $row['id_count'];
}
return $stats;
}
/**
* Gets overally team application statistics by sub-category.
*
* @param \Drupal\contacts_events\Entity\Event $event
* The event.
*
* @return array
* An array of counts of applications in each status, keyed by top level
* then 2nd level category. A team directly in a top level category will
* have the top level as the 2nd level category key.
*/
public function getTeamAppStatsBySubCategory(Event $event) {
$stats = [];
// Grouped by category.
$query = $this->entityTypeManager
->getStorage('c_events_team_app')
->getAggregateQuery();
$query->condition('event', $event->id());
$query->condition('state', 'archived', '!=');
$query->aggregate('id', 'COUNT');
$query->groupBy('team.entity.category');
$query->groupBy('state');
$categories = $this->entityTypeManager
->getStorage('taxonomy_term')
->loadTree('contacts_events_teams');
$parentage = [];
foreach ($categories as $category) {
if ($category->depth < 2) {
$parent = $category;
}
$parentage[$category->tid] = $parent->tid;
}
foreach ($query->execute() as $row) {
$tid = $parentage[$row['category']];
$stats[$tid][$row['state']] = ($stats[$tid][$row['state']] ?? 0) + $row['id_count'];
}
// Query tickets that don't have a team application yet to get not started
// counts.
$query = $this->entityTypeManager
->getStorage('contacts_ticket')
->getAggregateQuery();
// EntityQuery can't handle reverse entity references, so use a tag which
// will add it to the SQL directly.
// @see contacts_events_teams_query_contacts_events_teams_tickets_without_apps_alter
$query->addTag('contacts_events_teams_tickets_without_apps');
$query->condition('event', $event->id());
$query->condition('is_team_ticket', TRUE);
$query->condition('order_item.entity.state', 'team_app_in_progress');
$query->aggregate('id', 'COUNT');
$query->groupBy('team.entity.category');
foreach ($query->execute() as $row) {
$tid = $parentage[$row['category']];
$stats[$tid]['not_started'] = ($stats[$tid]['not_started'] ?? 0) + $row['id_count'];
}
return $stats;
}
/**
* Helper method that gets the team application for a ticket.
*
* @param \Drupal\contacts_events\Entity\TicketInterface $ticket
* The ticket.
*
* @return \Drupal\contacts_events_teams\Entity\TeamApplication|null
* The team application instance, or NULL if there isn't one.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function getTeamApplicationForTicket(TicketInterface $ticket) {
$storage = $this->entityTypeManager->getStorage('c_events_team_app');
$query = $storage->getQuery();
$query->accessCheck(TRUE);
$query->condition('ticket', $ticket->id());
$query->condition('state', ['archived', 'rejected_notified'], 'NOT IN');
$ids = $query->execute();
if (count($ids) > 1) {
throw new \Exception('Expected 1 team app per ticket - found ' . count($ids));
}
if (count($ids) === 0) {
return NULL;
}
return $storage->load(reset($ids));
}
}
