diff --git a/src/GroupMembership.php b/src/GroupMembership.php index cbb6493..de560ba 100644 --- a/src/GroupMembership.php +++ b/src/GroupMembership.php @@ -78,6 +78,23 @@ class GroupMembership implements CacheableDependencyInterface { return $group_role_storage->loadByUserAndGroup($this->getUser(), $this->getGroup()); } + /** + * Gets the group type roles.. + * + * @return \Drupal\group\Entity\GroupRoleInterface[] + * An array of group role objects. + */ + protected function getGroupTypeRoles() { + $properties = [ + 'group_type' => $this->groupContent->getGroup()->bundle(), + 'internal' => FALSE, + ]; + + return \Drupal::entityTypeManager() + ->getStorage('group_role') + ->loadByProperties($properties); + } + /** * Checks whether the member has a permission. * @@ -121,4 +138,69 @@ class GroupMembership implements CacheableDependencyInterface { return \Drupal::service('group_permission.checker'); } + /** + * Add a role to a member. + * + * @param string $role + * The role id for the role to add. + */ + public function addRole($role) { + // Check that the role exists for a given group type. + $group_type_roles = $this->getGroupTypeRoles(); + $role_exists = FALSE; + + foreach (array_keys($group_type_roles) as $group_type_role) { + if ($group_type_role === $role) { + $role_exists = TRUE; + break; + } + } + + if ($role_exists) { + // Check if a member already has the role. + foreach ($this->groupContent->group_roles as $key => $role_item) { + if ($role_item->target_id === $role) { + return; + } + } + + $this->groupContent->group_roles[] = $role; + $this->groupContent->save(); + } + } + + /** + * Remove a role from a member. + * + * @param string $role + * The role id for the role to remove. + */ + public function removeRole($role) { + $roles = $this->groupContent->group_roles; + foreach ($roles as $key => $role_item) { + if ($role_item->target_id == $role) { + $roles->removeItem($key); + } + } + + $this->groupContent->group_roles = $roles; + $this->groupContent->save(); + } + + /** + * Check if a member has a role. + * + * @param string $role + * The role id to be checked. + * + * @return bool + * True if the member has role. + */ + public function hasRole($role) { + $roles_values = $this->groupContent->group_roles->getValue(); + $roles = array_column($roles_values, 'target_id'); + + return in_array($role, $roles); + } + } diff --git a/tests/src/Kernel/ChainGroupPermissionCalculatorTest.php b/tests/src/Kernel/ChainGroupPermissionCalculatorTest.php index 87fd2aa..ee66b15 100644 --- a/tests/src/Kernel/ChainGroupPermissionCalculatorTest.php +++ b/tests/src/Kernel/ChainGroupPermissionCalculatorTest.php @@ -192,10 +192,7 @@ class ChainGroupPermissionCalculatorTest extends GroupKernelTestBase { $this->assertSame(-1, $calculated_permissions->getCacheMaxAge(), 'Member permissions have the right max cache age after joining a group.'); $this->assertSame($cache_tags, $calculated_permissions->getCacheTags(), 'Member permissions have the right cache tags after joining a group.'); - // @todo This displays a desperate need for addRole() and removeRole(). - $membership = $member->getGroupContent(); - $membership->group_roles[] = 'default-custom'; - $membership->save(); + $member->addRole('default-custom'); $permissions[$group->id()][] = 'join group'; $cache_tags[] = 'config:group.role.default-custom'; sort($cache_tags); diff --git a/tests/src/Kernel/GroupMembershipTest.php b/tests/src/Kernel/GroupMembershipTest.php new file mode 100644 index 0000000..78c42c6 --- /dev/null +++ b/tests/src/Kernel/GroupMembershipTest.php @@ -0,0 +1,94 @@ +group = $this->createGroup(); + } + + /** + * Tests the addition of a role to a member of a group. + * + * @covers ::addRole + */ + public function testAddRole() { + $account = $this->createUser(); + $this->group->addMember($account); + $member = $this->group->getMember($account); + $this->assertArrayNotHasKey('default-custom', $member->getRoles()); + + // Verify adding a non-existing role on a member that didn't have that role + // previously, doesn't add the role. + $user_role = 'default-non-existing-role'; + $member->addRole($user_role); + $this->assertArrayNotHasKey($user_role, $member->getRoles()); + + // Verify adding an existing role on a member that has that role already, + // doesn't set the role twice. + $user_role = 'default-member'; + $member->addRole($user_role); + $this->assertArrayHasKey($user_role, $member->getRoles()); + + // Verify adding an existing role on a member that didn't have that role + // previously, adds the role. + $user_role = 'default-custom'; + $member->addRole($user_role); + $this->assertArrayHasKey($user_role, $member->getRoles()); + } + + /** + * Tests the removing of a role on a member of a group. + * + * @covers ::removeRole + */ + public function testRemoveRole() { + $account = $this->createUser(); + $this->group->addMember($account); + $member = $this->group->getMember($account); + $role_name = 'default-custom'; + $this->assertArrayNotHasKey($role_name, $member->getRoles()); + + // First add a role we can remove afterwards. + $member->addRole($role_name); + $this->assertArrayHasKey($role_name, $member->getRoles()); + + // Now remove that role again. + $member->removeRole($role_name); + $this->assertArrayNotHasKey($role_name, $member->getRoles()); + } + + /** + * Tests a user has a role. + * + * @covers ::hasRole + */ + public function testHasRole() { + $account = $this->createUser(); + $role_name = 'default-custom'; + $this->group->addMember($account, ['group_roles' => $role_name]); + $member = $this->group->getMember($account); + + // Validate the user has role. + $this->assertTrue($member->hasRole($role_name)); + } + +} diff --git a/tests/src/Kernel/GroupRoleStorageTest.php b/tests/src/Kernel/GroupRoleStorageTest.php index 786c921..5cd5957 100644 --- a/tests/src/Kernel/GroupRoleStorageTest.php +++ b/tests/src/Kernel/GroupRoleStorageTest.php @@ -82,10 +82,9 @@ class GroupRoleStorageTest extends GroupKernelTestBase { 'weight' => 0, 'group_type' => 'default', ])->save(); - // @todo This displays a desperate need for addRole() and removeRole(). - $membership = $this->group->getMember($this->account)->getGroupContent(); - $membership->group_roles[] = 'default-editor'; - $membership->save(); + + $membership = $this->group->getMember($this->account); + $membership->addRole('default-editor'); $this->compareMemberRoles(['default-editor'], FALSE, 'User has the editor group role.'); $this->compareMemberRoles(['default-editor', 'default-member'], TRUE, 'User also has implicit member role.'); }