diff --git a/config/schema/ginvite.schema.yml b/config/schema/ginvite.schema.yml index 4af87568a4552ac9f4b58146b122cfbdcaac0604..b691b93a112d423c7110cc38f5cce78bc6ab6127 100644 --- a/config/schema/ginvite.schema.yml +++ b/config/schema/ginvite.schema.yml @@ -46,6 +46,10 @@ group_relation.config.send_email_existing_users: type: 'boolean' label: 'Send invitation e-mail to already registered users' +group_relation.config.remove_invitation: + type: 'integer' + label: 'Remove an invitation, when user join the group.' + group_relation.config.autoaccept_invitees: type: 'boolean' label: 'Automatically accept invitation' diff --git a/ginvite.module b/ginvite.module index 5f819b497741a3f610acb2eb68c53d97776287bb..bd1ffce14cd0a415c37e4a6332f61c50c43c8b5d 100644 --- a/ginvite.module +++ b/ginvite.module @@ -120,9 +120,7 @@ function ginvite_group_relationship_insert(GroupRelationshipInterface $group_rel $langcode = $from->getPreferredLangcode(); // Load plugin configuration. - $group_plugin_collection = \Drupal::service('group_relation_type.manager') - ->getInstalled($group->getGroupType()); - $group_invite_config = $group_plugin_collection->getConfiguration()['group_invitation']; + $group_invite_config = $group_relationship->getPlugin()->getConfiguration(); if ($invitee = user_load_by_mail($mail)) { $group_relationship->set('entity_id', $invitee); @@ -154,8 +152,14 @@ function ginvite_group_relationship_insert(GroupRelationshipInterface $group_rel $invitations = \Drupal::service('ginvite.invitation_loader')->loadByProperties($properties); if (!empty($invitations)) { foreach ($invitations as $invitation) { - // Mark invitation as accepted. - $invitation->getGroupRelationship()->set('invitation_status', GroupInvitation::INVITATION_ACCEPTED)->save(); + // Remove group content if setting is enabled. + if ($invitation->getGroupRelationship()->getPlugin()->getConfiguration()['remove_invitation'] == 1) { + $invitation->getGroupRelationship()->delete(); + } + else { + // Mark invitation as accepted. + $invitation->getGroupRelationship()->set('invitation_status', GroupInvitation::INVITATION_ACCEPTED)->save(); + } } $messenger->addMessage(t('You have accepted the invitation.')); @@ -169,11 +173,11 @@ function ginvite_group_relationship_insert(GroupRelationshipInterface $group_rel * Implements hook_ENTITY_TYPE_delete(). */ function ginvite_group_relationship_delete(GroupRelationshipInterface $group_relationship) { - if ($group_relationship->getPluginId() == 'group_invitation') { + $plugin_id = $group_relationship->getPluginId(); + if ($plugin_id == 'group_invitation') { $group = $group_relationship->getGroup(); // Load plugin configuration. - $group_plugin_collection = \Drupal::service('group_relation_type.manager')->getInstalled($group->getGroupType()); - $group_invite_config = $group_plugin_collection->getConfiguration()['group_invitation']; + $group_invite_config = $group_relationship->getPlugin()->getConfiguration(); if ($group_invite_config['send_cancel_email'] && $group_relationship->get('invitation_status')->value == GroupInvitation::INVITATION_PENDING) { $from = $group_relationship->getEntity(); @@ -190,6 +194,21 @@ function ginvite_group_relationship_delete(GroupRelationshipInterface $group_rel } } } + + // Remove invitation when member is removed. + if ($plugin_id == 'group_membership') { + $properties = [ + 'entity_id' => $group_relationship->getEntity()->id(), + 'gid' => $group_relationship->getGroup()->id(), + ]; + + // Remove invitations, when we remove the user. + $invitations = \Drupal::service('ginvite.invitation_loader')->loadByProperties($properties); + foreach ($invitations as $invitation) { + $invitation->getGroupRelationship()->delete(); + } + } + } /** diff --git a/src/Plugin/Group/Relation/GroupInvitation.php b/src/Plugin/Group/Relation/GroupInvitation.php index 059b70d031421fa809067bde8fe1b3a2b8db80f7..0792862205e912a20791eb4caab152094258376c 100644 --- a/src/Plugin/Group/Relation/GroupInvitation.php +++ b/src/Plugin/Group/Relation/GroupInvitation.php @@ -98,6 +98,7 @@ class GroupInvitation extends GroupRelationBase implements ContainerFactoryPlugi 'cancel_user_invitation_body' => $body_message_cancel, 'send_cancel_email' => FALSE, 'invitation_bypass_form' => FALSE, + 'remove_invitation' => FALSE, ]; } @@ -141,6 +142,13 @@ class GroupInvitation extends GroupRelationBase implements ContainerFactoryPlugi '#default_value' => $configuration['invitation_bypass_form'], ]; + $form['remove_invitation'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Remove invitation'), + '#description' => $this->t('Remove an invitation when a user join a group.'), + '#default_value' => $configuration['remove_invitation'], + ]; + $form['invitation_expire'] = [ '#type' => 'number', '#title' => $this->t('Expire invites'), diff --git a/tests/src/Kernel/GroupInviteConfigTest.php b/tests/src/Kernel/GroupInviteConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..39d1353421f63ee66866b8d1eeef94c9a0e2998c --- /dev/null +++ b/tests/src/Kernel/GroupInviteConfigTest.php @@ -0,0 +1,36 @@ +<?php + +namespace Drupal\Tests\ginvite\Kernel; + +use Drupal\KernelTests\Core\Entity\EntityKernelTestBase; + +/** + * Tests that all config provided by this module passes validation. + * + * @group ginvite + */ +class GroupInviteConfigTest extends EntityKernelTestBase { + + /** + * Modules to enable. + * + * @var array + */ + protected static $modules = [ + 'views', + 'group', + 'options', + 'entity', + 'flexible_permissions', + 'group', + 'ginvite', + ]; + + /** + * Tests that the module's config installs properly. + */ + public function testConfig() { + $this->installConfig(['ginvite']); + } + +} diff --git a/tests/src/Kernel/GroupInviteTest.php b/tests/src/Kernel/GroupInviteTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5822a043cb9ad845f0d1385248e121181b6f4833 --- /dev/null +++ b/tests/src/Kernel/GroupInviteTest.php @@ -0,0 +1,192 @@ +<?php + +namespace Drupal\Tests\ginvite\Kernel; + +use Drupal\group\Entity\GroupRelationship; +use Drupal\Tests\group\Kernel\GroupKernelTestBase; + +/** + * Tests the general behavior of group relationship group_invitation. + * + * @group ginvite + */ +class GroupInviteTest extends GroupKernelTestBase { + + /** + * The invitation loader. + * + * @var \Drupal\ginvite\GroupInvitationLoaderInterface + */ + protected $invitationLoader; + + /** + * The entity type manager. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + + /** + * The group we will use to test methods on. + * + * @var \Drupal\group\Entity\Group + */ + protected $group; + + /** + * The group relationship type for group membership request. + * + * @var \Drupal\group\Entity\GroupRelationshipTypeInterface + */ + protected $groupRelationshipType; + + /** + * Modules to enable. + * + * @var array + */ + protected static $modules = [ + 'ginvite' + ]; + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + + $this->installSchema('user', ['users_data']); + $this->installEntitySchema('user'); + + $this->installConfig([ + 'ginvite', + ]); + + $this->invitationLoader = $this->container->get('ginvite.invitation_loader'); + $this->entityTypeManager = $this->container->get('entity_type.manager'); + + $group_type = $this->createGroupType(); + $this->group = $this->createGroup(['type' => $group_type->id()]); + + $config = [ + 'group_cardinality' => 0, + 'entity_cardinality' => 1, + 'remove_invitation' => 0, + ]; + // Enable group membership request group relationship plugin. + $this->groupRelationshipType = $this->entityTypeManager->getStorage('group_relationship_type')->createFromPlugin($group_type, 'group_invitation', $config); + $this->groupRelationshipType->save(); + } + + /** + * Test group invitation removal with disabled settings. + */ + public function testRequestRemovalWithDisabledSettings() { + $account = $this->createUser(); + + // Add an invitation. + $this->createInvitation($this->group, $account); + + // Add the user as member. + $this->group->addMember($account); + + // Since removal is enabled we should not find any invitations. + $group_invitations = $this->invitationLoader->loadByProperties([ + 'gid' => $this->group->id(), + 'entity_id' => $account->id(), + ]); + $this->assertCount(1, $group_invitations); + } + + /** + * Test group invitation removal with enabled settings. + */ + public function testInvitationRemovalWithEnabledSettings() { + $config = [ + 'group_cardinality' => 0, + 'entity_cardinality' => 1, + 'remove_invitation' => 1, + ]; + $this->groupRelationshipType->updatePlugin($config); + $account = $this->createUser(); + + // Add an invitation. + $this->createInvitation($this->group, $account); + + // Add the user as member. + $this->group->addMember($account); + + // Since removal is enabled we should not find any invitations. + $group_invitations = $this->invitationLoader->loadByProperties([ + 'gid' => $this->group->id(), + 'entity_id' => $account->id(), + ]); + $this->assertCount(0, $group_invitations); + } + + /** + * Test autoacception of invitations. + */ + public function testInvitationAutoAcception() { + $config = [ + 'group_cardinality' => 0, + 'entity_cardinality' => 1, + 'autoaccept_invitees' => 1, + ]; + $this->groupRelationshipType->updatePlugin($config); + $account = $this->createUser(); + + // Add an invitation. + $this->createInvitation($this->group, $account); + + // It will call the same function, which is called during the login. + $account->save(); + + $member = $this->group->getMember($account); + $this->assertNotNull($member); + } + + /** + * Creates group invitation. + * + * @param \Drupal\group\Entity\Group $group + * Group. + * @param \Drupal\user\UserInterface $user + * User. + * + * @return \Drupal\group\Entity\GroupRelationship + * Group relationship invitation. + */ + private function createInvitation($group, $user) { + $group_relationship = GroupRelationship::create([ + 'type' => $this->entityTypeManager->getStorage('group_relationship_type')->getRelationshipTypeId($group->getGroupType()->id(), 'group_invitation'), + 'gid' => $group->id(), + 'entity_id' => $user->id(), + 'invitee_mail' => $user->get, + ]); + + $group_relationship->save(); + return $group_relationship; + } + + /** + * Test user removal. + */ + public function testUserRemoval() { + $account = $this->createUser(); + $user_id = $account->id(); + + // Add an invitation. + $this->createInvitation($this->group, $account); + + $account->delete(); + + // When user removed the invitations, should be removed too. + $group_invitations = $this->invitationLoader->loadByProperties([ + 'gid' => $this->group->id(), + 'entity_id' => $user_id, + ]); + $this->assertCount(0, $group_invitations); + } + +}