contacts_events-8.x-1.x-dev/modules/teams/src/Plugin/views/filter/TeamFilter.php
modules/teams/src/Plugin/views/filter/TeamFilter.php
<?php
namespace Drupal\contacts_events_teams\Plugin\views\filter;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\Plugin\views\filter\InOperator;
use Drupal\views\ViewExecutable;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Filter handler for the team.
*
* Note that this does not work in the views_ui designer as the designer
* doesn't make the view contextual arguments available until too late.
*
* @ingroup views_filter_handlers
*
* @ViewsFilter("contacts_events_teams_team")
*/
class TeamFilter extends InOperator {
/**
* Entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->entityTypeManager = $entity_type_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration, $plugin_id, $plugin_definition,
$container->get('entity_type.manager')
);
}
/**
* {@inheritdoc}
*/
public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
parent::init($view, $display, $options);
// InOperator::init sets valueOptions to NULL.
// Make sure we always default it back to an empty array.
$this->valueOptions = [];
}
/**
* {@inheritdoc}
*/
public function getValueOptions() {
if (!empty($this->valueOptions)) {
return $this->valueOptions;
}
if (count($this->view->args)) {
// Assume event ID is always first contextual filter.
$event_id = $this->view->args[0];
$teams = $this->getTeams($event_id);
$categories = $this->getCategories($teams);
$options = $this->buildOptions($teams, $categories);
$this->valueOptions = $options;
}
return $this->valueOptions;
}
/**
* {@inheritdoc}
*/
protected function opSimple() {
if (empty($this->value)) {
return;
}
if (count($this->view->args)) {
$this->ensureMyTable();
$event_id = $this->view->args[0];
$values = [];
foreach ($this->value as $key => $value) {
if (strpos($value, 'cat_') === 0) {
$category_id = substr($value, 4);
// Category mapping. Find any teams in this category.
foreach ($this->getTeamsInCategory($event_id, $category_id) as $team_id) {
$values[] = $team_id;
}
}
else {
$values[] = $value;
}
}
// Need to convert any category values to their underlying teams.
$this->query->addWhere($this->options['group'], "$this->tableAlias.$this->realField", $values, $this->operator);
}
else {
parent::opSimple();
}
}
/**
* Gets teams for an event.
*
* @param int $event_id
* Event ID.
*
* @return \Drupal\contacts_events_teams\Entity\Team[]
* Array of teams.
*/
private function getTeams($event_id) {
/** @var \Drupal\contacts_events_teams\Entity\Team[] $teams */
$teams = $this->entityTypeManager->getStorage('c_events_team')
->loadByProperties(['event' => $event_id]);
return $teams;
}
/**
* Gets distinct categories from a list of teams.
*
* @param \Drupal\contacts_events_teams\Entity\Team[] $teams
* Array of teams.
*
* @return array
* Array of category names keyed by category ID.
*/
private function getCategories(array $teams) {
$categories = [];
/** @var \Drupal\contacts_events_teams\Entity\Team $team */
foreach ($teams as $team) {
$category_item = $team->get('category');
if (!$category_item->isEmpty() && !isset($categories[$category_item->target_id])) {
$category = $category_item->entity;
$categories[$category_item->target_id] = $category ? $category->label() : $category_item->target_id;
}
}
return $categories;
}
/**
* Builds the list options for the filter.
*
* @param \Drupal\contacts_events_teams\Entity\Team[] $teams
* Array of team entities.
* @param array $categories
* Array of category names keyed by category ID.
*
* @return array
* List options.
*/
private function buildOptions(array $teams, array $categories) {
$options = [];
foreach ($categories as $category_id => $category_name) {
$options["cat_$category_id"] = $category_name;
$num_teams = 0;
foreach ($teams as $team_id => $team) {
/** @var \Drupal\contacts_events_teams\Entity\Team $team */
if ($team->category->target_id == $category_id) {
/** @var \Drupal\contacts_events_teams\Entity\Team $team */
$options[$team_id] = '- ' . $team->label();
unset($teams[$team_id]);
$num_teams++;
}
}
if ($num_teams == 0) {
// No teams for this category, so don't bother showing the category.
unset($options["cat_$category_id"]);
}
}
return $options;
}
/**
* Gets teams in a category.
*
* @param int $event_id
* Event ID.
* @param int $category_id
* Event Category ID (taxonomy term).
*
* @return int[]
* Array of team IDs.
*/
private function getTeamsInCategory($event_id, $category_id) {
$query = $this->entityTypeManager->getStorage('c_events_team')->getQuery();
$query->accessCheck(TRUE);
$query->condition('event', $event_id);
$query->condition('category', $category_id);
return $query->execute();
}
}
