Skip to content

Commit

Permalink
Replace node grants for 'group' visibility
Browse files Browse the repository at this point in the history
  • Loading branch information
nechai committed Oct 15, 2024
1 parent 3b2a0de commit 40e3178
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,10 @@ services:
arguments: []
tags:
- { name: cache.context }

Drupal\social_group\EventSubscriber\NodeQueryAccessAlterSubscriber:
arguments:
- '@entity_type.manager'
- '@group_relation_type.manager'
tags:
- { name: event_subscriber }
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
<?php

declare(strict_types=1);

namespace Drupal\social_group\EventSubscriber;

use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Session\AccountInterface;
use Drupal\group\Plugin\Group\Relation\GroupRelationTypeManagerInterface;
use Drupal\social_node\Event\NodeQueryAccessEvent;
use Drupal\social_node\Event\SocialNodeEvents;
use Drupal\social_node\SocialNodeQueryAccessAlterInterface;

/**
* Alter query access for nodes with "group" visibility.
*/
class NodeQueryAccessAlterSubscriber implements SocialNodeQueryAccessAlterInterface {

/**
* Constructs QueryAccessSubscriber.
*
* @param \Drupal\Core\Entity\EntityTypeManager $entityTypeManager
* The entity type definition.
* @param \Drupal\group\Plugin\Group\Relation\GroupRelationTypeManagerInterface $pluginManager
* The group relationship manager.
*/
public function __construct(
protected EntityTypeManager $entityTypeManager,
protected GroupRelationTypeManagerInterface $pluginManager,
) {}

/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array {
$events[SocialNodeEvents::NODE_QUERY_ACCESS_ALTER][] = ['alterQueryAccess'];
return $events;
}

/**
* {@inheritdoc}
*/
public function alterQueryAccess(NodeQueryAccessEvent $event): void {
$plugin_ids = $this->pluginManager->getPluginIdsByEntityTypeAccess('node');
if (empty($plugin_ids)) {
// If no group relationship plugins for "node" entity type is enabled.
return;
}

$account = $event->account();
$or = $event->getConditions();

// Make sure we have joined a group membership table.
$membership_table = $this->ensureMembershipJoin($account, $event);
$visibility_table = $event->ensureNodeFieldTableJoin('field_content_visibility');

$or->condition(
$event->query()->andConditionGroup()
->condition("$visibility_table.field_content_visibility_value", 'group')
->isNotNull("$membership_table.entity_id")
);
}

/**
* Ensures the query is joined with the memberships.
*
* @param \Drupal\Core\Session\AccountInterface $account
* The user account.
* @param \Drupal\social_node\Event\NodeQueryAccessEvent $event
* The event object.
*
* @return string
* The membership join alias.
*
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
protected function ensureMembershipJoin(AccountInterface $account, NodeQueryAccessEvent $event): string {
$query = $event->query();

// Join the memberships of the current user.
$group_relationship_data_table = $this->entityTypeManager
->getDefinition('group_content')
->getDataTable();

foreach ($query->getTables() as $join_info) {
if (
$join_info['table'] === $group_relationship_data_table &&
str_contains((string) $join_info['condition'], 'group_membership')
) {
return $join_info['alias'];
}
}

$group_relationship_table = $this->ensureGroupRelationshipJoin($event);

return $query->leftJoin(
$group_relationship_data_table,
'group_membership',
"$group_relationship_table.gid=%alias.gid AND %alias.plugin_id='group_membership' AND %alias.entity_id=:account_id",
[':account_id' => $account->id()]
);
}

/**
* Ensures the query is joined with the "group_relationship" table.
*
* @param \Drupal\social_node\Event\NodeQueryAccessEvent $event
* The event object.
*
* @return string
* The group relationship join alias.
*
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
* @throws \Exception
*/
private function ensureGroupRelationshipJoin(NodeQueryAccessEvent $event): string {
$query = $event->query();

$group_relationship_data_table = $this->entityTypeManager
->getDefinition('group_content')
->getDataTable();

foreach ($query->getTables() as $join_info) {
if (
$join_info['table'] === $group_relationship_data_table &&
str_contains((string) $join_info['condition'], 'plugin_ids_in_use')
) {
return $join_info['alias'];
}
}

// If the table wasn't joined in any of the previous query builder,
// we join it here.
// Join table with group relationship with nodes.
$node_base_table = $event->ensureNodeDataTable();
$plugin_ids = $this->pluginManager->getPluginIdsByEntityTypeAccess('node');

return $query->leftJoin(
$group_relationship_data_table,
'group_relationship',
"$node_base_table.nid=group_relationship.entity_id AND group_relationship.plugin_id IN (:plugin_ids_in_use[])",
[':plugin_ids_in_use[]' => $plugin_ids]
);
}

}

0 comments on commit 40e3178

Please sign in to comment.