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(); } }