-
-
Save msankhala/92ac183fc95d1bc8212ce4a5847c24a5 to your computer and use it in GitHub Desktop.
/web/modules/custom/axl_ks_topics/src/Plugin/EntityReferenceSelection/TopicsSelection.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Drupal\axl_ks_topics\Plugin\EntityReferenceSelection; | |
use Drupal\Component\Utility\Html; | |
use Drupal\Core\Database\Connection; | |
use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginBase; | |
use Drupal\Core\Entity\EntityTypeManagerInterface; | |
use Drupal\Core\Entity\Query\QueryInterface; | |
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; | |
use Symfony\Component\DependencyInjection\ContainerInterface; | |
/** | |
* Provides an entity reference selection for topics. | |
* | |
* @EntityReferenceSelection( | |
* id = "axl_ks_topics", | |
* label = @Translation("Unscheduled topics for an event"), | |
* entity_types = {"node"}, | |
* group = "axl_ks_topics", | |
* weight = 0 | |
* ) | |
*/ | |
class TopicsSelection extends SelectionPluginBase implements ContainerFactoryPluginInterface { | |
/** | |
* The entity type manager. | |
* | |
* @var \Drupal\Core\Entity\EntityTypeManagerInterface | |
*/ | |
protected $entityTypeManager; | |
/** | |
* Active database connection. | |
* | |
* @var \Drupal\Core\Database\Connection | |
*/ | |
protected $database; | |
/** | |
* Constructs a new selection object. | |
* | |
* @param array $configuration | |
* A configuration array containing information about the plugin instance. | |
* @param string $plugin_id | |
* The plugin_id for the plugin instance. | |
* @param mixed $plugin_definition | |
* The plugin implementation definition. | |
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager | |
* The entity manager service. | |
* @param \Drupal\Core\Database\Connection $database | |
* The database connection to be used. | |
*/ | |
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entityTypeManager, Connection $database) { | |
parent::__construct($configuration, $plugin_id, $plugin_definition); | |
$this->entityTypeManager = $entityTypeManager; | |
$this->database = $database; | |
} | |
/** | |
* {@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'), | |
$container->get('database') | |
); | |
} | |
/** | |
* Builds an EntityQuery to get referenceable topic entities. | |
* | |
* @param string|null $match | |
* Text to match the label against. | |
* @param string $match_operator | |
* The operation the matching should be done with. | |
* @param int $eventId | |
* The current enitity id. | |
* | |
* @return \Drupal\Core\Entity\Query\QueryInterface | |
* The query object that can query the given entity type. | |
*/ | |
protected function buildEntityQueryForTopics($match = NULL, $match_operator = 'CONTAINS', int $eventId = 0): QueryInterface { | |
$query = $this->entityTypeManager->getStorage('node')->getQuery(); | |
$query->condition('type', 'topic'); | |
$topics = $this->getReferenceableTopics($eventId); | |
if (!$topics) { | |
// If there are no topics, force the query to return an empty result. | |
$query->condition('nid', NULL, '='); | |
return $query; | |
} | |
$query->condition('nid', $topics, 'IN'); | |
if (isset($match)) { | |
$query->condition('title', $match, $match_operator); | |
} | |
// Add entity-access tag. | |
$query->addTag('node_access'); | |
// Add the Selection handler for system_query_entity_reference_alter(). | |
$query->addTag('entity_reference'); | |
$query->addMetaData('entity_reference_selection_handler', $this); | |
return $query; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) { | |
$query = $this->buildEntityQueryForTopics($match, $match_operator, $this->getParentEntityId()); | |
if ($limit > 0) { | |
$query->range(0, $limit); | |
} | |
$result = $query->execute(); | |
if (empty($result)) { | |
return []; | |
} | |
$options = []; | |
$entities = $this->entityTypeManager->getStorage('node')->loadMultiple($result); | |
$termStorage = $this->entityTypeManager->getStorage('taxonomy_term'); | |
$userStorage = $this->entityTypeManager->getStorage('user'); | |
foreach ($entities as $entity_id => $entity) { | |
$topic_type = $termStorage->load($entity->get('field_topic_type')->target_id); | |
$presenter = $userStorage->load($entity->get('field_topic_presenters')->target_id); | |
$duration = $entity->get('field_topic_duration')->value; | |
$options['topic'][$entity_id] = Html::escape(sprintf("%s - %s (%d mins, %s)", $entity->label(), $presenter->label(), $duration, $topic_type->label())); | |
} | |
return $options; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function countReferenceableEntities($match = NULL, $match_operator = 'CONTAINS') { | |
$query = $this->buildEntityQueryForTopics($match, $match_operator, $this->getParentEntityId()); | |
return $query | |
->count() | |
->execute(); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function validateReferenceableEntities(array $ids) { | |
$result = []; | |
if ($ids) { | |
$query = $this->buildEntityQueryForTopics(NULL, NULL, $this->getParentEntityId()); | |
$result = $query | |
->condition('nid', $ids, 'IN') | |
->execute(); | |
} | |
return $result; | |
} | |
/** | |
* Gets the list of topic referenceable entities. | |
* | |
* @param int $eventId | |
* The event ID for which topics are allowed to be referenced. | |
* | |
* @return mixed | |
* The query result. | |
*/ | |
protected function getReferenceableTopics(int $eventId) { | |
// @todo: Convert this to a dynamic query. | |
$eventTypeTid = $this->getEventTypeTermId(); | |
if ($eventTypeTid) { | |
$eventTypeSql = " AND topic_type.field_topic_type_target_id = '$eventTypeTid' "; | |
} | |
$sql = <<<SQL | |
SELECT topic.nid FROM {node_field_data} topic | |
LEFT JOIN {node__field_topic_type} topic_type ON topic_type.entity_id = topic.nid | |
LEFT JOIN {node__field_event_topics} event_topic ON event_topic.field_event_topics_target_id = topic.nid | |
WHERE topic.type = 'topic' | |
$eventTypeSql | |
AND (event_topic.field_event_topics_target_id IS NULL OR event_topic.entity_id = :event_id) | |
SQL; | |
$result = $this->database->query($sql, [':event_id' => $eventId]); | |
$nids = $result->fetchCol(); | |
return $nids; | |
} | |
/** | |
* Get the entity ID of the node with the ER plugin. | |
* | |
* @return int | |
* Entity ID of the parent or 0 if there is no stored entity yet. | |
*/ | |
protected function getParentEntityId(): int { | |
$config = $this->getConfiguration(); | |
/** @var \Drupal\Core\Entity\EntityInterface $entity */ | |
$entity = $config['entity']; | |
return $entity ? (int) $entity->id() : 0; | |
} | |
/** | |
* Get the term ID for the event type of the currently loaded event. | |
* | |
* @return int|null | |
* Event type term-id of the current entity. | |
*/ | |
protected function getEventTypeTermId(): ?int { | |
$config = $this->getConfiguration(); | |
/** @var \Drupal\Core\Entity\EntityInterface $entity */ | |
$entity = $config['entity']; | |
if (!$entity) { | |
return NULL; | |
} | |
$event_topic_type = $entity->get('field_event_topic_type')->getValue(); | |
return $event_topic_type[0]['target_id'] ?? NULL; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment