diff --git a/embargo.services.yml b/embargo.services.yml index fff9bb0..d5a6f3c 100644 --- a/embargo.services.yml +++ b/embargo.services.yml @@ -18,11 +18,12 @@ services: - '@entity_type.manager' - '@datetime.time' - '@date.formatter' + - '@event_dispatcher' embargo.route_subscriber: class: Drupal\embargo\Routing\EmbargoRouteSubscriber arguments: ['@entity_type.manager'] tags: - - { name: event_subscriber } + - { name: 'event_subscriber' } embargo.ip_range_redirect: class: '\Drupal\embargo\EventSubscriber\IpRangeRedirect' arguments: @@ -56,4 +57,9 @@ services: - '@request_stack' - '@entity_type.manager' tags: - - { name: cache.context } + - { name: 'cache.context' } + embargo.tagging_event_subscriber: + class: Drupal\embargo\EventSubscriber\TaggingEventSubscriber + tags: + - { name: 'event_subscriber' } + diff --git a/src/Access/QueryTagger.php b/src/Access/QueryTagger.php index 202c158..c5b0189 100644 --- a/src/Access/QueryTagger.php +++ b/src/Access/QueryTagger.php @@ -13,6 +13,7 @@ use Drupal\islandora_hierarchical_access\Access\QueryConjunctionTrait; use Drupal\islandora_hierarchical_access\TaggedTargetsTrait; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; /** * Handles tagging entity queries with access restrictions for embargoes. @@ -32,7 +33,8 @@ public function __construct( Connection $database, EntityTypeManagerInterface $entity_type_manager, TimeInterface $time, - DateFormatterInterface $date_formatter + DateFormatterInterface $date_formatter, + EventDispatcherInterface $event_dispatcher, ) { $this->user = $user; $this->currentIp = $request_stack->getCurrentRequest()->getClientIp(); @@ -40,6 +42,7 @@ public function __construct( $this->entityTypeManager = $entity_type_manager; $this->time = $time; $this->dateFormatter = $date_formatter; + $this->setEventDispatcher($event_dispatcher); } /** diff --git a/src/EmbargoExistenceQueryTrait.php b/src/EmbargoExistenceQueryTrait.php index cf7f84e..18db51b 100644 --- a/src/EmbargoExistenceQueryTrait.php +++ b/src/EmbargoExistenceQueryTrait.php @@ -10,6 +10,9 @@ use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Session\AccountProxyInterface; use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface; +use Drupal\embargo\Event\TagExclusionEvent; +use Drupal\embargo\Event\TagInclusionEvent; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; /** * Helper trait; facilitate filtering of embargoed entities. @@ -58,6 +61,13 @@ trait EmbargoExistenceQueryTrait { */ protected DateFormatterInterface $dateFormatter; + /** + * The event dispatcher service. + * + * @var \Symfony\Contracts\EventDispatcher\EventDispatcherInterface + */ + protected EventDispatcherInterface $eventDispatcher; + /** * Helper; apply existence checks to a node(-like) table. * @@ -80,6 +90,30 @@ protected function applyExistenceQuery( ); } + /** + * Set the event dispatcher service. + * + * @param \Symfony\Contracts\EventDispatcher\EventDispatcherInterface $event_dispatcher + * The event dispatcher service to set. + * + * @return \Drupal\embargo\EmbargoExistenceQueryTrait|\Drupal\embargo\Access\QueryTagger|\Drupal\embargo\EventSubscriber\IslandoraHierarchicalAccessEventSubscriber + * The current instance; fluent interface. + */ + protected function setEventDispatcher(EventDispatcherInterface $event_dispatcher) : self { + $this->eventDispatcher = $event_dispatcher; + return $this; + } + + /** + * Get the event dispatcher service. + * + * @return \Symfony\Contracts\EventDispatcher\EventDispatcherInterface + * The event dispatcher service. + */ + protected function getEventDispatch() : EventDispatcherInterface { + return $this->eventDispatcher ?? \Drupal::service('event_dispatcher'); + } + /** * Build out condition for matching embargo entities. * @@ -90,17 +124,9 @@ protected function applyExistenceQuery( * The condition to attach. */ protected function buildInclusionBaseCondition(SelectInterface $query) : ConditionInterface { - $condition = $query->orConditionGroup(); + $dispatched_event = $this->getEventDispatch()->dispatch(new TagInclusionEvent($query)); - $embargo_alias = $query->getMetaData('embargo_alias'); - $target_aliases = $query->getMetaData('embargo_target_aliases'); - - $condition->where(strtr('!field IN (!targets)', [ - '!field' => "{$embargo_alias}.embargoed_node", - '!targets' => implode(', ', $target_aliases), - ])); - - return $condition; + return $dispatched_event->getCondition(); } /** @@ -113,14 +139,9 @@ protected function buildInclusionBaseCondition(SelectInterface $query) : Conditi * The condition to attach. */ protected function buildExclusionBaseCondition(SelectInterface $query) : ConditionInterface { - $condition = $query->orConditionGroup(); - - $embargo_alias = $query->getMetaData('embargo_alias'); - $unexpired_alias = $query->getMetaData('embargo_unexpired_alias'); - - $condition->where("{$unexpired_alias}.embargoed_node = {$embargo_alias}.embargoed_node"); + $dispatched_event = $this->getEventDispatch()->dispatch(new TagExclusionEvent($query)); - return $condition; + return $dispatched_event->getCondition(); } /** diff --git a/src/Event/AbstractTagEvent.php b/src/Event/AbstractTagEvent.php new file mode 100644 index 0000000..220c62c --- /dev/null +++ b/src/Event/AbstractTagEvent.php @@ -0,0 +1,70 @@ +condition = $this->query->orConditionGroup(); + } + + /** + * Get the query upon which to act. + * + * @return \Drupal\Core\Database\Query\SelectInterface + * The query upon which we are to act. + */ + public function getQuery() : SelectInterface { + return $this->query; + } + + /** + * Get the current condition. + * + * @return \Drupal\Core\Database\Query\ConditionInterface + * The current condition. + */ + public function getCondition() : ConditionInterface { + return $this->condition; + } + + /** + * Get the base "embargo" table alias. + * + * @return string + * The base "embargo" alias, as used in the query. + */ + public function getEmbargoAlias() : string { + return $this->query->getMetaData('embargo_alias'); + } + + /** + * Get the base query columns representing node IDs to find embargoes. + * + * @return string[] + * The column aliases representing node IDs. + */ + public function getTargetAliases() : array { + return $this->query->getMetaData('embargo_target_aliases'); + } + +} diff --git a/src/Event/EmbargoEvents.php b/src/Event/EmbargoEvents.php new file mode 100644 index 0000000..effceb4 --- /dev/null +++ b/src/Event/EmbargoEvents.php @@ -0,0 +1,14 @@ +query->getMetaData('embargo_unexpired_alias'); + } + +} diff --git a/src/Event/TagInclusionEvent.php b/src/Event/TagInclusionEvent.php new file mode 100644 index 0000000..42937a7 --- /dev/null +++ b/src/Event/TagInclusionEvent.php @@ -0,0 +1,10 @@ +get('current_user'), $container->get('request_stack'), $container->get('database'), $container->get('entity_type.manager'), $container->get('datetime.time'), $container->get('date.formatter'), - ); + )) + ->setEventDispatcher($container->get('event_dispatcher')); } /** diff --git a/src/EventSubscriber/TaggingEventSubscriber.php b/src/EventSubscriber/TaggingEventSubscriber.php new file mode 100644 index 0000000..8d86a1e --- /dev/null +++ b/src/EventSubscriber/TaggingEventSubscriber.php @@ -0,0 +1,48 @@ + 'inclusion', + EmbargoEvents::TAG_EXCLUSION => 'exclusion', + ]; + } + + /** + * Event handler; tagging inclusion event. + * + * @param \Drupal\embargo\Event\TagInclusionEvent $event + * The event being handled. + */ + public function inclusion(TagInclusionEvent $event) : void { + $event->getCondition()->where(strtr('!field IN (!targets)', [ + '!field' => "{$event->getEmbargoAlias()}.embargoed_node", + '!targets' => implode(', ', $event->getTargetAliases()), + ])); + } + + /** + * Event handler; tagging exclusion event. + * + * @param \Drupal\embargo\Event\TagExclusionEvent $event + * The event being handled. + */ + public function exclusion(TagExclusionEvent $event) : void { + $event->getCondition()->where("{$event->getUnexpiredAlias()}.embargoed_node = {$event->getEmbargoAlias()}.embargoed_node"); + } + +}