Skip to content
Snippets Groups Projects
Commit e58eb389 authored by Kristiaan Van den Eynde's avatar Kristiaan Van den Eynde
Browse files

Issue #3132084 by kristiaanvandeneynde, LOBsTerr, Aporie, Spokje, JordiK:...

Issue #3132084 by kristiaanvandeneynde, LOBsTerr, Aporie, Spokje, JordiK: Add/Remove group role for a user programmatically
parent 4137a898
No related branches found
No related tags found
3 merge requests!193Issue #3304728 by kristiaanvandeneynde: Add member page missing due to...,!142Issue #3304728 by kristiaanvandeneynde: Add member page missing due to...,!111Issue #3397021 by adamfranco: Add entity_mappings for phpstan-drupal
Pipeline #111927 passed with warnings
......@@ -23,6 +23,22 @@ interface GroupMembershipInterface extends GroupRelationshipInterface {
*/
public function getRoles($include_synchronized = TRUE);
/**
* Adds a group role to the membership.
*
* @param string $role_id
* The ID of the group role to add.
*/
public function addRole(string $role_id): void;
/**
* Removes a group role from the membership.
*
* @param string $role_id
* The ID of the group role to remove.
*/
public function removeRole(string $role_id): void;
/**
* Checks whether the member has a permission.
*
......
......@@ -19,6 +19,43 @@ trait GroupMembershipTrait {
return $group_role_storage->loadByUserAndGroup($this->getEntity(), $this->getGroup(), $include_synchronized);
}
/**
* {@inheritdoc}
*/
public function addRole(string $role_id): void {
// Do nothing if the role is already present.
foreach ($this->group_roles as $group_role_ref) {
if ($group_role_ref->target_id === $role_id) {
return;
}
}
// @todo Add the below two checks to a preSave() hook.
$storage = \Drupal::entityTypeManager()->getStorage('group_role');
if (!$group_role = $storage->load($role_id)) {
throw new \InvalidArgumentException(sprintf('Could not add role with ID %s, role does not exist.', $role_id));
}
assert($group_role instanceof GroupRoleInterface);
if ($group_role->getGroupTypeId() !== $this->getGroupTypeId()) {
throw new \InvalidArgumentException(sprintf('Could not add role with ID %s, role belongs to a different group type.', $role_id));
}
$this->group_roles[] = $role_id;
$this->save();
}
/**
* {@inheritdoc}
*/
public function removeRole(string $role_id): void {
foreach ($this->group_roles as $key => $group_role_ref) {
if ($group_role_ref->target_id === $role_id) {
$this->group_roles->removeItem($key);
}
}
$this->save();
}
/**
* {@inheritdoc}
*/
......
......@@ -95,6 +95,30 @@ class GroupMembership implements CacheableDependencyInterface {
return $group_role_storage->loadByUserAndGroup($this->getUser(), $this->getGroup(), $include_synchronized);
}
/**
* Adds a group role to the membership.
*
* @param string $role_id
* The ID of the group role to add.
*/
public function addRole(string $role_id): void {
if ($this->groupRelationship instanceof GroupMembershipInterface) {
$this->groupRelationship->addRole($role_id);
}
}
/**
* Removes a group role from the membership.
*
* @param string $role_id
* The ID of the group role to remove.
*/
public function removeRole(string $role_id): void {
if ($this->groupRelationship instanceof GroupMembershipInterface) {
$this->groupRelationship->removeRole($role_id);
}
}
/**
* Checks whether the member has a permission.
*
......
<?php
namespace Drupal\Tests\group\Kernel;
use Drupal\Core\Session\AccountInterface;
use Drupal\group\Access\GroupPermissionCheckerInterface;
use Drupal\group\Entity\GroupInterface;
use Drupal\group\Entity\GroupMembershipInterface;
use Drupal\group\Entity\GroupRoleInterface;
use Drupal\group\Entity\GroupTypeInterface;
use Drupal\group\PermissionScopeInterface;
use Drupal\user\RoleInterface;
/**
* Tests the behavior of the GroupMembership shared bundle class.
*
* @coversDefaultClass \Drupal\group\Entity\GroupMembership
* @group group
*/
class GroupMembershipTest extends GroupKernelTestBase {
/**
* The account to use in testing.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected AccountInterface $account;
/**
* The group type to use in testing.
*
* @var \Drupal\group\Entity\GroupTypeInterface
*/
protected GroupTypeInterface $groupType;
/**
* The insider group role to use in testing.
*
* @var \Drupal\group\Entity\GroupRoleInterface
*/
protected GroupRoleInterface $groupRoleInsider;
/**
* The individual group role to use in testing.
*
* @var \Drupal\group\Entity\GroupRoleInterface
*/
protected GroupRoleInterface $groupRoleIndividual;
/**
* The group to use in testing.
*
* @var \Drupal\group\Entity\GroupInterface
*/
protected GroupInterface $group;
/**
* The group membership to run tests on.
*
* @var \Drupal\group\Entity\GroupMembershipInterface
*/
protected GroupMembershipInterface $groupMembership;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->account = $this->createUser();
$this->groupType = $this->createGroupType();
$this->groupRoleInsider = $this->createGroupRole([
'group_type' => $this->groupType->id(),
'scope' => PermissionScopeInterface::INSIDER_ID,
'global_role' => RoleInterface::AUTHENTICATED_ID,
]);
$this->groupRoleIndividual = $this->createGroupRole([
'group_type' => $this->groupType->id(),
'scope' => PermissionScopeInterface::INDIVIDUAL_ID,
'permissions' => ['view group'],
]);
// Reload the roles so that we can do proper comparison of loaded roles.
$storage = $this->entityTypeManager->getStorage('group_role');
$this->groupRoleInsider = $storage->load($this->groupRoleInsider->id());
$this->groupRoleIndividual = $storage->load($this->groupRoleIndividual->id());
$this->group = $this->createGroup(['type' => $this->groupType->id()]);
$this->group->addMember($this->account, ['group_roles' => [$this->groupRoleIndividual->id()]]);
// Manually load the membership here using the storage so that we don't
// end up testing ::loadSingle() via a detour.
$memberships = $this->entityTypeManager
->getStorage('group_content')
->loadByProperties([
'gid' => $this->group->id(),
'entity_id' => $this->account->id(),
'plugin_id' => 'group_membership',
]);
$this->groupMembership = reset($memberships);
}
/**
* Tests the retrieval of a membership's group roles.
*
* @covers ::getRoles
*/
public function testGetRoles() {
$expected[$this->groupRoleIndividual->id()] = $this->groupRoleIndividual;
$this->assertEquals($expected, $this->groupMembership->getRoles(FALSE));
$expected[$this->groupRoleInsider->id()] = $this->groupRoleInsider;
$this->assertEquals($expected, $this->groupMembership->getRoles());
}
/**
* Tests the addition of a group role to a membership.
*
* @covers ::addRole
* @depends testGetRoles
*/
public function testAddRole() {
$group_role = $this->createGroupRole([
'group_type' => $this->groupType->id(),
'scope' => PermissionScopeInterface::INDIVIDUAL_ID,
]);
$expected = [
$this->groupRoleIndividual->id(),
$this->groupRoleInsider->id(),
$group_role->id(),
];
$this->groupMembership->addRole($group_role->id());
$this->assertEqualsCanonicalizing($expected, array_keys($this->groupMembership->getRoles()));
}
/**
* Tests the removal of a group role from a membership.
*
* @covers ::removeRole
* @depends testGetRoles
*/
public function testRemoveRole() {
$this->groupMembership->removeRole($this->groupRoleIndividual->id());
$this->assertEquals([$this->groupRoleInsider->id()], array_keys($this->groupMembership->getRoles()));
}
/**
* Tests the permission check on a membership.
*
* @covers ::hasPermission
*/
public function testHasPermission() {
// This should always be a wrapper around the permission checker, so check.
$permission_checker = \Drupal::service('group_permission.checker');
assert($permission_checker instanceof GroupPermissionCheckerInterface);
$expected = $permission_checker->hasPermissionInGroup('view group', $this->account, $this->group);
$this->assertSame($expected, $this->groupMembership->hasPermission('view group'));
$expected = $permission_checker->hasPermissionInGroup('edit group', $this->account, $this->group);
$this->assertSame($expected, $this->groupMembership->hasPermission('edit group'));
}
}
......@@ -91,10 +91,9 @@ class GroupRoleStorageTest extends GroupKernelTestBase {
'group_type' => $this->group->bundle(),
'scope' => PermissionScopeInterface::INDIVIDUAL_ID,
]);
// @todo This displays a desperate need for addRole() and removeRole().
$membership = $this->group->getMember($this->account)->getGroupRelationship();
$membership->group_roles[] = $individual_role->id();
$membership->save();
$membership = $this->group->getMember($this->account);
$membership->addRole($individual_role->id());
$this->compareMemberRoles([$individual_role->id()], FALSE, 'User has the individual group role.');
$this->compareMemberRoles([$individual_role->id(), $insider_role->id()], TRUE, 'User also has synchronized insider role.');
}
......
......@@ -71,12 +71,8 @@ class IndividualGroupPermissionCalculatorTest extends GroupKernelTestBase {
$this->assertSame(-1, $calculated_permissions->getCacheMaxAge(), 'Permissions have the right max cache age.');
$this->assertEqualsCanonicalizing($cache_tags, $calculated_permissions->getCacheTags(), 'Permissions have the right cache tags.');
// @todo This displays a desperate need for addRole() and removeRole().
$group->addMember($account);
$group->addMember($account, ['group_roles' => [$group_role->id()]]);
$member = $group->getMember($account);
$group_relationship = $member->getGroupRelationship();
$group_relationship->group_roles[] = $group_role->id();
$group_relationship->save();
$permissions[$scope][$group->id()][] = 'view group';
$permissions[$scope][$group->id()][] = 'leave group';
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment